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

This commit is contained in:
Arash Partow 2014-04-19 21:10:15 +10:00
parent f6a56d8048
commit afc7c074fa
6 changed files with 374 additions and 235 deletions

View File

@ -34,6 +34,7 @@ BUILD_LIST+=exprtk_simple_example_07
BUILD_LIST+=exprtk_simple_example_08
BUILD_LIST+=exprtk_simple_example_09
BUILD_LIST+=exprtk_simple_example_10
BUILD_LIST+=exprtk_simple_example_11
all: $(BUILD_LIST)
@ -73,6 +74,9 @@ exprtk_simple_example_09: exprtk_simple_example_09.cpp exprtk.hpp
exprtk_simple_example_10: exprtk_simple_example_10.cpp exprtk.hpp
$(COMPILER) $(OPTIONS) exprtk_simple_example_10 exprtk_simple_example_10.cpp $(LINKER_OPT)
exprtk_simple_example_11: exprtk_simple_example_11.cpp exprtk.hpp
$(COMPILER) $(OPTIONS) exprtk_simple_example_11 exprtk_simple_example_11.cpp $(LINKER_OPT)
pgo: exprtk_test.cpp exprtk_benchmark.cpp exprtk.hpp
$(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-generate -o exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT)
./exprtk_benchmark
@ -91,6 +95,7 @@ strip_bin:
strip -s exprtk_simple_example_08
strip -s exprtk_simple_example_09
strip -s exprtk_simple_example_10
strip -s exprtk_simple_example_11
valgrind_check:
valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_test
@ -105,6 +110,7 @@ valgrind_check:
valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_08
valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_09
valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_10
valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_11
clean:
rm -f core.* *~ *.o *.bak *stackdump gmon.out *.gcda *.gcno *.gcnor *.gch

View File

