C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html

This commit is contained in:
Arash Partow 2015-03-28 23:21:55 +11:00
parent 73b1e4c9f3
commit 53b2977902
8 changed files with 3861 additions and 2838 deletions

1360
exprtk.hpp

File diff suppressed because it is too large Load Diff

View File

@ -24,16 +24,21 @@
template <typename T> template <typename T>
void trig_function() void trig_function()
{ {
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)"; std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)";
T x; T x;
exprtk::symbol_table<T> symbol_table;
symbol_table_t symbol_table;
symbol_table.add_variable("x",x); symbol_table.add_variable("x",x);
symbol_table.add_constants(); symbol_table.add_constants();
exprtk::expression<T> expression; expression_t expression;
expression.register_symbol_table(symbol_table); expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser; parser_t parser;
parser.compile(expression_string,expression); parser.compile(expression_string,expression);
for (x = T(-5); x <= T(+5); x += T(0.001)) for (x = T(-5); x <= T(+5); x += T(0.001))

View File

@ -24,6 +24,10 @@
template <typename T> template <typename T>
void square_wave() void square_wave()
{ {
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
std::string expr_string = "a*(4/pi)*" std::string expr_string = "a*(4/pi)*"
"((1 /1)*sin( 2*pi*f*t)+(1 /3)*sin( 6*pi*f*t)+" "((1 /1)*sin( 2*pi*f*t)+(1 /3)*sin( 6*pi*f*t)+"
" (1 /5)*sin(10*pi*f*t)+(1 /7)*sin(14*pi*f*t)+" " (1 /5)*sin(10*pi*f*t)+(1 /7)*sin(14*pi*f*t)+"
@ -39,16 +43,16 @@ void square_wave()
T t = T(0); T t = T(0);
T a = T(10); T a = T(10);
exprtk::symbol_table<T> symbol_table; symbol_table_t symbol_table;
symbol_table.add_variable("f",f); 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_variable("a",a);
symbol_table.add_constants(); symbol_table.add_constants();
exprtk::expression<T> expression; expression_t expression;
expression.register_symbol_table(symbol_table); expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser; parser_t parser;
parser.compile(expr_string,expression); parser.compile(expr_string,expression);
const T delta = (T(4) * pi) / T(1000); const T delta = (T(4) * pi) / T(1000);

View File

@ -24,19 +24,23 @@
template <typename T> template <typename T>
void polynomial() void polynomial()
{ {
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
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); T r0 = T(0);
T r1 = T(1); T r1 = T(1);
T x = T(0); T x = T(0);
exprtk::symbol_table<T> symbol_table; symbol_table_t symbol_table;
symbol_table.add_variable("x",x); symbol_table.add_variable("x",x);
exprtk::expression<T> expression; expression_t expression;
expression.register_symbol_table(symbol_table); expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser; parser_t parser;
parser.compile(expression_string,expression); parser.compile(expression_string,expression);
const T delta = T(1.0 / 100.0); const T delta = T(1.0 / 100.0);

View File

@ -37,13 +37,17 @@ struct myfunc : public exprtk::ifunction<T>
template <typename T> template <typename T>
void custom_function() void custom_function()
{ {
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
std::string expression_string = "myfunc(sin(x * pi),y / 2)"; std::string expression_string = "myfunc(sin(x * pi),y / 2)";
T x = T(1); T x = T(1);
T y = T(2); T y = T(2);
myfunc<T> mf; myfunc<T> mf;
exprtk::symbol_table<T> symbol_table; symbol_table_t symbol_table;
symbol_table.add_variable("x",x); symbol_table.add_variable("x",x);
symbol_table.add_variable("y",y); symbol_table.add_variable("y",y);
symbol_table.add_function("myfunc",mf); symbol_table.add_function("myfunc",mf);
@ -52,7 +56,7 @@ void custom_function()
expression_t expression; expression_t expression;
expression.register_symbol_table(symbol_table); expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser; parser_t parser;
parser.compile(expression_string,expression); parser.compile(expression_string,expression);
T result = expression.value(); T result = expression.value();

View File

@ -24,10 +24,13 @@
template <typename T> template <typename T>
void logic() void logic()
{ {
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
std::string expression_string = "not(A and B) or C"; std::string expression_string = "not(A and B) or C";
exprtk::symbol_table<T> symbol_table; symbol_table_t symbol_table;
symbol_table.create_variable("A"); symbol_table.create_variable("A");
symbol_table.create_variable("B"); symbol_table.create_variable("B");
symbol_table.create_variable("C"); symbol_table.create_variable("C");
@ -35,7 +38,7 @@ void logic()
expression_t expression; expression_t expression;
expression.register_symbol_table(symbol_table); expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser; parser_t parser;
parser.compile(expression_string,expression); parser.compile(expression_string,expression);
printf(" # | A | B | C | %s\n" printf(" # | A | B | C | %s\n"

View File

@ -2287,7 +2287,8 @@ inline bool run_test02()
parser.error().c_str(), parser.error().c_str(),
test.expr.c_str()); test.expr.c_str());
return false; result = false;
continue;
} }
} }
@ -2303,7 +2304,9 @@ inline bool run_test02()
test.expr.c_str(), test.expr.c_str(),
(double)test.result, (double)test.result,
(double)expr_result); (double)expr_result);
result = false; result = false;
continue;
} }
} }
@ -2347,18 +2350,21 @@ inline bool run_test02()
{ {
printf("run_test02() - Evaluation Error [2]: Expression: [%s]\tExpected: True\n", printf("run_test02() - Evaluation Error [2]: Expression: [%s]\tExpected: True\n",
expression_str.c_str()); expression_str.c_str());
return false; return false;
} }
else if ("234567" != s0) else if ("234567" != s0)
{ {
printf("run_test02() - Evaluation Error [2]: Expression: [%s]\tInvalid value for s0\n", printf("run_test02() - Evaluation Error [2]: Expression: [%s]\tInvalid value for s0\n",
expression_str.c_str()); expression_str.c_str());
return false; return false;
} }
else if ("xyz" != s1) else if ("xyz" != s1)
{ {
printf("run_test02() - Evaluation Error [2]: Expression: [%s]\tInvalid value for s1\n", printf("run_test02() - Evaluation Error [2]: Expression: [%s]\tInvalid value for s1\n",
expression_str.c_str()); expression_str.c_str());
return false; return false;
} }
} }
@ -2406,7 +2412,8 @@ inline bool run_test03()
for (std::size_t r = 0; r < rounds; ++r) for (std::size_t r = 0; r < rounds; ++r)
{ {
exprtk::symbol_table<T> symbol_table; exprtk::symbol_table<T> symbol_table_0;
exprtk::symbol_table<T> symbol_table_1;
exprtk::expression<T> expression; exprtk::expression<T> expression;
std::vector<T> v; std::vector<T> v;
@ -2415,21 +2422,28 @@ inline bool run_test03()
for (std::size_t i = 0; i < variable_list_size; ++i) for (std::size_t i = 0; i < variable_list_size; ++i)
{ {
v[i] = T(i); v[i] = T(i);
symbol_table.add_variable(variable_list[i],v[i]); if (i & 1)
symbol_table_0.add_variable(variable_list[i],v[i]);
else
symbol_table_1.add_variable(variable_list[i],v[i]);
} }
if (variable_list_size != symbol_table.variable_count()) std::size_t total_symbol_count = symbol_table_0.variable_count() +
symbol_table_1.variable_count();
if (variable_list_size != total_symbol_count)
{ {
printf("run_test03() - Error - Invalid number of variables in symbol_table! Expected: %d got: %d\n", printf("run_test03() - Error - Invalid number of variables in symbol_table! Expected: %d got: %d\n",
static_cast<unsigned int>(variable_list_size), static_cast<unsigned int>(variable_list_size),
static_cast<unsigned int>(symbol_table.variable_count())); static_cast<unsigned int>(total_symbol_count));
return false; return false;
} }
symbol_table.add_constants(); symbol_table_0.add_constants();
expression.register_symbol_table(symbol_table); expression.register_symbol_table(symbol_table_0);
expression.register_symbol_table(symbol_table_1);
{ {
exprtk::parser<T> parser; exprtk::parser<T> parser;
@ -3750,6 +3764,21 @@ inline bool run_test10()
"~{ var x := 1 } + ~{ var x := 2 } == 3", "~{ var x := 1 } + ~{ var x := 2 } == 3",
"(~{ var x := 1 } + ~{ var x := 2 }) == (~{ var x := 2 } + ~{ var x := 1 })", "(~{ var x := 1 } + ~{ var x := 2 }) == (~{ var x := 2 } + ~{ var x := 1 })",
"(~{ var x := 1 } + ~{ var x := 2 } + ~{~{ var x := 1 } + ~{ var x := 2 }}) == 6", "(~{ var x := 1 } + ~{ var x := 2 } + ~{~{ var x := 1 } + ~{ var x := 2 }}) == 6",
"(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6",
"(~{ var x := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6",
"(~{ var x[1] := [1] } + ~{ var x := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6",
"(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x := [1] } + ~{ var x[1] := [2] }}) == 6",
"(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x := [2] }}) == 6",
"(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6",
"(~{~{ var x := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6",
"(~{~{ var x[1] := [1] } + ~{ var x := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6",
"(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x := [1] } + ~{ var x[1] := [2] }) == 6",
"(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x := [2] }) == 6",
"(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6",
"(~{~{ var x := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6",
"(~{~{ var x[1] := [1] }} + ~{ var x := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6",
"(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x := [2] } + ~{{ var x[1] := [2] }}) == 6",
"(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x := [2] }}) == 6",
"(~{ var x[3] := [1] } + ~{ var x[6] := {6,5,4,3,2,1}}) == 7", "(~{ var x[3] := [1] } + ~{ var x[6] := {6,5,4,3,2,1}}) == 7",
"(~{ var x[6] := {6,5,4,3,2,1} } + ~{ var x := 1 }) == 7", "(~{ var x[6] := {6,5,4,3,2,1} } + ~{ var x := 1 }) == 7",
"(~{ var x := 1 } + ~{ var x[6] := {6,5,4,3,2,1} }) == 7", "(~{ var x := 1 } + ~{ var x[6] := {6,5,4,3,2,1} }) == 7",
@ -3885,7 +3914,12 @@ inline bool run_test10()
"+ ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; j += 1) " "+ ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; j += 1) "
" { var y := 3; var v2[3] := {1,2,3}; if ((i + j + y + x + abs(v0[i % v0[]] - " " { var y := 3; var v2[3] := {1,2,3}; if ((i + j + y + x + abs(v0[i % v0[]] - "
"v2[j % v2[]])) < 6) { var v3[3] := {1,2,3}; y += x / v3[j % v3[]]; " "v2[j % v2[]])) < 6) { var v3[3] := {1,2,3}; y += x / v3[j % v3[]]; "
"continue; } else break[i + j]; } } } ) == 18 " "continue; } else break[i + j]; } } } ) == 18 ",
"12 == (if (1 > 2) { var x:= 2; } else { var x[3] := {7,2,3}; sum(x); })",
"12 == (if (1 < 2) { var x[3] := {7,2,3}; sum(x); } else { var x:= 2; })",
"12 == (if (1 > 2) { var x:= 2; } else { var x[3] := {7,2,3}; sum(x); })",
"12 == (if (1 < 2) { var x[3] := {7,2,3}; sum(x); } else { var x:= 2; })"
}; };
const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
@ -3916,7 +3950,8 @@ inline bool run_test10()
parser.error().c_str(), parser.error().c_str(),
expression_list[i].c_str()); expression_list[i].c_str());
return false; failed = true;
continue;
} }
} }
@ -3926,6 +3961,7 @@ inline bool run_test10()
{ {
printf("run_test10() - swaps evaluation error Expression: %s\n", printf("run_test10() - swaps evaluation error Expression: %s\n",
expression_list[i].c_str()); expression_list[i].c_str());
failed = true; failed = true;
} }
} }
@ -4142,7 +4178,10 @@ struct cosine_deg : public exprtk::ifunction<T>
template <typename T> template <typename T>
inline bool run_test13() inline bool run_test13()
{ {
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
static const std::string expression_string[] = static const std::string expression_string[] =
{ {
"equal(sin(30),0.5) ", "equal(sin(30),0.5) ",
@ -4153,25 +4192,38 @@ inline bool run_test13()
"equal(cos(y_deg),0.5) ", "equal(cos(y_deg),0.5) ",
"equal(sin(y_deg),sqrt(3)/2) ", "equal(sin(y_deg),sqrt(3)/2) ",
"equal(cos(x_deg),sqrt(3)/2) ", "equal(cos(x_deg),sqrt(3)/2) ",
"equal(sin(30) + sin(30),1.0) ",
"equal(cos(60) + cos(60),1.0) ",
"equal(sin(60) + sin(60),sqrt(3)) ",
"equal(cos(30) + cos(30),sqrt(3)) ",
"equal(sin(x_deg) + sin(x_deg),1.0) ",
"equal(cos(y_deg) + cos(y_deg),1.0) ",
"equal(sin(y_deg) + sin(y_deg),sqrt(3))",
"equal(cos(x_deg) + cos(x_deg),sqrt(3))"
}; };
static const std::size_t expression_string_size = sizeof(expression_string) / sizeof(std::string); static const std::size_t expression_string_size = sizeof(expression_string) / sizeof(std::string);
{
T x_deg = T(30); T x_deg = T(30);
T y_deg = T(60); T y_deg = T(60);
sine_deg <T> sine; sine_deg <T> sine;
cosine_deg<T> cosine; cosine_deg<T> cosine;
exprtk::symbol_table<T> symbol_table; symbol_table_t symbol_table_0;
symbol_table_t symbol_table_1;
symbol_table.add_variable("x_deg",x_deg); symbol_table_0.add_variable("x_deg",x_deg);
symbol_table.add_variable("y_deg",y_deg); symbol_table_1.add_variable("y_deg",y_deg);
symbol_table.add_function("sine_deg",sine); symbol_table_0.add_function( "sine_deg", sine);
symbol_table.add_function("cosine_deg",cosine); symbol_table_1.add_function("cosine_deg", cosine);
expression_t expression; expression_t expression;
expression.register_symbol_table(symbol_table);
expression.register_symbol_table(symbol_table_0);
expression.register_symbol_table(symbol_table_1);
static const std::size_t rounds = 100; static const std::size_t rounds = 100;
@ -4182,14 +4234,14 @@ inline bool run_test13()
const std::string& expr_str = expression_string[j]; const std::string& expr_str = expression_string[j];
{ {
exprtk::parser<T> parser; parser_t parser;
parser.replace_symbol("sin", "sine_deg"); parser.replace_symbol("sin", "sine_deg");
parser.replace_symbol("cos", "cosine_deg"); parser.replace_symbol("cos", "cosine_deg");
if (!parser.compile(expr_str,expression)) if (!parser.compile(expr_str,expression))
{ {
printf("run_test13() - Error: %s Expression: %s\n", printf("run_test13() - Error: %s Expression: %s [1]\n",
parser.error().c_str(), parser.error().c_str(),
expr_str.c_str()); expr_str.c_str());
@ -4199,11 +4251,69 @@ inline bool run_test13()
if (T(1) != expression.value()) if (T(1) != expression.value())
{ {
printf("run_test13() - Error in evaluation! Expression: %s\n",expr_str.c_str()); printf("run_test13() - Error in evaluation! Expression: %s [1]\n",expr_str.c_str());
return false; return false;
} }
} }
} }
}
{
T x_deg = T(30);
T y_deg = T(60);
sine_deg <T> sine;
cosine_deg<T> cosine;
symbol_table_t symbol_table_0;
symbol_table_t symbol_table_1;
symbol_table_0.add_variable("x_deg",x_deg);
symbol_table_1.add_variable("y_deg",y_deg);
symbol_table_0.add_reserved_function("sin", sine);
symbol_table_1.add_reserved_function("cos",cosine);
expression_t expression;
expression.register_symbol_table(symbol_table_0);
expression.register_symbol_table(symbol_table_1);
static const std::size_t rounds = 100;
for (std::size_t i = 0; i < rounds; ++i)
{
for (std::size_t j = 0; j < expression_string_size; ++j)
{
const std::string& expr_str = expression_string[j];
{
typedef typename parser_t::settings_store settings_t;
parser_t parser;
parser.settings()
.disable_base_function(settings_t::e_bf_sin)
.disable_base_function(settings_t::e_bf_cos);
if (!parser.compile(expr_str,expression))
{
printf("run_test13() - Error: %s Expression: %s [2]\n",
parser.error().c_str(),
expr_str.c_str());
return false;
}
}
if (T(1) != expression.value())
{
printf("run_test13() - Error in evaluation! Expression: %s [2]\n",expr_str.c_str());
return false;
}
}
}
}
return true; return true;
} }
@ -6397,11 +6507,18 @@ inline bool run_test20()
for (std::size_t i = 0; i < 100; ++i) for (std::size_t i = 0; i < 100; ++i)
{ {
exprtk::symbol_table<T> symbol_table; exprtk::symbol_table<T> symbol_table0;
symbol_table.add_constants(); exprtk::symbol_table<T> symbol_table1;
exprtk::symbol_table<T> symbol_table2;
exprtk::symbol_table<T> symbol_table3;
symbol_table0.add_constants();
expression_t expression; expression_t expression;
expression.register_symbol_table(symbol_table); expression.register_symbol_table(symbol_table0);
expression.register_symbol_table(symbol_table1);
expression.register_symbol_table(symbol_table2);
expression.register_symbol_table(symbol_table3);
exprtk::parser<T> parser; exprtk::parser<T> parser;

View File

@ -442,7 +442,7 @@ of C++ compilers:
| | eg: | | | eg: |
| | 1. 'abc'[] == 3 | | | 1. 'abc'[] == 3 |
| | 2. var max_str_length := max(s0[],s1[],s2[],s3[]) | | | 2. var max_str_length := max(s0[],s1[],s2[],s3[]) |
| | 3. ('abc' + 'xyz')[] == 3 | | | 3. ('abc' + 'xyz')[] == 6 |
| | 4. (('abc' + 'xyz')[1:4])[] == 4 | | | 4. (('abc' + 'xyz')[1:4])[] == 4 |
+----------+---------------------------------------------------------+ +----------+---------------------------------------------------------+
@ -604,7 +604,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 specialize the ExprTk components (float, double, long
double MPFR et al). double, MPFR et al).
(2) Vector Type (2) Vector Type
@ -628,9 +628,9 @@ There are three primary components, that are specialized 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:
1. Symbol Table exprtk::symbol_table<NumericType> (1) Symbol Table exprtk::symbol_table<NumericType>
2. Expression exprtk::expression<NumericType> (2) Expression exprtk::expression<NumericType>
3. Parser exprtk::parser<NumericType> (3) Parser exprtk::parser<NumericType>
(1) Symbol Table (1) Symbol Table
@ -736,12 +736,12 @@ Expression: z := (x + y^-2.345) * sin(pi / min(w - 7.3,v))
(3) Parser (3) Parser
A structure which takes as input a string representation of an A structure which takes as input a string representation of an
expression and attempts to compile said input with the result expression and attempts to compile said input with the result being an
being an instance of Expression. If an error is encountered instance of Expression. If an error is encountered during the
during the compilation process, the parser will stop compiling compilation process, the parser will stop compiling and return an
and return an error status code, with a more detailed error status code, with a more detailed description of the error(s)
description of the error(s) and its location within the input and its location within the input provided by the 'get_error'
provided by the 'get_error' interface. interface.
@ -751,11 +751,11 @@ options to be used during the compilation process of expressions.
An example instantiation of exprtk::parser where only the joiner, An example instantiation of exprtk::parser where only the joiner,
commutative and strength reduction options are enabled is as follows: commutative and strength reduction options are enabled is as follows:
typedef exprtk::parser<NumericType> parser_t; typedef exprtk::parser<NumericType>::settings_t settings_t;
std::size_t compile_options = parser_t::e_joiner + std::size_t compile_options = settings_t::e_joiner +
parser_t::e_commutative_check + settings_t::e_commutative_check +
parser_t::e_strength_reduction; settings_t::e_strength_reduction;
parser_t parser(compile_options); parser_t parser(compile_options);
@ -763,6 +763,15 @@ commutative and strength reduction options are enabled is as follows:
Currently seven types of compile time options are supported, and Currently seven types of compile time options are supported, and
enabled by default. The options and their explanations are as follows: enabled by default. The options and their explanations are as follows:
(1) Replacer
(2) Joiner
(3) Numeric Check
(4) Bracket Check
(5) Sequence Check
(6) Commutative Check
(7) Strength Reduction Check
(1) Replacer (e_replacer) (1) Replacer (e_replacer)
Enable replacement of specific tokens with other tokens. For example Enable replacement of specific tokens with other tokens. For example
the token "true" of type symbol will be replaced with the numeric the token "true" of type symbol will be replaced with the numeric
@ -1084,6 +1093,7 @@ not a vector but rather a single value.
var x[3] := { 1, 2, 3 }; var x[3] := { 1, 2, 3 };
sum(x) == 6
sum(1 + 2x) == 15 sum(1 + 2x) == 15
avg(3x + 1) == 7 avg(3x + 1) == 7
min(1 / x) == (1 / 3) min(1 / x) == (1 / 3)
@ -1095,7 +1105,7 @@ not a vector but rather a single value.
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 utilized 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. Function can take in 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
type. type.
@ -1103,7 +1113,7 @@ During expression compilation when required the reference to the
function will be obtained from the associated symbol_table and be function will be obtained from the associated symbol_table and be
embedded into the expression. embedded into the expression.
There are two types of function interface: There are five types of function interface:
(1) ifunction (1) ifunction
(2) ivararg_function (2) ivararg_function
@ -1323,7 +1333,7 @@ situations such as concatenation and equality operations.
String <-- function(i_0, i_1, i_2....., i_N) String <-- function(i_0, i_1, i_2....., i_N)
The following example defines an generic function named 'toupper' with The following example defines a generic function named 'toupper' with
the string return type function operator being explicitly overridden: the string return type function operator being explicitly overridden:
template <typename T> template <typename T>
@ -1376,10 +1386,10 @@ is done:
symbol_table_t::e_ft_strfunc); symbol_table_t::e_ft_strfunc);
Note: There are two further refinements to the type checking facility Note: Two further refinements to the type checking facility are the
are the possibilities of a variable number of common types which can possibilities of a variable number of common types which can be
be accomplished by using a wildcard '*' and a special 'any type' which accomplished by using a wildcard '*' and a special 'any type' which is
is done using the '?' character. It should be noted that the wildcard done using the '?' character. It should be noted that the wildcard
operator is associated with the previous type in the sequence and operator is associated with the previous type in the sequence and
implies one or more of that type. implies one or more of that type.
@ -1507,7 +1517,7 @@ symbol table.
.expression("1 + cos(x * y) / z;")); .expression("1 + cos(x * y) / z;"));
(4) Using Functions In Expressions (6) Using Functions In Expressions
For the above denoted custom and composited functions to be used in an 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 expression, an instance of each function needs to be registered with a
symbol_table that has been associated with the expression instance. symbol_table that has been associated with the expression instance.
@ -1558,7 +1568,7 @@ The following demonstrates how all the pieces are put together:
expression.value(); expression.value();
(5) Function Side-Effects (7) Function Side-Effects
All function calls are assumed to have side-effects by default. This All function calls are assumed to have side-effects by default. This
assumption implicitly disables constant folding optimisations when all assumption implicitly disables constant folding optimisations when all
parameters being passed to the function are deduced as being constants parameters being passed to the function are deduced as being constants
@ -1580,7 +1590,7 @@ to the constructor to denote the lack of side-effects.
}; };
(6) Zero Parameter Functions (8) Zero Parameter Functions
When either an ifunction or ivararg_function derived type is defined When either an ifunction or ivararg_function derived type is defined
with zero number of parameters, there are two calling conventions with zero number of parameters, there are two calling conventions
within expressions that are allowed. For a function named 'foo' with within expressions that are allowed. For a function named 'foo' with
@ -1676,11 +1686,11 @@ within an expression. The following are example expressions and their
associated assignments: associated assignments:
Assignments Expression Assignments Expression
1. x x := y + z (1) x x := y + z
2. x, y x += y += z (2) x, y x += y += z
3. x, y, z x := y += sin(z := w + 2) (3) x, y, z x := y += sin(z := w + 2)
4. z, w if (x > y, z := x + 2, w := 'A String') (4) z, w if (x > y, z := x + 2, w := 'A String')
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 'z' and 'w' are denoted as being
@ -1835,7 +1845,7 @@ via the 'unknown symbol resolver' mechanism.
[18 - EXPRTK NOTES] [18 - EXPRTK NOTES]
The following is a list of facts and suggestions one may want to take The following is a list of facts and suggestions one may want to take
into account when using Exprtk: into account when using ExprTk:
(00) Precision and performance of expression evaluations are the (00) Precision and performance of expression evaluations are the
dominant principles of the ExprTk library. dominant principles of the ExprTk library.
@ -1935,38 +1945,38 @@ into account when using Exprtk:
into account. Specifically the 'compile' method of the parser into account. Specifically the 'compile' method of the parser
and the 'add_xxx' set of methods of the symbol_table as they and the 'add_xxx' set of methods of the symbol_table as they
denote either the success or failure state of the invoked call. denote either the success or failure state of the invoked call.
Cointinued processing from a failed state without having first Continued processing from a failed state without having first
rectified the underlying issue will in turn result in further rectified the underlying issue will in turn result in further
failures and undefined behaviours. failures and undefined behaviours.
(25) The following are examples of compliant floating point value (25) The following are examples of compliant floating point value
representations: representations:
(a) 12345 (e) -123.456 (1) 12345 (5) -123.456
(b) +123.456e+12 (f) 123.456E-12 (2) +123.456e+12 (6) 123.456E-12
(c) +012.045e+07 (g) .1234 (3) +012.045e+07 (7) .1234
(d) 123.456f (h) -321.654E+3L (4) 123.456f (8) -321.654E+3L
(26) Expressions may contain any of the following comment styles: (26) Expressions may contain any of the following comment styles:
1. // .... \n (1) // .... \n
2. # .... \n (2) # .... \n
3. /* .... */ (3) /* .... */
(27) The 'null' value type is a special non-zero type that (27) The 'null' value type is a special non-zero type that
incorporates specific semantics when undergoing operations with incorporates specific semantics when undergoing operations with
the standard numeric type. The following is a list of type and the standard numeric type. The following is a list of type and
boolean results associated with the use of 'null': boolean results associated with the use of 'null':
1. null +,-,*,/,% x --> x (1) null +,-,*,/,% x --> x
2. x +,-,*,/,% null --> x (2) x +,-,*,/,% null --> x
3. null +,-,*,/,% null --> null (3) null +,-,*,/,% null --> null
4. null == null --> true (4) null == null --> true
5. null == x --> true (5) null == x --> true
6. x == null --> true (6) x == null --> true
7. x != null --> false (7) x != null --> false
8. null != null --> false (8) null != null --> false
9. null != x --> false (9) null != x --> false
(28) The following is a list of reserved words and symbols used by (28) The following is a list of reserved words and symbols used by
ExprTk. Attempting to add a variable or custom function to a ExprTk. Attempting to add a variable or custom function to a
@ -1979,9 +1989,9 @@ into account when using Exprtk:
expm1, false, floor, for, frac, grad2deg, hypot, iclamp, if, expm1, false, floor, for, frac, grad2deg, hypot, iclamp, if,
ilike, in, inrange, in, like, log, log10, log1p, log2, logn, ilike, in, inrange, in, like, log, log10, log1p, log2, logn,
mand, max, min, mod, mor, mul, nand, ncdf, nor, not, mand, max, min, mod, mor, mul, nand, ncdf, nor, not,
not_equal, not, null, or, pow, rad2deg, repeat, root, not_equal, not, null, or, pow, rad2deg, repeat, return,
roundn, round, sec, sgn, shl, shr, sinc, sinh, sin, sqrt, root, roundn, round, sec, sgn, shl, shr, sinc, sinh, sin,
sum, swap, switch, tanh, tan, true, trunc, until, var, sqrt, sum, swap, switch, tanh, tan, true, trunc, until, var,
while, xnor, xor, xor while, xnor, xor, xor
(29) Every valid ExprTk statement is a "value returning" expression. (29) Every valid ExprTk statement is a "value returning" expression.