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

This commit is contained in:
Arash Partow 2020-01-01 00:00:00 +00:00
parent 050dcf0b5a
commit 93a9f44f99
26 changed files with 5414 additions and 2681 deletions

34
.circleci/config.yml Normal file
View File

@ -0,0 +1,34 @@
version: 2.1
jobs:
build_gcc_6:
docker:
- image: gcc:6
steps:
- checkout
- run: make all -j 2
- run: ./exprtk_test
build_gcc_7:
docker:
- image: gcc:7
steps:
- checkout
- run: make all -j 2
- run: ./exprtk_test
build_gcc_latest:
docker:
- image: gcc:latest
steps:
- checkout
- run: make all -j 2
- run: ./exprtk_test
workflows:
version: 2
build_and_test:
jobs:
- build_gcc_6
- build_gcc_7
- build_gcc_latest

View File

@ -1,12 +0,0 @@
language: cpp
sudo: required
dist: trusty
compiler:
- gcc
script:
- make clean all
- ./exprtk_test

View File

@ -2,7 +2,7 @@
# ************************************************************** # **************************************************************
# * C++ Mathematical Expression Toolkit Library * # * C++ Mathematical Expression Toolkit Library *
# * * # * *
# * Author: Arash Partow (1999-2018) * # * Author: Arash Partow (1999-2020) *
# * URL: http://www.partow.net/programming/exprtk/index.html * # * URL: http://www.partow.net/programming/exprtk/index.html *
# * * # * *
# * Copyright notice: * # * Copyright notice: *
@ -15,37 +15,18 @@
# #
COMPILER = -c++ COMPILER := -c++
#COMPILER = -clang #COMPILER := -clang++
OPTIMIZATION_OPT = -O1 OPTIMIZATION_OPT := -O1
BASE_OPTIONS = -pedantic-errors -Wall -Wextra -Werror -Wno-long-long BASE_OPTIONS := -pedantic-errors -Wall -Wextra -Werror -Wno-long-long
OPTIONS = $(BASE_OPTIONS) $(OPTIMIZATION_OPT) OPTIONS := $(BASE_OPTIONS) $(OPTIMIZATION_OPT)
LINKER_OPT = -L/usr/lib -lstdc++ -lm LINKER_OPT := -L/usr/lib -lstdc++ -lm
ASAN_OPT = -g -fsanitize=address -fno-omit-frame-pointer ASAN_OPT := -g -fsanitize=address -fno-omit-frame-pointer
MSAN_OPT = -g -fsanitize=memory -fno-omit-frame-pointer MSAN_OPT := -g -fsanitize=memory -fno-omit-frame-pointer
LSAN_OPT = -g -fsanitize=leak -fno-omit-frame-pointer LSAN_OPT := -g -fsanitize=leak -fno-omit-frame-pointer
USAN_OPT := -g -fsanitize=undefined -fno-omit-frame-pointer
BUILD_LIST+=exprtk_test BUILD_SRC := $(sort $(wildcard exprtk_*.cpp))
BUILD_LIST+=exprtk_benchmark BUILD_LIST := $(BUILD_SRC:%.cpp=%)
BUILD_LIST+=exprtk_simple_example_01
BUILD_LIST+=exprtk_simple_example_02
BUILD_LIST+=exprtk_simple_example_03
BUILD_LIST+=exprtk_simple_example_04
BUILD_LIST+=exprtk_simple_example_05
BUILD_LIST+=exprtk_simple_example_06
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
BUILD_LIST+=exprtk_simple_example_12
BUILD_LIST+=exprtk_simple_example_13
BUILD_LIST+=exprtk_simple_example_14
BUILD_LIST+=exprtk_simple_example_15
BUILD_LIST+=exprtk_simple_example_16
BUILD_LIST+=exprtk_simple_example_17
BUILD_LIST+=exprtk_simple_example_18
BUILD_LIST+=exprtk_simple_example_19
all: $(BUILD_LIST) all: $(BUILD_LIST)

6775
exprtk.hpp

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* ExprTk vs Native Benchmarks * * ExprTk vs Native Benchmarks *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 1 * * Simple Example 1 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -28,7 +29,8 @@ void trig_function()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)"; const std::string expression_string =
"clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)";
T x; T x;
@ -44,8 +46,8 @@ void trig_function()
for (x = T(-5); x <= T(+5); x += T(0.001)) for (x = T(-5); x <= T(+5); x += T(0.001))
{ {
T y = expression.value(); const T y = expression.value();
printf("%19.15f\t%19.15f\n",x,y); printf("%19.15f\t%19.15f\n", x, y);
} }
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 2 * * Simple Example 2 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -28,14 +29,15 @@ void square_wave()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string expr_string = "a*(4/pi)*" const std::string expr_string =
"((1 /1)*sin( 2*pi*f*t)+(1 /3)*sin( 6*pi*f*t)+" "a*(4/pi)*"
" (1 /5)*sin(10*pi*f*t)+(1 /7)*sin(14*pi*f*t)+" "((1 /1)*sin( 2*pi*f*t)+(1 /3)*sin( 6*pi*f*t)+"
" (1 /9)*sin(18*pi*f*t)+(1/11)*sin(22*pi*f*t)+" " (1 /5)*sin(10*pi*f*t)+(1 /7)*sin(14*pi*f*t)+"
" (1/13)*sin(26*pi*f*t)+(1/15)*sin(30*pi*f*t)+" " (1 /9)*sin(18*pi*f*t)+(1/11)*sin(22*pi*f*t)+"
" (1/17)*sin(34*pi*f*t)+(1/19)*sin(38*pi*f*t)+" " (1/13)*sin(26*pi*f*t)+(1/15)*sin(30*pi*f*t)+"
" (1/21)*sin(42*pi*f*t)+(1/23)*sin(46*pi*f*t)+" " (1/17)*sin(34*pi*f*t)+(1/19)*sin(38*pi*f*t)+"
" (1/25)*sin(50*pi*f*t)+(1/27)*sin(54*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.141592653589793238462643383279502); static const T pi = T(3.141592653589793238462643383279502);
@ -59,8 +61,8 @@ void square_wave()
for (t = (T(-2) * pi); t <= (T(+2) * pi); t += delta) for (t = (T(-2) * pi); t <= (T(+2) * pi); t += delta)
{ {
T result = expression.value(); const T result = expression.value();
printf("%19.15f\t%19.15f\n",t,result); printf("%19.15f\t%19.15f\n", t, result);
} }
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 3 * * Simple Example 3 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -28,7 +29,8 @@ void polynomial()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string expression_string = "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1"; const std::string expression_string =
"25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1";
const T r0 = T(0); const T r0 = T(0);
const T r1 = T(1); const T r1 = T(1);
@ -47,7 +49,7 @@ void polynomial()
for (x = r0; x <= r1; x += delta) for (x = r0; x <= r1; x += delta)
{ {
printf("%19.15f\t%19.15f\n",x,expression.value()); printf("%19.15f\t%19.15f\n", x, expression.value());
} }
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 4 * * Simple Example 4 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -72,7 +73,7 @@ void fibonacci()
{ {
x = static_cast<T>(i); x = static_cast<T>(i);
T result = expression.value(); const T result = expression.value();
printf("fibonacci(%3d) = %10.0f\n", printf("fibonacci(%3d) = %10.0f\n",
static_cast<int>(i), static_cast<int>(i),

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 5 * * Simple Example 5 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -49,7 +50,7 @@ void custom_function()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string expression_string = const std::string expression_string =
"myfunc(sin(x / pi), otherfunc(3 * y, x / 2, x * y))"; "myfunc(sin(x / pi), otherfunc(3 * y, x / 2, x * y))";
T x = T(1); T x = T(1);
@ -69,7 +70,7 @@ void custom_function()
parser_t parser; parser_t parser;
parser.compile(expression_string,expression); parser.compile(expression_string,expression);
T result = expression.value(); const T result = expression.value();
printf("Result: %10.5f\n",result); printf("Result: %10.5f\n",result);
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 6 * * Simple Example 6 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -28,7 +29,7 @@ void vector_function()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string expression_string = const std::string expression_string =
" for (var i := 0; i < min(x[],y[],z[]); i += 1) " " for (var i := 0; i < min(x[],y[],z[]); i += 1) "
" { " " { "
" z[i] := 3sin(x[i]) + 2log(y[i]); " " z[i] := 3sin(x[i]) + 2log(y[i]); "

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 7 * * Simple Example 7 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -28,7 +29,7 @@ void logic()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string expression_string = "not(A and B) or C"; const std::string expression_string = "not(A and B) or C";
symbol_table_t symbol_table; symbol_table_t symbol_table;
symbol_table.create_variable("A"); symbol_table.create_variable("A");
@ -52,7 +53,7 @@ void logic()
symbol_table.get_variable("B")->ref() = T((i & 0x02) ? 1 : 0); symbol_table.get_variable("B")->ref() = T((i & 0x02) ? 1 : 0);
symbol_table.get_variable("C")->ref() = T((i & 0x04) ? 1 : 0); symbol_table.get_variable("C")->ref() = T((i & 0x04) ? 1 : 0);
int result = static_cast<int>(expression.value()); const int result = static_cast<int>(expression.value());
printf(" %d | %d | %d | %d | %d \n", printf(" %d | %d | %d | %d | %d \n",
i, i,

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 8 * * Simple Example 8 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -27,7 +28,7 @@ void composite()
typedef exprtk::symbol_table<T> symbol_table_t; 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; typedef exprtk::parser<T> parser_t;
typedef exprtk::parser_error::type error_t; typedef exprtk::parser_error::type err_t;
typedef exprtk::function_compositor<T> compositor_t; typedef exprtk::function_compositor<T> compositor_t;
typedef typename compositor_t::function function_t; typedef typename compositor_t::function function_t;
@ -64,7 +65,7 @@ void composite()
for (std::size_t i = 0; i < parser.error_count(); ++i) for (std::size_t i = 0; i < parser.error_count(); ++i)
{ {
error_t error = parser.get_error(i); const err_t error = parser.get_error(i);
printf("Error: %02d Position: %02d Type: [%14s] Msg: %s\tExpression: %s\n", printf("Error: %02d Position: %02d Type: [%14s] Msg: %s\tExpression: %s\n",
static_cast<unsigned int>(i), static_cast<unsigned int>(i),
@ -77,7 +78,7 @@ void composite()
return; return;
} }
T result = expression.value(); const T result = expression.value();
printf("%s = %e\n", expression_string.c_str(), result); printf("%s = %e\n", expression_string.c_str(), result);
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 9 * * Simple Example 9 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -132,9 +133,9 @@ void primes()
{ {
x = static_cast<T>(i); x = static_cast<T>(i);
T result1 = expression1.value(); const T result1 = expression1.value();
T result2 = expression2.value(); const T result2 = expression2.value();
T result3 = expression3.value(); const T result3 = expression3.value();
printf("%03d Result1: %c Result2: %c Result3: %c\n", printf("%03d Result1: %c Result2: %c Result3: %c\n",
static_cast<unsigned int>(i), static_cast<unsigned int>(i),

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 10 * * Simple Example 10 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -19,6 +19,7 @@
#include <cmath> #include <cmath>
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -44,25 +45,26 @@ void newton_sqrt()
.add( .add(
function_t( // define function: newton_sqrt(x) function_t( // define function: newton_sqrt(x)
"newton_sqrt", "newton_sqrt",
" switch " " switch "
" { " " { "
" case x < 0 : -inf; " " case x < 0 : null; "
" case x == 0 : 0; " " case x == 0 : 0; "
" case x == 1 : 1; " " case x == 1 : 1; "
" default: " " default: "
" ~{ " " ~{ "
" var z := 100; " " var z := 100; "
" var sqrt_x := x / 2; " " var sqrt_x := x / 2; "
" repeat " " repeat "
" sqrt_x := (1 / 2) * (sqrt_x + (x / sqrt_x)); " " if (equal(sqrt_x^2, x)) "
" if (equal(sqrt_x^2, x)) " " break[sqrt_x]; "
" break[sqrt_x]; " " else "
" until ((z -= 1) <= 0); " " sqrt_x := (1 / 2) * (sqrt_x + (x / sqrt_x)); "
" }; " " until ((z -= 1) <= 0); "
" } ", " }; "
" } ",
"x")); "x"));
std::string expression_str = "newton_sqrt(x)"; const std::string expression_str = "newton_sqrt(x)";
expression_t expression; expression_t expression;
expression.register_symbol_table(symbol_table); expression.register_symbol_table(symbol_table);
@ -74,9 +76,9 @@ void newton_sqrt()
{ {
x = static_cast<T>(i); x = static_cast<T>(i);
T result = expression.value(); const T result = expression.value();
printf("sqrt(%03d) - Result: %12.10f\tReal: %12.10f\n", printf("sqrt(%03d) - Result: %15.13f\tReal: %15.13f\n",
static_cast<unsigned int>(i), static_cast<unsigned int>(i),
result, result,
std::sqrt(x)); std::sqrt(x));

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 11 * * Simple Example 11 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -28,7 +29,7 @@ void square_wave2()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string wave_program = const std::string wave_program =
" var r := 0; " " var r := 0; "
" for (var i := 0; i < 1000; i += 1) " " for (var i := 0; i < 1000; i += 1) "
" { " " { "
@ -58,8 +59,8 @@ void square_wave2()
for (t = (T(-2) * pi); t <= (T(+2) * pi); t += delta) for (t = (T(-2) * pi); t <= (T(+2) * pi); t += delta)
{ {
T result = expression.value(); const T result = expression.value();
printf("%19.15f\t%19.15f\n",t,result); printf("%19.15f\t%19.15f\n", t, result);
} }
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 12 * * Simple Example 12 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -28,7 +29,7 @@ void bubble_sort()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string bubblesort_program = const std::string bubblesort_program =
" var upper_bound := v[]; " " var upper_bound := v[]; "
" var swapped := false; " " var swapped := false; "
" repeat " " repeat "

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 13 * * Simple Example 13 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -20,6 +20,7 @@
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -30,7 +31,7 @@ void savitzky_golay_filter()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string sgfilter_program = const std::string sgfilter_program =
" var weight[9] := " " var weight[9] := "
" { " " { "
" -21, 14, 39, " " -21, 14, 39, "
@ -88,7 +89,7 @@ void savitzky_golay_filter()
for (std::size_t i = 0; i < v_out.size(); ++i) for (std::size_t i = 0; i < v_out.size(); ++i)
{ {
printf("%10.6f\t%10.6f\n",v_in[i],v_out[i]); printf("%10.6f\t%10.6f\n", v_in[i], v_out[i]);
} }
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 14 * * Simple Example 14 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -27,7 +28,7 @@ void stddev_example()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string stddev_program = const std::string stddev_program =
" var x[25] := { " " var x[25] := { "
" 1, 2, 3, 4, 5, " " 1, 2, 3, 4, 5, "
" 6, 7, 8, 9, 10, " " 6, 7, 8, 9, 10, "
@ -43,7 +44,7 @@ void stddev_example()
parser_t parser; parser_t parser;
parser.compile(stddev_program,expression); parser.compile(stddev_program,expression);
T stddev = expression.value(); const T stddev = expression.value();
printf("stddev(1..25) = %10.6f\n",stddev); printf("stddev(1..25) = %10.6f\n",stddev);
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 15 * * Simple Example 15 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -28,7 +29,7 @@ void black_scholes_merton_model()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string bsm_model_program = const std::string bsm_model_program =
" var d1 := (log(s / x) + (r + v^2 / 2) * t) / (v * sqrt(t)); " " var d1 := (log(s / x) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
" var d2 := d1 - v * sqrt(t); " " var d2 := d1 - v * sqrt(t); "
" " " "
@ -70,7 +71,7 @@ void black_scholes_merton_model()
printf("BSM(%s,%5.3f,%5.3f,%5.3f,%5.3f,%5.3f) = %10.6f\n", printf("BSM(%s,%5.3f,%5.3f,%5.3f,%5.3f,%5.3f) = %10.6f\n",
callput_flag.c_str(), callput_flag.c_str(),
s,x,t,r,v, s, x, t, r, v,
bsm); bsm);
} }
@ -81,7 +82,7 @@ void black_scholes_merton_model()
printf("BSM(%s,%5.3f,%5.3f,%5.3f,%5.3f,%5.3f) = %10.6f\n", printf("BSM(%s,%5.3f,%5.3f,%5.3f,%5.3f,%5.3f) = %10.6f\n",
callput_flag.c_str(), callput_flag.c_str(),
s,x,t,r,v, s, x, t, r, v,
bsm); bsm);
} }
} }

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 16 * * Simple Example 16 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -19,6 +19,7 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <string> #include <string>
#include "exprtk.hpp" #include "exprtk.hpp"
@ -29,7 +30,7 @@ void linear_least_squares()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string linear_least_squares_program = const std::string linear_least_squares_program =
" if (x[] == y[]) " " if (x[] == y[]) "
" { " " { "
" beta := (sum(x * y) - sum(x) * sum(y) / x[]) / " " beta := (sum(x * y) - sum(x) * sum(y) / x[]) / "

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 17 * * Simple Example 17 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -47,7 +47,7 @@ void monte_carlo_pi()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string monte_carlo_pi_program = const std::string monte_carlo_pi_program =
" var experiments[5 * 10^7] := [(rnd_01^2 + rnd_01^2) <= 1]; " " var experiments[5 * 10^7] := [(rnd_01^2 + rnd_01^2) <= 1]; "
" 4 * sum(experiments) / experiments[]; "; " 4 * sum(experiments) / experiments[]; ";

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 18 * * Simple Example 18 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -29,7 +29,7 @@ void file_io()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string fileio_program = const std::string fileio_program =
" var file_name := 'file.txt'; " " var file_name := 'file.txt'; "
" var stream := null; " " var stream := null; "
" " " "

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Simple Example 19 * * Simple Example 19 *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -55,7 +55,7 @@ public:
if ( if (
(1 == ps_index) && (1 == ps_index) &&
!exprtk::rtl::vecops::helper:: !exprtk::rtl::vecops::helper::
load_vector_range<T>::process(parameters,r0,r1,1,2,0) load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
) )
return T(0); return T(0);
@ -84,7 +84,7 @@ void vector_randu()
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t; typedef exprtk::parser<T> parser_t;
std::string vecrandu_program = const std::string vecrandu_program =
" var noise[6] := [0]; " " var noise[6] := [0]; "
" " " "
" if (randu(noise,0,5) == false) " " if (randu(noise,0,5) == false) "

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library * * C++ Mathematical Expression Toolkit Library *
* * * *
* Examples and Unit-Tests * * Examples and Unit-Tests *
* Author: Arash Partow (1999-2018) * * Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html * * URL: http://www.partow.net/programming/exprtk/index.html *
* * * *
* Copyright notice: * * Copyright notice: *
@ -23,6 +23,7 @@
#include <deque> #include <deque>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <numeric>
#include <string> #include <string>
#include <vector> #include <vector>
@ -2450,7 +2451,92 @@ inline bool run_test02()
test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+1] <=> y[:]; (x == '01XXX') and (y == 'XX234567890')", "","",T(1.0)), test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+1] <=> y[:]; (x == '01XXX') and (y == 'XX234567890')", "","",T(1.0)),
test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+2] <=> y[:]; (x == '012XX') and (y == 'XXX34567890')", "","",T(1.0)), test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+2] <=> y[:]; (x == '012XX') and (y == 'XXX34567890')", "","",T(1.0)),
test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+3] <=> y[:]; (x == '0123X') and (y == 'XXXX4567890')", "","",T(1.0)), test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+3] <=> y[:]; (x == '0123X') and (y == 'XXXX4567890')", "","",T(1.0)),
test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+4] <=> y[:]; (x == '01234') and (y == 'XXXXX567890')", "","",T(1.0)) test_ab<T>("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+4] <=> y[:]; (x == '01234') and (y == 'XXXXX567890')", "","",T(1.0)),
test_ab<T>("var v[4] := {1,2,3,4}; for (var i := 0; i < v[]; i += 1) { v[i] += 10; v[i] == 0 }; sum(v) == (1 + 2 + 3 + 4) + (v[] * 10)", "","",T(1.0)),
test_ab<T>("var v[4] := {1,2,3,4}; for (var i := 0; i < v[]; i += 1) { v[i] -= 10; v[i] == 0 }; sum(v) == (1 + 2 + 3 + 4) - (v[] * 10)", "","",T(1.0)),
test_ab<T>("var v[4] := {1,2,3,4}; for (var i := 0; i < v[]; i += 1) { v[i] *= 10; v[i] == 0 }; sum(v) == (1 + 2 + 3 + 4) * 10", "","",T(1.0)),
test_ab<T>("var v[4] := {1,2,3,4}; for (var i := 0; i < v[]; i += 1) { v[i] /= 10; v[i] == 0 }; sum(v) == (1 + 2 + 3 + 4) / 10", "","",T(1.0)),
test_ab<T>("a like b", "abcd", "abcd*", T(1.0)),
test_ab<T>("a like b", "abcd", "abcd" , T(1.0)),
test_ab<T>("a like b", "abcd", "abc*" , T(1.0)),
test_ab<T>("a like b", "abcd", "*bcd" , T(1.0)),
test_ab<T>("a like b", "abcd", "abc?" , T(1.0)),
test_ab<T>("a like b", "abcd", "?bcd" , T(1.0)),
test_ab<T>("a like b", "abcd", "ab?d" , T(1.0)),
test_ab<T>("a like b", "abcd", "ab*d" , T(1.0)),
test_ab<T>("a like b", "abcd", "a?cd" , T(1.0)),
test_ab<T>("a like b", "abcd", "a*cd" , T(1.0)),
test_ab<T>("a like b", "abcd", "a??d" , T(1.0)),
test_ab<T>("a like b", "abcd", "a*?d" , T(1.0)),
test_ab<T>("a like b", "abcd", "*bc*" , T(1.0)),
test_ab<T>("a like b", "abcd", "?bc?" , T(1.0)),
test_ab<T>("a like b", "abcd", "????" , T(1.0)),
test_ab<T>("a like b", "abcd", "a???" , T(1.0)),
test_ab<T>("a like b", "abcd", "ab??" , T(1.0)),
test_ab<T>("a like b", "abcd", "abc?" , T(1.0)),
test_ab<T>("a like b", "abcd", "???d" , T(1.0)),
test_ab<T>("a like b", "abcd", "??cd" , T(1.0)),
test_ab<T>("a like b", "abcd", "?bcd" , T(1.0)),
test_ab<T>("a like b", "abcd", "?b?d" , T(1.0)),
test_ab<T>("a like b", "abcd", "a?c?" , T(1.0)),
test_ab<T>("a like b", "abcd", "a??d" , T(1.0)),
test_ab<T>("a like b", "abcd", "?bc?" , T(1.0)),
test_ab<T>("a like b", "abcd", "ab**" , T(1.0)),
test_ab<T>("a like b", "abcd", "ab*?" , T(1.0)),
test_ab<T>("a like b", "abcd", "a***" , T(1.0)),
test_ab<T>("a like b", "abcd", "**cd" , T(1.0)),
test_ab<T>("a like b", "abcd", "*?cd" , T(1.0)),
test_ab<T>("a like b", "abcd", "***d" , T(1.0)),
test_ab<T>("a like b", "abcd", "*bc*" , T(1.0)),
test_ab<T>("a like b", "abcd", "*bc?" , T(1.0)),
test_ab<T>("a like b", "abcd", "*b??" , T(1.0)),
test_ab<T>("a like b", "abcd", "?bc*" , T(1.0)),
test_ab<T>("a like b", "abcd", "??c*" , T(1.0)),
test_ab<T>("a like b", "abcd", "*b?*" , T(1.0)),
test_ab<T>("a like b", "ab" , "a*" , T(1.0)),
test_ab<T>("a like b", "ab" , "a?" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "abcd*", T(1.0)),
test_ab<T>("a ilike b", "aBcD", "abcd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "abc*" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "*bcd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "abc?" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "?bcd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "ab?d" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "ab*d" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "a?cd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "a*cd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "a??d" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "a*?d" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "*bc*" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "?bc?" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "????" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "a???" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "ab??" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "abc?" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "???d" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "??cd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "?bcd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "?b?d" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "a?c?" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "a??d" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "?bc?" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "ab**" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "ab*?" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "a***" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "**cd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "*?cd" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "***d" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "*bc*" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "*bc?" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "*b??" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "?bc*" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "??c*" , T(1.0)),
test_ab<T>("a ilike b", "aBcD", "*b?*" , T(1.0)),
test_ab<T>("a ilike b", "aB" , "a*" , T(1.0)),
test_ab<T>("a ilike b", "aB" , "a?" , T(1.0))
}; };
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>); static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>);
@ -2589,6 +2675,10 @@ inline bool run_test02()
template <typename T> template <typename T>
inline bool run_test03() inline bool run_test03()
{ {
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
std::string expression_string = "A+A0+aA+Aa0+b+B1+Bb+bB1+A+A0+AA+AA0+B+B1+BB+BB1+a+a0+aa+aa0+b+b1+bb+bb1+" std::string expression_string = "A+A0+aA+Aa0+b+B1+Bb+bB1+A+A0+AA+AA0+B+B1+BB+BB1+a+a0+aa+aa0+b+b1+bb+bb1+"
"c+C2+Cc+Cc2+D+D3+dD+dD3+C+C2+CC+CC2+D+D3+DD+DD3+c+c2+cc+cc2+d+d3+dd+dd3+" "c+C2+Cc+Cc2+D+D3+dD+dD3+C+C2+CC+CC2+D+D3+DD+DD3+c+c2+cc+cc2+d+d3+dd+dd3+"
"E+E4+eE+Ee4+f+F5+Ff+fF5+E+E4+EE+EE4+F+F5+FF+FF5+e+e4+ee+ee4+f+f5+ff+ff5+" "E+E4+eE+Ee4+f+F5+Ff+fF5+E+E4+EE+EE4+F+F5+FF+FF5+e+e4+ee+ee4+f+f5+ff+ff5+"
@ -2626,9 +2716,9 @@ 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_0; symbol_table_t symbol_table_0;
exprtk::symbol_table<T> symbol_table_1; symbol_table_t symbol_table_1;
exprtk::expression<T> expression; expression_t expression;
std::vector<T> v; std::vector<T> v;
v.resize(variable_list_size); v.resize(variable_list_size);
@ -2726,7 +2816,38 @@ inline bool run_test03()
"1 v x", "1 v x",
"1 v y", "1 v y",
"x v 1", "x v 1",
"y v 1" "y v 1",
"(x == 'a string' )",
"(x == 'a string'[1:2] )",
"(x == 'a string' + 'b string' )",
"(x == ('a string' + 'b string')[3:5])",
"('a string' == x )",
"('a string'[1:2] == x )",
"('a string' + 'b string' == x )",
"(('a string' + 'b string')[3:5] == x)",
"var a; var b; 3in(a)+sin(b) ",
"var a; var b; sin(a)+3in(b) ",
"var a; var b; sqrt(a)<3in(8) ",
"var a; var b; (1.99-3in((b-b))) ",
"var a; var b; ((3in(sin((b+b)))/1.06)-a) ",
"var a; var b; ((sin(3in((b+b)))/1.06)-a) ",
"var a; var b; (3in(x*(y+z))+cos(x*(y-z))) ",
"var a; var b; (cos(x*(y+z))+3in(x*(y-z))) ",
"1++++",
"1+-+-+",
"1===",
"1====",
"[*][*][*][*][*]",
"var v[1] := {}; var s0appe0 := false; repeat s0appe0 false for(){(){}}",
"var v[2] := {}; repeat var s0appe0 := false; s0appe0 false for(){(){}}",
"var v[3] := {}; repeat var s0appe0 := false; for(){(){}} s0appe0 false",
"var v[4] := {}; repeat var s0appe0 := false; s0appe0 for(){(){}} false",
"var v[5] := {}; repeat for(){(){}} var s0appe0 := false; s0appe0 false",
"var v{};v ;v 60;v 60;v o5"
}; };
const std::size_t invalid_expr_size = sizeof(invalid_expr) / sizeof(std::string); const std::size_t invalid_expr_size = sizeof(invalid_expr) / sizeof(std::string);
@ -2734,9 +2855,9 @@ inline bool run_test03()
{ {
for (std::size_t i = 0; i < invalid_expr_size; ++i) for (std::size_t i = 0; i < invalid_expr_size; ++i)
{ {
exprtk::symbol_table<T> symbol_table; symbol_table_t symbol_table;
expression_t expression;
exprtk::expression<T> expression; parser_t parser;
T x = T(0); T x = T(0);
std::string s; std::string s;
@ -2746,8 +2867,6 @@ inline bool run_test03()
symbol_table.add_stringvar("s",s); symbol_table.add_stringvar("s",s);
symbol_table.add_vector ("v",v); symbol_table.add_vector ("v",v);
exprtk::parser<T> parser;
if (parser.compile(invalid_expr[i],expression)) if (parser.compile(invalid_expr[i],expression))
{ {
printf("run_test03() - Error: [1] Invalid expression compiled successfuly. Expression: %s\n", printf("run_test03() - Error: [1] Invalid expression compiled successfuly. Expression: %s\n",
@ -2763,14 +2882,13 @@ inline bool run_test03()
std::string s; std::string s;
std::vector<T> v(10, T(1.234)); std::vector<T> v(10, T(1.234));
exprtk::symbol_table<T> symbol_table; symbol_table_t symbol_table;
parser_t parser;
symbol_table.add_variable ("x",x); symbol_table.add_variable ("x",x);
symbol_table.add_stringvar("s",s); symbol_table.add_stringvar("s",s);
symbol_table.add_vector ("v",v); symbol_table.add_vector ("v",v);
exprtk::parser<T> parser;
for (std::size_t i = 0; i < invalid_expr_size; ++i) for (std::size_t i = 0; i < invalid_expr_size; ++i)
{ {
exprtk::expression<T> expression; exprtk::expression<T> expression;
@ -2784,6 +2902,64 @@ inline bool run_test03()
} }
} }
} }
{
const std::string base_expression =
"1+(2+2(3+3(4+4cos(((((a+((x*(e-tan((cos((((((b/(tan(((1.60*a)-0.34))-0.76))-x)+y)-3.27)+a))/pi))))^a))+y)*b)-e))+e)/z)+w)+"
"(((b+(a/((((tan((b*((((((a-(cos((cos(tan(((a+a)*3.33)))-b))/2.52))*x)/b)+3.07)^0.86)+b)))*3.95)/0.39)*y)+a)))*a)*z)";
const std::string mod =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789^+-/*,;:<>=%?[]{}() #&'\"\\\t\r\n";
symbol_table_t symbol_table;
expression_t expression;
parser_t parser;
T a = T(1.1 );
T b = T(2.2 );
T c = T(3.3 );
T d = T(4.5 );
T e = T(4.5 );
T x = T(2.123456);
T y = T(3.123456);
T z = T(4.123456);
T w = T(5.123456);
symbol_table.add_variable("a", a);
symbol_table.add_variable("b", b);
symbol_table.add_variable("c", c);
symbol_table.add_variable("d", d);
symbol_table.add_variable("e", e);
symbol_table.add_variable("x", x);
symbol_table.add_variable("y", y);
symbol_table.add_variable("z", z);
symbol_table.add_variable("w", w);
expression.register_symbol_table(symbol_table);
T total = T(0);
for (std::size_t j = 0; j < base_expression.size(); ++j)
{
std::string expression_str = base_expression;
const char old_c = base_expression[j];
for (std::size_t i = 0; i < mod.size(); ++i)
{
expression_str[j] = mod[i];
if (parser.compile(expression_str, expression))
{
total += expression.value();
}
}
expression_str[j] = old_c;
}
if (total == T(12345.6789)) { printf(" "); }
}
} }
return true; return true;
@ -4074,6 +4250,62 @@ inline bool run_test10()
} }
} }
{
const std::string expression =
"for (var i := 0; i < min(x[],y[],z[]); i += 1)"
"{ z[i] := 3sin(x[i]) + 2log(y[i]); }";
std::vector<std::string> var_symbol_list;
std::vector<std::string> func_symbol_list;
if (!exprtk::collect_variables(expression, var_symbol_list))
{
printf("run_test10() - Failed to collect variables.\n");
return false;
}
if (!exprtk::collect_functions(expression, func_symbol_list))
{
printf("run_test10() - Failed to collect functions.\n");
return false;
}
std::sort(var_symbol_list .begin(), var_symbol_list .end());
std::sort(func_symbol_list.begin(), func_symbol_list.end());
std::vector<std::string> expected_var_symbol_list;
std::vector<std::string> expected_func_symbol_list;
expected_var_symbol_list.push_back("i");
expected_var_symbol_list.push_back("x");
expected_var_symbol_list.push_back("y");
expected_var_symbol_list.push_back("z");
expected_func_symbol_list.push_back("log");
expected_func_symbol_list.push_back("min");
expected_func_symbol_list.push_back("sin");
const bool var_result = (var_symbol_list.size() == expected_var_symbol_list.size()) &&
std::equal(var_symbol_list.begin(),
var_symbol_list.end(),
expected_var_symbol_list.begin());
if (!var_result)
{
printf("run_test10() - Failed collected variable comparison between recieved and expected variables\n");
return false;
}
const bool func_result = (func_symbol_list.size() == expected_func_symbol_list.size()) &&
std::equal(func_symbol_list.begin(),
func_symbol_list.end(),
expected_func_symbol_list.begin());
if (!func_result)
{
printf("run_test10() - Failed collected fuctions comparison between recieved and expected functions\n");
return false;
}
}
{ {
std::string expression_list[] = std::string expression_list[] =
{ {
@ -5578,6 +5810,109 @@ struct vararg_func : public exprtk::igeneric_function<T>
} }
}; };
template <typename T>
struct vecrebase_func : public exprtk::igeneric_function<T>
{
typedef typename exprtk::igeneric_function<T>::parameter_list_t
parameter_list_t;
typedef typename exprtk::igeneric_function<T>::generic_type
generic_type;
typedef typename generic_type::vector_view vector_t;
using exprtk::igeneric_function<T>::operator();
vecrebase_func()
: exprtk::igeneric_function<T>("V")
{}
inline T operator()(parameter_list_t params)
{
vector_t v(params[0]);
return std::accumulate(v.begin(), v.end(), T(0));
}
};
template <typename T>
struct overload_func : exprtk::igeneric_function<T>
{
typedef typename exprtk::igeneric_function<T> igfun_t;
typedef typename igfun_t::parameter_list_t parameter_list_t;
typedef typename igfun_t::generic_type generic_type;
typedef typename generic_type::vector_view vector_t;
using exprtk::igeneric_function<T>::operator();
overload_func(const std::string& param_seq_list)
: exprtk::igeneric_function<T>(param_seq_list, igfun_t::e_rtrn_overload),
current_ps_index(std::numeric_limits<std::size_t>::max())
{
clear();
}
void clear()
{
current_ps_index = std::numeric_limits<std::size_t>::max();
current_param_seq = "";
}
inline T operator()(const std::size_t& ps_index,
parameter_list_t parameters)
{
current_ps_index = ps_index;
determine_param_seq(parameters);
return T(1);
}
inline T operator()(const std::size_t& ps_index,
std::string& result,
parameter_list_t parameters)
{
current_ps_index = ps_index;
determine_param_seq(parameters);
result = "string result";
return T(1);
}
void determine_param_seq(parameter_list_t parameters)
{
current_param_seq = "";
for (std::size_t i = 0; i < parameters.size(); ++i)
{
generic_type& gt = parameters[i];
switch (gt.type)
{
case generic_type::e_scalar : current_param_seq += "T";
break;
case generic_type::e_vector : current_param_seq += "V";
break;
case generic_type::e_string : current_param_seq += "S";
break;
default : continue;
}
}
}
std::size_t current_ps_index;
std::string current_param_seq;
struct test_result_t
{
test_result_t(const std::size_t psi, const std::string& ps)
: ps_index(psi),
param_seq(ps)
{}
std::size_t ps_index;
std::string param_seq;
};
};
template <typename T> template <typename T>
inline bool run_test18() inline bool run_test18()
@ -6516,6 +6851,68 @@ inline bool run_test18()
return false; return false;
} }
{
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
T v0[] = { T(0), T(1), T(2), T(3), T(4) };
T v1[] = { T(5), T(6), T(7), T(8), T(9) };
const std::size_t v0_size = sizeof(v0) / sizeof (T);
const std::size_t v1_size = sizeof(v1) / sizeof (T);
exprtk::vector_view<T> v = exprtk::make_vector_view(v0, v0_size);
vecrebase_func<T> vec_sum;
symbol_table_t symbol_table;
symbol_table.add_vector("v",v);
symbol_table.add_function("vec_sum",vec_sum);
expression_t expression;
expression.register_symbol_table(symbol_table);
parser_t parser;
const std::string expr_string = "vec_sum(v)";
if (!parser.compile(expr_string,expression))
{
printf("run_test18() - Error: %s\tExpression: %s\n",
parser.error().c_str(),
expr_string.c_str());
return false;
}
const T expected_result0 = std::accumulate(v0, v0 + v0_size,T(0));
if (expression.value() != expected_result0)
{
printf("run_test18() - Error in evaluation! (10.1) Expression: %s Expected: %5.3f Computed: %5.3f\n",
expr_string.c_str(),
expected_result0,
expression.value());
return false;
}
v.rebase(v1);
const T expected_result1 = std::accumulate(v1, v1 + v1_size,T(0));
if (expression.value() != expected_result1)
{
printf("run_test18() - Error in evaluation! (10.2) Expression: %s Expected: %5.3f Computed: %5.3f\n",
expr_string.c_str(),
expected_result1,
expression.value());
return false;
}
}
{ {
bool failure = false; bool failure = false;
@ -6648,7 +7045,7 @@ inline bool run_test18()
if (result != T(1)) if (result != T(1))
{ {
printf("run_test18() - Error in evaluation! (10) Expression: %s\n", printf("run_test18() - Error in evaluation! (11) Expression: %s\n",
expr_str_list[i].c_str()); expr_str_list[i].c_str());
failure = true; failure = true;
@ -6659,6 +7056,295 @@ inline bool run_test18()
return false; return false;
} }
{
typedef exprtk::expression<T> expression_t;
std::string a = "a";
std::string b = "b";
std::string c = "c";
std::string d = "d";
T x = T(1.1);
T y = T(2.2);
T z = T(3.3);
T w = T(4.4);
overload_func<T> ovrld_func
(
"T:T|T:TT|T:TTT|T:TTTT|"
"T:S|T:SS|T:SSS|T:SSSS|"
"T:ST|T:STS|T:STST|"
"T:TS|T:TST|T:TSTS|"
"T:TTSS|T:SSTT|T:STTS|T:TSST"
);
exprtk::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);
symbol_table.add_variable ("w",w);
symbol_table.add_stringvar("a",a);
symbol_table.add_stringvar("b",b);
symbol_table.add_stringvar("c",c);
symbol_table.add_stringvar("d",d);
symbol_table.add_function("foo",ovrld_func);
typedef typename overload_func<T>::test_result_t test_result_t;
typedef std::pair<std::string, typename overload_func<T>::test_result_t> test_pack_t;
static const test_pack_t test_pack_list[] =
{
test_pack_t("foo(x)" , test_result_t( 0, "T" )),
test_pack_t("foo(x, y)" , test_result_t( 1, "TT" )),
test_pack_t("foo(x, y, z)" , test_result_t( 2, "TTT" )),
test_pack_t("foo(x, y, z, w)" , test_result_t( 3, "TTTT")),
test_pack_t("foo(x + y)" , test_result_t( 0, "T" )),
test_pack_t("foo(x + y, y + z)" , test_result_t( 1, "TT" )),
test_pack_t("foo(x + y, y + z, z + w)" , test_result_t( 2, "TTT" )),
test_pack_t("foo(x + y, y + z, z + w, w)" , test_result_t( 3, "TTTT")),
test_pack_t("foo(a)" , test_result_t( 4, "S" )),
test_pack_t("foo(a, b)" , test_result_t( 5, "SS" )),
test_pack_t("foo(a, b, c)" , test_result_t( 6, "SSS" )),
test_pack_t("foo(a, b, c, d)" , test_result_t( 7, "SSSS")),
test_pack_t("foo(a + b)" , test_result_t( 4, "S" )),
test_pack_t("foo(a + b, b + c)" , test_result_t( 5, "SS" )),
test_pack_t("foo(a + b, b + c, c + d)" , test_result_t( 6, "SSS" )),
test_pack_t("foo(a + b, b + c, c + d, d)" , test_result_t( 7, "SSSS")),
test_pack_t("foo(a, x)" , test_result_t( 8, "ST" )),
test_pack_t("foo(a, x, b)" , test_result_t( 9, "STS" )),
test_pack_t("foo(a, x, b, y)" , test_result_t(10, "STST")),
test_pack_t("foo(a + b, x + y)" , test_result_t( 8, "ST" )),
test_pack_t("foo(a + b, x + y, b + c)" , test_result_t( 9, "STS" )),
test_pack_t("foo(a + b, x + y, b + c, y + z)" , test_result_t(10, "STST")),
test_pack_t("foo(x, a)" , test_result_t(11, "TS" )),
test_pack_t("foo(x, a, y)" , test_result_t(12, "TST" )),
test_pack_t("foo(x, a, y, b)" , test_result_t(13, "TSTS")),
test_pack_t("foo(x + y, a + b)" , test_result_t(11, "TS" )),
test_pack_t("foo(x + y, a + b, y + z)" , test_result_t(12, "TST" )),
test_pack_t("foo(x + y, a + b, y + z, b + c)" , test_result_t(13, "TSTS")),
test_pack_t("foo(x, y, a, b)" , test_result_t(14, "TTSS")),
test_pack_t("foo(a, b, x, y)" , test_result_t(15, "SSTT")),
test_pack_t("foo(a, x, y, b)" , test_result_t(16, "STTS")),
test_pack_t("foo(x, a, b, y)" , test_result_t(17, "TSST")),
test_pack_t("foo(x + y, y + z, a + b, b + c)" , test_result_t(14, "TTSS")),
test_pack_t("foo(a + b, b + c, x + y, y + z)" , test_result_t(15, "SSTT")),
test_pack_t("foo(a + b, x + y, y + z, b + c)" , test_result_t(16, "STTS")),
test_pack_t("foo(x + y, a + b, b + c, y + z)" , test_result_t(17, "TSST"))
};
static const std::size_t test_pack_list_size = sizeof(test_pack_list) / sizeof(test_pack_t);
std::deque<expression_t> expression_list;
for (std::size_t i = 0; i < test_pack_list_size; ++i)
{
expression_t expression;
expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser;
if (!parser.compile(test_pack_list[i].first, expression))
{
printf("run_test18() - (12) Overload VarArg Error: %s Expression: %s\n",
parser.error().c_str(),
test_pack_list[i].first.c_str());
return false;
}
else
expression_list.push_back(expression);
}
bool failure = false;
for (std::size_t i = 0; i < expression_list.size(); ++i)
{
ovrld_func.clear();
if (T(1) != expression_list[i].value())
{
printf("run_test18() - Error in evaluation! (12) Expression: %s\n",
test_pack_list[i].first.c_str());
failure = true;
}
if (ovrld_func.current_ps_index != test_pack_list[i].second.ps_index)
{
printf("run_test18() - Error with ps_index (12) Expression: %s Expected: %d Got: %d\n",
test_pack_list[i].first.c_str(),
static_cast<int>(test_pack_list[i].second.ps_index),
static_cast<int>(ovrld_func.current_ps_index));
failure = true;
}
if (ovrld_func.current_param_seq != test_pack_list[i].second.param_seq)
{
printf("run_test18() - Error with parameter seq (12) Expression: %s Expected: %s Got: %s\n",
test_pack_list[i].first.c_str(),
test_pack_list[i].second.param_seq.c_str(),
ovrld_func.current_param_seq.c_str());
failure = true;
}
::fflush(stdout);
}
if (failure)
return false;
}
{
typedef exprtk::expression<T> expression_t;
std::string a = "a";
std::string b = "b";
std::string c = "c";
std::string d = "d";
std::string result = "";
T x = T(1.1);
T y = T(2.2);
T z = T(3.3);
T w = T(4.4);
overload_func<T> ovrld_func
(
"S:T|S:TT|S:TTT|S:TTTT|"
"S:S|S:SS|S:SSS|S:SSSS|"
"S:ST|S:STS|S:STST|"
"S:TS|S:TST|S:TSTS|"
"S:TTSS|S:SSTT|S:STTS|S:TSST"
);
exprtk::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);
symbol_table.add_variable ("w",w);
symbol_table.add_stringvar("a",a);
symbol_table.add_stringvar("b",b);
symbol_table.add_stringvar("c",c);
symbol_table.add_stringvar("d",d);
symbol_table.add_stringvar("result",result);
symbol_table.add_function("foo",ovrld_func);
typedef typename overload_func<T>::test_result_t test_result_t;
typedef std::pair<std::string, typename overload_func<T>::test_result_t> test_pack_t;
static const test_pack_t test_pack_list[] =
{
test_pack_t("result := foo(x)" , test_result_t( 0, "T" )),
test_pack_t("result := foo(x, y)" , test_result_t( 1, "TT" )),
test_pack_t("result := foo(x, y, z)" , test_result_t( 2, "TTT" )),
test_pack_t("result := foo(x, y, z, w)" , test_result_t( 3, "TTTT")),
test_pack_t("result := foo(x + y)" , test_result_t( 0, "T" )),
test_pack_t("result := foo(x + y, y + z)" , test_result_t( 1, "TT" )),
test_pack_t("result := foo(x + y, y + z, z + w)" , test_result_t( 2, "TTT" )),
test_pack_t("result := foo(x + y, y + z, z + w, w)" , test_result_t( 3, "TTTT")),
test_pack_t("result := foo(a)" , test_result_t( 4, "S" )),
test_pack_t("result := foo(a, b)" , test_result_t( 5, "SS" )),
test_pack_t("result := foo(a, b, c)" , test_result_t( 6, "SSS" )),
test_pack_t("result := foo(a, b, c, d)" , test_result_t( 7, "SSSS")),
test_pack_t("result := foo(a + b)" , test_result_t( 4, "S" )),
test_pack_t("result := foo(a + b, b + c)" , test_result_t( 5, "SS" )),
test_pack_t("result := foo(a + b, b + c, c + d)" , test_result_t( 6, "SSS" )),
test_pack_t("result := foo(a + b, b + c, c + d, d)" , test_result_t( 7, "SSSS")),
test_pack_t("result := foo(a, x)" , test_result_t( 8, "ST" )),
test_pack_t("result := foo(a, x, b)" , test_result_t( 9, "STS" )),
test_pack_t("result := foo(a, x, b, y)" , test_result_t(10, "STST")),
test_pack_t("result := foo(a + b, x + y)" , test_result_t( 8, "ST" )),
test_pack_t("result := foo(a + b, x + y, b + c)" , test_result_t( 9, "STS" )),
test_pack_t("result := foo(a + b, x + y, b + c, y + z)" , test_result_t(10, "STST")),
test_pack_t("result := foo(x, a)" , test_result_t(11, "TS" )),
test_pack_t("result := foo(x, a, y)" , test_result_t(12, "TST" )),
test_pack_t("result := foo(x, a, y, b)" , test_result_t(13, "TSTS")),
test_pack_t("result := foo(x + y, a + b)" , test_result_t(11, "TS" )),
test_pack_t("result := foo(x + y, a + b, y + z)" , test_result_t(12, "TST" )),
test_pack_t("result := foo(x + y, a + b, y + z, b + c)" , test_result_t(13, "TSTS")),
test_pack_t("result := foo(x, y, a, b)" , test_result_t(14, "TTSS")),
test_pack_t("result := foo(a, b, x, y)" , test_result_t(15, "SSTT")),
test_pack_t("result := foo(a, x, y, b)" , test_result_t(16, "STTS")),
test_pack_t("result := foo(x, a, b, y)" , test_result_t(17, "TSST")),
test_pack_t("result := foo(x + y, y + z, a + b, b + c)" , test_result_t(14, "TTSS")),
test_pack_t("result := foo(a + b, b + c, x + y, y + z)" , test_result_t(15, "SSTT")),
test_pack_t("result := foo(a + b, x + y, y + z, b + c)" , test_result_t(16, "STTS")),
test_pack_t("result := foo(x + y, a + b, b + c, y + z)" , test_result_t(17, "TSST"))
};
static const std::size_t test_pack_list_size = sizeof(test_pack_list) / sizeof(test_pack_t);
std::deque<expression_t> expression_list;
for (std::size_t i = 0; i < test_pack_list_size; ++i)
{
expression_t expression;
expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser;
if (!parser.compile(test_pack_list[i].first, expression))
{
printf("run_test18() - (13) Overload VarArg Error: %s Expression: %s\n",
parser.error().c_str(),
test_pack_list[i].first.c_str());
return false;
}
else
expression_list.push_back(expression);
}
bool failure = false;
for (std::size_t i = 0; i < expression_list.size(); ++i)
{
ovrld_func.clear();
result = "";
expression_list[i].value();
if (result != "string result")
{
printf("run_test18() - Error in evaluation! (13) Expression: %s\n",
test_pack_list[i].first.c_str());
failure = true;
}
if (ovrld_func.current_ps_index != test_pack_list[i].second.ps_index)
{
printf("run_test18() - Error with ps_index (13) Expression: %s Expected: %d Got: %d\n",
test_pack_list[i].first.c_str(),
static_cast<int>(test_pack_list[i].second.ps_index),
static_cast<int>(ovrld_func.current_ps_index));
failure = true;
}
if (ovrld_func.current_param_seq != test_pack_list[i].second.param_seq)
{
printf("run_test18() - Error with parameter seq (13) Expression: %s Expected: %s Got: %s\n",
test_pack_list[i].first.c_str(),
test_pack_list[i].second.param_seq.c_str(),
ovrld_func.current_param_seq.c_str());
failure = true;
}
}
if (failure)
return false;
}
return true; return true;
} }
@ -7826,6 +8512,126 @@ inline bool run_test20()
} }
} }
{
T var;
std::string str;
std::vector<T> vec(10,0.0);
typedef exprtk::symbol_table<T> symbol_table_t;
bool result = true;
{
symbol_table_t symbol_table;
symbol_table.add_variable ("val",var);
symbol_table.add_stringvar("str",str);
symbol_table.add_vector ("vec",vec);
if (symbol_table.get_variable("val") == 0 || !symbol_table.symbol_exists("val"))
{
printf("run_test20() - [3] Failed to get 'val' from symbol_table\n");
result = false;
}
if (symbol_table.get_stringvar("str") == 0 || !symbol_table.symbol_exists("str"))
{
printf("run_test20() - [3] Failed to get 'str' from symbol_table\n");
result = false;
}
if (symbol_table.get_vector("vec") == 0 || !symbol_table.symbol_exists("vec"))
{
printf("run_test20() - [3] Failed to get 'vec' from symbol_table\n");
result = false;
}
}
if (!result)
return result;
{
symbol_table_t symbol_table;
symbol_table.add_variable("val",var);
if (symbol_table.get_variable("val") == 0 || !symbol_table.symbol_exists("val"))
{
printf("run_test20() - [4] Failed to get 'val' from symbol_table\n");
result = false;
}
if (symbol_table.get_stringvar("str") != 0 || symbol_table.symbol_exists("str"))
{
printf("run_test20() - [4] Failed to get 'str' from symbol_table\n");
result = false;
}
if (symbol_table.get_vector("vec") != 0 || symbol_table.symbol_exists("vec"))
{
printf("run_test20() - [4] Failed to get 'vec' from symbol_table\n");
result = false;
}
}
if (!result)
return result;
{
symbol_table_t symbol_table;
symbol_table.add_stringvar("str",str);
if (symbol_table.get_stringvar("str") == 0 || !symbol_table.symbol_exists("str"))
{
printf("run_test20() - [5] Failed to get 'str' from symbol_table\n");
result = false;
}
if (symbol_table.get_variable("val") != 0 || symbol_table.symbol_exists("val"))
{
printf("run_test20() - [5] Failed to get 'val' from symbol_table\n");
result = false;
}
if (symbol_table.get_vector("vec") != 0 || symbol_table.symbol_exists("vec"))
{
printf("run_test20() - [5] Failed to get 'vec' from symbol_table\n");
result = false;
}
}
if (!result)
return result;
{
symbol_table_t symbol_table;
symbol_table.add_vector("vec",vec);
if (symbol_table.get_vector("vec") == 0 || !symbol_table.symbol_exists("vec"))
{
printf("run_test20() - [6] Failed to get 'vec' from symbol_table\n");
result = false;
}
if (symbol_table.get_variable("val") != 0 || symbol_table.symbol_exists("val"))
{
printf("run_test20() - [6] Failed to get 'val' from symbol_table\n");
result = false;
}
if (symbol_table.get_stringvar("str") != 0 || symbol_table.symbol_exists("str"))
{
printf("run_test20() - [6] Failed to get 'str' from symbol_table\n");
result = false;
}
}
if (!result)
return result;
}
return true; return true;
} }

View File

@ -428,8 +428,8 @@ of C++ compilers:
| [r0:r1] | The closed interval [r0,r1] of the specified string. | | [r0:r1] | The closed interval [r0,r1] of the specified string. |
| | eg: Given a string x with a value of 'abcdefgh' then: | | | eg: Given a string x with a value of 'abcdefgh' then: |
| | 1. x[1:4] == 'bcde' | | | 1. x[1:4] == 'bcde' |
| | 2. x[ :5] == x[:5] == 'abcdef' | | | 2. x[ :5] == x[:10 / 2] == 'abcdef' |
| | 3. x[3: ] == x[3:] =='cdefgh' | | | 3. x[2 + 1: ] == x[3:] =='defgh' |
| | 4. x[ : ] == x[:] == 'abcdefgh' | | | 4. x[ : ] == x[:] == 'abcdefgh' |
| | 5. x[4/2:3+2] == x[2:5] == 'cdef' | | | 5. x[4/2:3+2] == x[2:5] == 'cdef' |
| | | | | |
@ -706,6 +706,61 @@ This allows for the original element to be modified independently of
the expression instance and to also allow the expression to be the expression instance and to also allow the expression to be
evaluated using the current value of the element. evaluated using the current value of the element.
Note: Any variable reference provided to a given symbol_table
instance, must have a life time at least as long as the life-time of
the symbol_table instance. In the event the variable reference is
invalidated before the symbol_table or any dependent expression
instances have been destructed, then any associated expression
evaluations or variable referencing via the symbol_table instance will
result in undefined behaviour.
The following bit of code instantiates a symbol_table and expression
instance, then proceeds to demonstrate various ways in which
references to variables can be added to the symbol_table, and how
those references are subsequently invalidated resulting in various
forms of undefined behaviour.
typedef exprtk::symbol_table<double> symbol_table_t;
symbol_table_t symbol_table;
expression_t expression;
{
double x = 123.4567;
symbol_table.add_variable("x", x);
} // Reference to variable x has been invalidated
std::deque<double> y {1.1, 2.2, 3.3};
symbol_table.add_variable("y", y.back());
y.pop_back(); // Reference to variable y has been invalidated
std::vector<double> z {4.4, 5.5, 6.6};
symbol_table.add_variable("z", z.front());
z.erase(z.begin());
// Reference to variable z has been invalidated
double* w = new double(123.456);
symbol_table.add_variable("w", *w);
delete w; // Reference to variable w has been invalidated
const std::string expression_str = "x + y / z * w";
// Compilation of expression will succeed
parser.compile(expression_str,expression);
expression.value();
// Evaluation will result in undefined behaviour
symbol_table.get_variable("x")->ref() = 135.791;
// Assignment will result in undefined behaviour
The example below demonstrates the relationship between variables, The example below demonstrates the relationship between variables,
symbol_table and expression. Note the variables are modified as they symbol_table and expression. Note the variables are modified as they
normally would in a program, and when the expression is evaluated the normally would in a program, and when the expression is evaluated the
@ -865,7 +920,7 @@ The above denoted AST will be evaluated in the following order:
Generally an expression in ExprTk can be thought of as a free function Generally an expression in ExprTk can be thought of as a free function
similar to those found in imperative languages. This form of pseudo similar to those found in imperative languages. This form of pseudo
function will have a name, it may have a set of one or more inputs and function will have a name, it may have a set of one or more inputs and
will return at least one value as its result. Futhermore the function will return at least one value as its result. Furthermore the function
when invoked, may cause a side-effect that changes the state of the when invoked, may cause a side-effect that changes the state of the
host program. host program.
@ -968,7 +1023,7 @@ copied, it will then result in two or more identical expressions
utilizing the exact same references for variables. This obviously is utilizing the exact same references for variables. This obviously is
not the default assumed scenario and will give rise to non-obvious not the default assumed scenario and will give rise to non-obvious
behaviours when using the expressions in various contexts such as behaviours when using the expressions in various contexts such as
muli-threading et al. multi-threading et al.
The prescribed method for cloning an expression is to compile it from The prescribed method for cloning an expression is to compile it from
its string form. Doing so will allow the 'user' to properly consider its string form. Doing so will allow the 'user' to properly consider
@ -1260,7 +1315,7 @@ in a statement will cause it to have a side-effect:
(b) Invoking a user-defined function that has side-effects (b) Invoking a user-defined function that has side-effects
The following are examples of expressions where the side-effect status The following are examples of expressions where the side-effect status
of the statements (or sub-exressions) within the expressions have been of the statements (sub-expressions) within the expressions have been
noted: noted:
+-+----------------------+------------------------------+ +-+----------------------+------------------------------+
@ -1537,7 +1592,7 @@ zero. The following are examples of variable definitions:
var y := 3; var y := 3;
(c) Initialise z to the expression (c) Initialise z to the expression
var z := if (max(1,x + y) > 2,w,v); var z := if (max(1, x + y) > 2, w, v);
(2) Vector Definition (2) Vector Definition
@ -1552,7 +1607,7 @@ zero. The following are examples of vector definitions:
var x[3] := {}; var x[3] := {};
(c) Initialise all values to given expression (c) Initialise all values to given expression
var x[3] := [123 + 3y + sin(w/z)]; var x[3] := [123 + 3y + sin(w / z)];
(d) Initialise the first two values, all other elements to zero (d) Initialise the first two values, all other elements to zero
var x[3] := { 1 + x[2], sin(y[0] / x[]) + 3 }; var x[3] := { 1 + x[2], sin(y[0] / x[]) + 3 };
@ -1814,15 +1869,16 @@ embedded into the expression.
There are five types of function interface: There are five types of function interface:
+---+----------------------+-------------+----------------------+ +---+----------------------+--------------+----------------------+
| # | Name | Return Type | Input Types | | # | Name | Return Type | Input Types |
+---+----------------------+-------------+----------------------+ +---+----------------------+--------------+----------------------+
| 1 | ifunction | Scalar | Scalar | | 1 | ifunction | Scalar | Scalar |
| 2 | ivararg_function | Scalar | Scalar | | 2 | ivararg_function | Scalar | Scalar |
| 3 | igeneric_function | Scalar | Scalar,Vector,String | | 3 | igeneric_function | Scalar | Scalar,Vector,String |
| 4 | igeneric_function II | String | Scalar,Vector,String | | 4 | igeneric_function II | String | Scalar,Vector,String |
| 5 | function_compositor | Scalar | Scalar | | 5 | igeneric_function III| String/Scalar| Scalar,Vector,String |
+---+----------------------+-------------+----------------------+ | 6 | function_compositor | Scalar | Scalar |
+---+----------------------+--------------+----------------------+
(1) ifunction (1) ifunction
This interface supports zero to 20 input parameters of only the scalar This interface supports zero to 20 input parameters of only the scalar
@ -2198,7 +2254,60 @@ as follows:
(4) Scalar (4) String (4) Scalar (4) String
(5) function_compositor (5) igeneric_function III
In this section we will discuss an extension of the igeneric_function
interface that will allow for the overloading of a user defined custom
function, where by it can return either a scalar or string value type
depending on the input parameter sequence with which the function is
invoked.
template <typename T>
struct foo : public exprtk::igeneric_function<T>
{
typedef typename exprtk::igeneric_function<T>::parameter_list_t
parameter_list_t;
foo()
: exprtk::igeneric_function<T>
(
"T:T|S:TS",
igfun_t::e_rtrn_overload
)
{}
// Scalar value returning invocations
inline T operator()(const std::size_t& ps_index,
parameter_list_t parameters)
{
...
}
// String value returning invocations
inline T operator()(const std::size_t& ps_index,
std::string& result,
parameter_list_t& parameters)
{
...
}
};
In the example above the custom user defined function "foo" can be
invoked by using either one of two input parameter sequences, which
are defined as follows:
Sequence-0 Sequence-1
'T' -> T 'TS' -> S
(1) Scalar (1) Scalar
(2) String
The parameter sequence definitions are identical to the previously
define igeneric_function, with the exception of the inclusion of the
return type - which can only be either a scalar T or a string S.
(6) function_compositor
The function compositor is a factory that allows one to define and The function compositor is a factory that allows one to define and
construct a function using ExprTk syntax. The functions are limited to construct a function using ExprTk syntax. The functions are limited to
returning a single scalar value and consuming up to six parameters as returning a single scalar value and consuming up to six parameters as
@ -2355,11 +2464,11 @@ default be assumed to have side-effects and hence will not participate
in constant folding optimisations. in constant folding optimisations.
In the following example, a two input parameter free function named In the following example, a two input parameter free function named
'compute', and a three input parameter lambda will be registered with 'compute1', and a three input parameter lambda named 'compute2' will
the given symbol_table instance: be registered with the given symbol_table instance:
double compute(double v0, double v1) double compute1(double v0, double v1)
{ {
return 2.0 * v0 + v1 / 3.0; return 2.0 * v0 + v1 / 3.0;
} }
@ -2372,12 +2481,12 @@ the given symbol_table instance:
symbol_table_t symbol_table; symbol_table_t symbol_table;
symbol_table.add_function("compute", compute); symbol_table.add_function("compute1", compute1);
symbol_table.add_function("lambda",
[](double v0, double v1, double v2) -> double
{ return v0 / v1 + v2; });
symbol_table.add_function(
"compute2",
[](double v0, double v1, double v2) -> double
{ return v0 / v1 + v2; });
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2715,7 +2824,7 @@ expression being compiled.
This can become problematic, as in the default scenario it is assumed This can become problematic, as in the default scenario it is assumed
the symbol_table that is registered with the expression instance will the symbol_table that is registered with the expression instance will
already posses the externally available variables, functions and already possess the externally available variables, functions and
constants needed during the compilation of the expression. constants needed during the compilation of the expression.
In the event there are symbols in the expression that can't be mapped In the event there are symbols in the expression that can't be mapped
@ -2838,7 +2947,7 @@ after which the expression itself can be evaluated.
for (auto& var_name : variable_list) for (auto& var_name : variable_list)
{ {
T& v = symbol_table.variable_ref(var_name); T& v = unknown_var_symbol_table.variable_ref(var_name);
v = ...; v = ...;
} }
@ -2999,6 +3108,24 @@ constructor of the user defined USR.
Note: The primary symbol table for an expression is the first symbol Note: The primary symbol table for an expression is the first symbol
table to be registered with that instance of the expression. table to be registered with that instance of the expression.
Note: For a successful symbol resolution using the normal USR all of
the following are required:
(1) Only if successful shall the process method return TRUE
(2) The default_value parameter will have been set
(3) The error_message parameter will be empty
(4) usr_symbol_type input parameter field will be set to either:
(*) e_usr_variable_type
(*) e_usr_constant_type
Note: For a successful symbol resolution using the extended USR all of
the following are required:
(1) Only if successful shall the process method return TRUE
(2) symbol_table parameter will have had the newly resolved
variable or string added to it
(3) error_message parameter will be empty
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 19 - ENABLING & DISABLING FEATURES] [SECTION 19 - ENABLING & DISABLING FEATURES]
@ -3710,13 +3837,13 @@ follows:
if (exprtk::collect_variables(expression, variable_list)) if (exprtk::collect_variables(expression, variable_list))
{ {
for (auto var : variable_list) for (const auto& var : variable_list)
{ {
... ...
} }
} }
else else
printf("An error occured."); printf("An error occurred.");
(b) collect_functions (b) collect_functions
@ -3734,13 +3861,13 @@ follows:
if (exprtk::collect_functions(expression, function_list)) if (exprtk::collect_functions(expression, function_list))
{ {
for (auto func : function_list) for (const auto& func : function_list)
{ {
... ...
} }
} }
else else
printf("An error occured."); printf("An error occurred.");
Note: When either the 'collect_variables' or 'collect_functions' free Note: When either the 'collect_variables' or 'collect_functions' free
@ -3752,10 +3879,10 @@ true.
Note: The default interface provided for both the collect_variables Note: The default interface provided for both the collect_variables
and collect_functions free_functions, assumes that expressions will and collect_functions free_functions, assumes that expressions will
only be utilising the ExprTk reserved funnctions (eg: abs, cos, min only be utilising the ExprTk reserved functions (eg: abs, cos, min
etc). When user defined functions are to be used in an expression, a etc). When user defined functions are to be used in an expression, a
symbol_table instance containing said functions can be passed to symbol_table instance containing said functions can be passed to
either routine, and will be incorparated during the compilation and either routine, and will be incorporated during the compilation and
Dependent Entity Collection processes. In the following example, a Dependent Entity Collection processes. In the following example, a
user defined free function named 'foo' is registered with a user defined free function named 'foo' is registered with a
symbol_table. Finally the symbol_table instance and associated symbol_table. Finally the symbol_table instance and associated
@ -3779,13 +3906,13 @@ expression string are passed to the exprtk::collect_functions routine.
if (exprtk::collect_functions(expression, sym_tab, function_list)) if (exprtk::collect_functions(expression, sym_tab, function_list))
{ {
for (auto func : function_list) for (const auto& func : function_list)
{ {
... ...
} }
} }
else else
printf("An error occured."); printf("An error occurred.");
(c) compute (c) compute
@ -3910,7 +4037,7 @@ function is as follows:
// Differentiate expression at 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);
// Differentiate expression where value x = 45.6 using name // Differentiate expression where value x = 45.6 using name
// of the x variable // of the x variable
@ -3988,7 +4115,7 @@ is as follows:
// Third derivative of expression where value of x = 12.3 using a // Third derivative of expression where value of x = 12.3 using a
// reference to the x variable // reference to the x variable
x = T(12.3); x = T(12.3);
T derivative1 = exprtk::third_derivative(expression,x); T derivative1 = exprtk::third_derivative(expression, x);
// Third derivative of expression where value of x = 45.6 using // Third derivative of expression where value of x = 45.6 using
// name of the x variable // name of the x variable
@ -4168,9 +4295,11 @@ into account when using ExprTk:
function names are case-insensitive. function names are case-insensitive.
(07) Variable, vector, string variable and function names must begin (07) Variable, vector, string variable and function names must begin
with a letter (A-Z or a-z), then can be comprised of any with a letter (A-Z or a-z), then can be comprised of any
combination of letters, digits, underscores and dots. (eg: x, combination of letters, digits, underscores and dots, ending in
var1 or power_func99, person.age, item.size.0) either a letter (A-Z or a-z), digit or underscore. (eg: x, y2,
var1, power_func99, person.age, item.size.0). The associated
regex pattern is: [a-zA-Z]([a-zA-Z0-9_.]*|[a-zA-Z0-9_])
(08) Expression lengths and sub-expression lists are limited only by (08) Expression lengths and sub-expression lists are limited only by
storage capacity. storage capacity.