@ -32,7 +32,9 @@ void square_wave()
" (1/17)*sin(34*pi*f*t)+(1/19)*sin(38*pi*f*t)+"
" (1/21)*sin(42*pi*f*t)+(1/23)*sin(46*pi*f*t)+"
" (1/25)*sin(50*pi*f*t)+(1/27)*sin(54*pi*f*t))";
static const T pi = T(3.14159265358979323846);
T f = pi / T(10);
T t = T(0);
T a = T(10);
@ -50,6 +52,7 @@ void square_wave()
parser.compile(expr_string,expression);
const T delta = (T(4) * pi) / T(1000);
for (t = (T(-2) * pi); t <= (T(+2) * pi); t += delta)
{
T result = expression.value();

View File

@ -38,7 +38,7 @@ void fibonacci()
" case x == 0 : 0; "
" case x == 1 : 1; "
" default : "
" while ((x := (x - 1)) > 0)"
" while ((x -= 1) > 0) "
" { "
" w := z; "
" z := z + y; "

View File

@ -0,0 +1,67 @@
/*
**************************************************************
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 11 *
* Author: Arash Partow (1999-2014) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
* Free use of the Mathematical Expression Toolkit Library is *
* permitted under the guidelines and in accordance with the *
* most current version of the Common Public License. *
* http://www.opensource.org/licenses/cpl1.0.php *
* *
**************************************************************
*/
#include <cstdio>
#include <string>
#include "exprtk.hpp"
template<typename T>
void square_wave2()
{
std::string expr_string = " r := 0; "
" for(i := 0; i < 1000; i += 1) "
" { "
" r += (1/(2i+1))*sin((4i+2)*pi*f*t); "
" }; "
" r *= a*(4 / pi); ";
static const T pi = T(3.14159265358979323846);
T f = pi / T(10);
T t = T(0);
T a = T(10);
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable("f",f);
symbol_table.add_variable("t",t);
symbol_table.add_variable("a",a);
symbol_table.add_constants();
exprtk::expression<T> expression;
expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser;
parser.enable_unknown_symbol_resolver();
parser.compile(expr_string,expression);
const T delta = (T(4) * pi) / T(1000);
for (t = (T(-2) * pi); t <= (T(+2) * pi); t += delta)
{
T result = expression.value();
printf("%19.15f\t%19.15f\n",t,result);
}
}
int main()
{
square_wave2<double>();
return 0;
}

View File

@ -1511,6 +1511,17 @@ inline bool run_test01()
test_xy<T>("(x < (y + y) ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)),
test_xy<T>("((x + x) < y ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)),
test_xy<T>("((x + x) < (y + y) ? 7 : 9) == 7",T(1.0),T(3.0),T( 1.0)),
test_xy<T>("(x += 2 ) == 3 " ,T(1),T(3),T(1)),
test_xy<T>("(x += 2y) == 7 " ,T(1),T(3),T(1)),
test_xy<T>("(x -= 2 ) == -1 " ,T(1),T(3),T(1)),
test_xy<T>("(x -= 2y) == -5 " ,T(1),T(3),T(1)),
test_xy<T>("(x *= 2 ) == 2 " ,T(1),T(3),T(1)),
test_xy<T>("(x *= 2y) == 6 " ,T(1),T(3),T(1)),
test_xy<T>("(x /= 2 ) == (1/2)" ,T(1),T(3),T(1)),
test_xy<T>("(x /= 2y) == (1/6)" ,T(1),T(3),T(1)),
test_xy<T>("for(i := 0; (i < 10);) { i += 1; }; x;" ,T(1),T(20),T( 1)),
test_xy<T>("for(i := 0; (i < 10) and (i != y); i+=2) { x += i; }; x;" ,T(1),T(20),T(21)),
test_xy<T>("for(i := 0; (i < 10) and (i != y);) { x += i; i+=2; }; x;",T(1),T(20),T(21))
};
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_xy<T>);
@ -1524,9 +1535,12 @@ inline bool run_test01()
{
test_xy<T>& test = const_cast<test_xy<T>&>(test_list[i]);
T x = test.x;
T y = test.y;
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable("x",test.x);
symbol_table.add_variable("y",test.y);
symbol_table.add_variable("x",x);
symbol_table.add_variable("y",y);
exprtk::expression<T> expression;
expression.register_symbol_table(symbol_table);
@ -2056,6 +2070,7 @@ inline bool run_test03()
expression.register_symbol_table(symbol_table);
{
exprtk::parser<T> parser;
if (!parser.compile(expression_string,expression))
@ -2065,6 +2080,7 @@ inline bool run_test03()
expression_string.c_str());
return false;
}
}
expression.value();
}
@ -2153,9 +2169,11 @@ inline bool run_test05()
for (std::size_t i = 0; i < expression_count; ++i)
{
expression_t e;
exprtk::parser<T> parser;
e.register_symbol_table(symbol_table);
{
exprtk::parser<T> parser;
if (!parser.compile(expression_string,e))
{
printf("run_test05() - Error: %s Expression: %s\n",
@ -2163,6 +2181,7 @@ inline bool run_test05()
expression_string.c_str());
return false;
}
}
expression_list.push_back(e);
}
@ -2214,6 +2233,7 @@ inline bool run_test06()
expression_t expression;
expression.register_symbol_table(symbol_table);
{
exprtk::parser<T> parser;
if (!parser.compile(expression_string,expression))
@ -2223,6 +2243,7 @@ inline bool run_test06()
expression_string.c_str());
return false;
}
}
T total_area1 = exprtk::integrate(expression,x,T(-1),T(1));
T total_area2 = exprtk::integrate(expression,"x",T(-1),T(1));
@ -2259,6 +2280,7 @@ inline bool run_test07()
expression_t expression;
expression.register_symbol_table(symbol_table);
{
exprtk::parser<T> parser;
if (!parser.compile(expression_string,expression))
@ -2269,6 +2291,7 @@ inline bool run_test07()
return false;
}
}
for (x = T(-200); x < T(200); x += T(0.0001))
{
@ -2507,6 +2530,7 @@ inline bool run_test08()
expression_t expression;
expression.register_symbol_table(symbol_table);
{
exprtk::parser<T> parser;
if (!parser.compile(expr_str[j],expression))
@ -2516,6 +2540,7 @@ inline bool run_test08()
expr_str[j].c_str());
return false;
}
}
expression.value();
}
@ -2585,6 +2610,7 @@ inline bool run_test09()
expression_t expression;
expression.register_symbol_table(symbol_table);
{
exprtk::parser<T> parser;
if (!parser.compile(expression_string,expression))
@ -2594,6 +2620,7 @@ inline bool run_test09()
expression_string.c_str());
return false;
}
}
const T pi = T(3.141592653589793238462);
@ -4215,41 +4242,33 @@ inline bool run_test19()
symbol_table.add_constants();
symbol_table.add_variable("x",x);
std::string expression_str1 = "is_prime1(x)";
std::string expression_str2 = "is_prime2(x)";
std::string expression_str3 = "is_prime3(x)";
const std::string expression_str[] = {
"is_prime1(x)",
"is_prime2(x)",
"is_prime3(x)"
};
expression_t expression1;
expression_t expression2;
expression_t expression3;
expression1.register_symbol_table(symbol_table);
expression2.register_symbol_table(symbol_table);
expression3.register_symbol_table(symbol_table);
const std::size_t expression_count = sizeof(expression_str) / sizeof(std::string);
std::vector<expression_t> expression_list;
for (std::size_t i = 0; i < expression_count; ++i)
{
parser_t parser;
if (!parser.compile(expression_str1,expression1))
expression_t expression;
expression.register_symbol_table(symbol_table);
if (!parser.compile(expression_str[i],expression))
{
printf("run_test19() - Error: %s Expression1: %s\n",
printf("run_test19() - Error: %s Expression%d: %s\n",
parser.error().c_str(),
expression_str1.c_str());
static_cast<unsigned int>(i),
expression_str[i].c_str());
return false;
}
if (!parser.compile(expression_str2,expression2))
{
printf("run_test19() - Error: %s Expression2: %s\n",
parser.error().c_str(),
expression_str2.c_str());
return false;
}
if (!parser.compile(expression_str3,expression3))
{
printf("run_test19() - Error: %s Expression3: %s\n",
parser.error().c_str(),
expression_str3.c_str());
return false;
else
expression_list.push_back(expression);
}
bool failure = false;
@ -4276,33 +4295,50 @@ inline bool run_test19()
};
const std::size_t prime_list_size = sizeof(prime_list) / sizeof(std::size_t);
for (std::size_t i = 0; i < prime_list_size; ++i)
for (std::size_t i = 0; (i < prime_list_size) && (!failure); ++i)
{
x = prime_list[i];
T result1 = expression1.value();
T result2 = expression2.value();
T result3 = expression3.value();
std::vector<T> result(expression_count,T(0));
if ((result1 != result2) || (result1 != result3))
for (std::size_t j = 0; j < expression_list.size(); ++j)
{
printf("run_test19() - Error in evaluation! (3) Results don't match! Prime: %d "
"Expression1: %s Expression2: %s Expression3: %s\n",
static_cast<unsigned int>(prime_list[i]),
expression_str1.c_str(),
expression_str2.c_str(),
expression_str3.c_str());
failure = true;
result[j] = expression_list[j].value();
}
if (T(1) != result1)
for (std::size_t j = 1; j < expression_list.size(); ++j)
{
if (result[j] != result[0])
{
printf("run_test19() - Error in evaluation! (3) Prime: %d "
"Expression1: %s Expression2: %s Expression3: %s\n",
static_cast<unsigned int>(prime_list[i]),
expression_str1.c_str(),
expression_str2.c_str(),
expression_str3.c_str());
failure = true;
break;
}
}
if (failure)
{
printf("run_test19() - Error in evaluation! (3) Results don't match! Prime: %d\n",
static_cast<unsigned int>(prime_list[i]));
for (std::size_t j = 0; j < expression_list.size(); ++j)
{
printf("Expression[%02d]: %s = %d\n",
static_cast<unsigned int>(j),
expression_str[j].c_str(),
static_cast<unsigned int>(result[j]));
}
}
else if (T(1) != expression_list[0].value())
{
printf("run_test19() - Error in evaluation! (4) Results don't match! Prime: %d\n",
static_cast<unsigned int>(prime_list[i]));
for (std::size_t j = 0; j < expression_list.size(); ++j)
{
printf("Expression[%02d]: %s = %d\n",
static_cast<unsigned int>(j),
expression_str[j].c_str(),
static_cast<unsigned int>(result[j]));
}
}
}
@ -4338,7 +4374,8 @@ inline bool run_test19()
"{ "
" case x == 0 : 0; "
" case x == 1 : 1; "
" default : while ((x := (x - 1)) > 0)"
" default : "
" while ((x := (x - 1)) > 0)"
" { "
" w := z; "
" z := z + y; "
@ -4359,7 +4396,8 @@ inline bool run_test19()
"{ "
" case x == 0 : 0; "
" case x == 1 : 1; "
" default : repeat "
" default : "
" repeat "
" w := z; "
" z := z + y; "
" y := w; "
@ -4374,56 +4412,48 @@ inline bool run_test19()
"fibonacci_impl4(x,0,1,0)",
"x");
compositor
.add("fibonacci5",
"if ((x == 0) or (x == 1)) "
" x; "
"else "
" fibonacci5(x - 1) + fibonacci5(x - 2); ",
"x");
symbol_table_t& symbol_table = compositor.symbol_table();
symbol_table.add_constants();
symbol_table.add_variable("x",x);
std::string expression_str1 = "fibonacci1(x)";
std::string expression_str2 = "fibonacci2(x)";
std::string expression_str3 = "fibonacci3(x)";
std::string expression_str4 = "fibonacci4(x)";
const std::string expression_str[] = {
"fibonacci1(x)",
"fibonacci2(x)",
"fibonacci3(x)",
"fibonacci4(x)",
"fibonacci5(x)"
};
expression_t expression1;
expression_t expression2;
expression_t expression3;
expression_t expression4;
expression1.register_symbol_table(symbol_table);
expression2.register_symbol_table(symbol_table);
expression3.register_symbol_table(symbol_table);
expression4.register_symbol_table(symbol_table);
const std::size_t expression_count = sizeof(expression_str) / sizeof(std::string);
std::vector<expression_t> expression_list;
for (std::size_t i = 0; i < expression_count; ++i)
{
parser_t parser;
if (!parser.compile(expression_str1,expression1))
expression_t expression;
expression.register_symbol_table(symbol_table);
if (!parser.compile(expression_str[i],expression))
{
printf("run_test19() - Error: %s Expression1: %s\n",
printf("run_test19() - Error: %s Expression[%02d]: %s\n",
parser.error().c_str(),
expression_str1.c_str());
static_cast<unsigned int>(i),
expression_str[i].c_str());
return false;
}
if (!parser.compile(expression_str2,expression2))
{
printf("run_test19() - Error: %s Expression2: %s\n",
parser.error().c_str(),
expression_str2.c_str());
return false;
}
if (!parser.compile(expression_str3,expression3))
{
printf("run_test19() - Error: %s Expression3: %s\n",
parser.error().c_str(),
expression_str3.c_str());
return false;
}
if (!parser.compile(expression_str4,expression4))
{
printf("run_test19() - Error: %s Expression4: %s\n",
parser.error().c_str(),
expression_str4.c_str());
return false;
else
expression_list.push_back(expression);
}
bool failure = false;
@ -4441,50 +4471,52 @@ inline bool run_test19()
};
const std::size_t fibonacci_list_size = sizeof(fibonacci_list) / sizeof(std::size_t);
for (std::size_t i = 0; i < fibonacci_list_size; ++i)
for (std::size_t i = 0; (i < fibonacci_list_size) && (!failure); ++i)
{
x = i;
T result1 = expression1.value();
T result2 = expression2.value();
T result3 = expression3.value();
T result4 = expression4.value();
std::vector<T> result(expression_count,T(0));
if (
(result1 != result2) ||
(result1 != result3) ||
(result1 != result4)
)
for (std::size_t j = 0; j < expression_list.size(); ++j)
{
printf("run_test19() - Error in evaluation! (3) Results don't match! fibonacci(%d) = %d "
"Expression1: %s = %d Expression2: %s = %d Expression3: %s = %d Expression4: %s = %d\n",
static_cast<unsigned int>(i),
static_cast<unsigned int>(fibonacci_list[i]),
expression_str1.c_str(),
static_cast<unsigned int>(result1),
expression_str2.c_str(),
static_cast<unsigned int>(result2),
expression_str3.c_str(),
static_cast<unsigned int>(result3),
expression_str4.c_str(),
static_cast<unsigned int>(result4));
failure = true;
result[j] = expression_list[j].value();
}
if (fibonacci_list[i] != expression1.value())
for (std::size_t j = 1; j < expression_list.size(); ++j)
{
if (result[j] != result[0])
{
printf("run_test19() - Error in evaluation! (4) fibonacci(%d) = %d "
"Expression1: %s = %d Expression2: %s = %d Expression3: %s = %d Expression4: %s = %d\n",
static_cast<unsigned int>(i),
static_cast<unsigned int>(fibonacci_list[i]),
expression_str1.c_str(),
static_cast<unsigned int>(result1),
expression_str2.c_str(),
static_cast<unsigned int>(result2),
expression_str3.c_str(),
static_cast<unsigned int>(result3),
expression_str4.c_str(),
static_cast<unsigned int>(result4));
failure = true;
break;
}
}
if (failure)
{
printf("run_test19() - Error in evaluation! (5) Results don't match! fibonacci(%d) = %d\n",
static_cast<unsigned int>(i),
static_cast<unsigned int>(fibonacci_list[i]));
for (std::size_t j = 0; j < expression_list.size(); ++j)
{
printf("Expression[%02d]: %s = %d\n",
static_cast<unsigned int>(j),
expression_str[j].c_str(),
static_cast<unsigned int>(result[j]));
}
}
else if (fibonacci_list[i] != expression_list[0].value())
{
printf("run_test19() - Error in evaluation! (6) Results don't match! fibonacci(%d) = %d\n",
static_cast<unsigned int>(i),
static_cast<unsigned int>(fibonacci_list[i]));
for (std::size_t j = 0; j < expression_list.size(); ++j)
{
printf("Expression[%02d]: %s = %d\n",
static_cast<unsigned int>(j),
expression_str[j].c_str(),
static_cast<unsigned int>(result[j]));
}
}
}
@ -4515,8 +4547,10 @@ inline bool run_test19()
" y := x / 2; "
" while ((z := (z - 1)) > 0) "
" { "
" if (equal(y * y,x), z := 0, 0);"
" y := (1 / 2) * (y + (x / y)) "
" if (equal(y^2,x)) "
" y := y + (z := 0); "
" else "
" y := (1 / 2) * (y + (x / y)); "
" } "
" }; "
"} ",

View File

@ -33,9 +33,9 @@ arithmetic operations, functions and processes:
(5) Conditional,
Switch &
Loop statements: if-then-else, ternary conditional, switch-case,
while, repeat-until
while, for, repeat-until
(6) Assignment: :=
(6) Assignment: :=, +=, -=, *=, /=
(7) String
processing: in, like, ilike
@ -107,20 +107,20 @@ include path (e.g: /usr/include/).
[07 - COMPILER COMPATIBILITY]
(*) GNU Compiler Collection (4.1+)
(*) Intel C++ Compiler (9.x+)
(*) GNU Compiler Collection (3.3+)
(*) Intel C++ Compiler (8.x+)
(*) Clang/LLVM (1.1+)
(*) PGI C++ (10.x+)
(*) Microsoft Visual Studio C++ Compiler (8.1+)
(*) Comeau C++ Compiler (4.3+)
(*) IBM XL C/C++ (10.x+)
(*) IBM XL C/C++ (9.x+)
(*) C++ Builder (XE4+)
[08 - BUILT-IN OPERATIONS & FUNCTIONS]
(0) Arithmetic Operators
(0) Arithmetic & Assignment Operators
+----------+---------------------------------------------------------+
| OPERATOR | DEFINITION |
+----------+---------------------------------------------------------+
@ -139,6 +139,23 @@ include path (e.g: /usr/include/).
| := | Assign the value of x to y. (eg: y := x) |
| | Where y is a variable type. |
+----------+---------------------------------------------------------+
| += | Increment x to by the value of the expression on the |
| | right-hand side. Where x is a variable type. |
| | (eg: x += abs(y - z)) |
+----------+---------------------------------------------------------+
| -= | Decrement x to by the value of the expression on the |
| | right-hand side. Where x is a variable type. |
| | (eg: x -= abs(y + z)) |
+----------+---------------------------------------------------------+
| *= | Assign the multiplication of x by the value of the |
| | expression on the right-hand side to x. Where x is a |
| | variable type. |
| | (eg: x *= abs(y / z)) |
+----------+---------------------------------------------------------+
| /= | Assign the division of x by the value of the expression |
| | on the right-hand side to x. Where x is a variable type.|
| | (eg: x /= abs(y * z)) |
+----------+---------------------------------------------------------+
(1) Equalities & Inequalities
+----------+---------------------------------------------------------+
@ -411,10 +428,10 @@ include path (e.g: /usr/include/).
| | statement in the final iteration will be used as the |
| | return value of the loop. |
| | eg: |
| | while ((x := (x - 1)) > 0) |
| | while ((x -= 1) > 0) |
| | { |
| | y := x + z; |
| | w := z + y; |
| | w := u + y; |
| | } |
+----------+---------------------------------------------------------+
| repeat/ | The structure will repeatedly evaluate the internal |
@ -424,8 +441,20 @@ include path (e.g: /usr/include/).
| | eg: |
| | repeat |
| | y := x + z; |
| | w := z + y; |
| | until ((x := (x - 1)) <= 0) |
| | w := u + y; |
| | until ((x - 1) <= 0) |
+----------+---------------------------------------------------------+
| for | The structure will repeatedly evaluate the internal |
| | statement(s) while the condition is true. On each loop |
| | iteration, an 'incrementing' expression is evaluated. |
| | The conditional is mandatory whereas the initializer |
| | and incrementing expressions are optional. |
| | eg: |
| | for (x := 0; x < n && (x != y); x := x + 1) |
| | { |
| | y := y + x / 2 - z; |
| | w := u + y; |
| | } |
+----------+---------------------------------------------------------+
| ?: | Ternary conditional statement, similar to that of the |
| | above denoted if-statement. |
@ -833,10 +862,10 @@ correctly optimize such expressions for a given architecture.
multiple expressions.
(21) The common use-case for an expression is to have it compiled
only once and then subsequently have it evaluated multiple
times. An extremely inefficient approach would be to recompile
an expression from its string form every time it requires
evaluating.
only ONCE and then subsequently have it evaluated multiple
times. An extremely inefficient and suboptimal approach would
be to recompile an expression from its string form every time
it requires evaluating.
(22) The following are examples of compliant floating point value
representations: