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

This commit is contained in:
Arash Partow 2020-01-01 00:00:00 +00:00 committed by ArashPartow
parent f32d2b4bbb
commit c7c219480d
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 *
# * *
# * Author: Arash Partow (1999-2018) *
# * Author: Arash Partow (1999-2020) *
# * URL: http://www.partow.net/programming/exprtk/index.html *
# * *
# * Copyright notice: *
@ -15,37 +15,18 @@
#
COMPILER = -c++
#COMPILER = -clang
OPTIMIZATION_OPT = -O1
BASE_OPTIONS = -pedantic-errors -Wall -Wextra -Werror -Wno-long-long
OPTIONS = $(BASE_OPTIONS) $(OPTIMIZATION_OPT)
LINKER_OPT = -L/usr/lib -lstdc++ -lm
ASAN_OPT = -g -fsanitize=address -fno-omit-frame-pointer
MSAN_OPT = -g -fsanitize=memory -fno-omit-frame-pointer
LSAN_OPT = -g -fsanitize=leak -fno-omit-frame-pointer
BUILD_LIST+=exprtk_test
BUILD_LIST+=exprtk_benchmark
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
COMPILER := -c++
#COMPILER := -clang++
OPTIMIZATION_OPT := -O1
BASE_OPTIONS := -pedantic-errors -Wall -Wextra -Werror -Wno-long-long
OPTIONS := $(BASE_OPTIONS) $(OPTIMIZATION_OPT)
LINKER_OPT := -L/usr/lib -lstdc++ -lm
ASAN_OPT := -g -fsanitize=address -fno-omit-frame-pointer
MSAN_OPT := -g -fsanitize=memory -fno-omit-frame-pointer
LSAN_OPT := -g -fsanitize=leak -fno-omit-frame-pointer
USAN_OPT := -g -fsanitize=undefined -fno-omit-frame-pointer
BUILD_SRC := $(sort $(wildcard exprtk_*.cpp))
BUILD_LIST := $(BUILD_SRC:%.cpp=%)
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 *
* *
* ExprTk vs Native Benchmarks *
* Author: Arash Partow (1999-2018) *
* Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 7 *
* Author: Arash Partow (1999-2018) *
* Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio>
#include <string>
#include "exprtk.hpp"
@ -28,7 +29,7 @@ void logic()
typedef exprtk::expression<T> expression_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.create_variable("A");
@ -52,7 +53,7 @@ void logic()
symbol_table.get_variable("B")->ref() = T((i & 0x02) ? 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",
i,

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 8 *
* Author: Arash Partow (1999-2018) *
* Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio>
#include <string>
#include "exprtk.hpp"
@ -27,7 +28,7 @@ void composite()
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_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 typename compositor_t::function function_t;
@ -64,7 +65,7 @@ void composite()
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",
static_cast<unsigned int>(i),
@ -77,7 +78,7 @@ void composite()
return;
}
T result = expression.value();
const T result = expression.value();
printf("%s = %e\n", expression_string.c_str(), result);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 15 *
* Author: Arash Partow (1999-2018) *
* Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
@ -18,6 +18,7 @@
#include <cstdio>
#include <string>
#include "exprtk.hpp"
@ -28,7 +29,7 @@ void black_scholes_merton_model()
typedef exprtk::expression<T> expression_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 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",
callput_flag.c_str(),
s,x,t,r,v,
s, x, t, r, v,
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",
callput_flag.c_str(),
s,x,t,r,v,
s, x, t, r, v,
bsm);
}
}

View File

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

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 17 *
* Author: Arash Partow (1999-2018) *
* Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
@ -47,7 +47,7 @@ void monte_carlo_pi()
typedef exprtk::expression<T> expression_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]; "
" 4 * sum(experiments) / experiments[]; ";

View File

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

View File

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

View File

@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Examples and Unit-Tests *
* Author: Arash Partow (1999-2018) *
* Author: Arash Partow (1999-2020) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
@ -23,6 +23,7 @@
#include <deque>
#include <fstream>
#include <iostream>
#include <numeric>
#include <string>
#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+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+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>);
@ -2589,6 +2675,10 @@ inline bool run_test02()
template <typename T>
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+"
"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+"
@ -2626,9 +2716,9 @@ inline bool run_test03()
for (std::size_t r = 0; r < rounds; ++r)
{
exprtk::symbol_table<T> symbol_table_0;
exprtk::symbol_table<T> symbol_table_1;
exprtk::expression<T> expression;
symbol_table_t symbol_table_0;
symbol_table_t symbol_table_1;
expression_t expression;
std::vector<T> v;
v.resize(variable_list_size);
@ -2726,7 +2816,38 @@ inline bool run_test03()
"1 v x",
"1 v y",
"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);
@ -2734,9 +2855,9 @@ inline bool run_test03()
{
for (std::size_t i = 0; i < invalid_expr_size; ++i)
{
exprtk::symbol_table<T> symbol_table;
exprtk::expression<T> expression;
symbol_table_t symbol_table;
expression_t expression;
parser_t parser;
T x = T(0);
std::string s;
@ -2746,8 +2867,6 @@ inline bool run_test03()
symbol_table.add_stringvar("s",s);
symbol_table.add_vector ("v",v);
exprtk::parser<T> parser;
if (parser.compile(invalid_expr[i],expression))
{
printf("run_test03() - Error: [1] Invalid expression compiled successfuly. Expression: %s\n",
@ -2763,14 +2882,13 @@ inline bool run_test03()
std::string s;
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_stringvar("s",s);
symbol_table.add_vector ("v",v);
exprtk::parser<T> parser;
for (std::size_t i = 0; i < invalid_expr_size; ++i)
{
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;
@ -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[] =
{
@ -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>
inline bool run_test18()
@ -6516,6 +6851,68 @@ inline bool run_test18()
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;
@ -6648,7 +7045,7 @@ inline bool run_test18()
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());
failure = true;
@ -6659,6 +7056,295 @@ inline bool run_test18()
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;
}
@ -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;
}

View File

@ -428,8 +428,8 @@ of C++ compilers:
| [r0:r1] | The closed interval [r0,r1] of the specified string. |
| | eg: Given a string x with a value of 'abcdefgh' then: |
| | 1. x[1:4] == 'bcde' |
| | 2. x[ :5] == x[:5] == 'abcdef' |
| | 3. x[3: ] == x[3:] =='cdefgh' |
| | 2. x[ :5] == x[:10 / 2] == 'abcdef' |
| | 3. x[2 + 1: ] == x[3:] =='defgh' |
| | 4. x[ : ] == x[:] == 'abcdefgh' |
| | 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
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,
symbol_table and expression. Note the variables are modified as they
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
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
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
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
not the default assumed scenario and will give rise to non-obvious
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
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
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:
+-+----------------------+------------------------------+
@ -1537,7 +1592,7 @@ zero. The following are examples of variable definitions:
var y := 3;
(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
@ -1552,7 +1607,7 @@ zero. The following are examples of vector definitions:
var x[3] := {};
(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
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:
+---+----------------------+-------------+----------------------+
| # | Name | Return Type | Input Types |
+---+----------------------+-------------+----------------------+
| 1 | ifunction | Scalar | Scalar |
| 2 | ivararg_function | Scalar | Scalar |
| 3 | igeneric_function | Scalar | Scalar,Vector,String |
| 4 | igeneric_function II | String | Scalar,Vector,String |
| 5 | function_compositor | Scalar | Scalar |
+---+----------------------+-------------+----------------------+
+---+----------------------+--------------+----------------------+
| # | Name | Return Type | Input Types |
+---+----------------------+--------------+----------------------+
| 1 | ifunction | Scalar | Scalar |
| 2 | ivararg_function | Scalar | Scalar |
| 3 | igeneric_function | Scalar | Scalar,Vector,String |
| 4 | igeneric_function II | String | Scalar,Vector,String |
| 5 | igeneric_function III| String/Scalar| Scalar,Vector,String |
| 6 | function_compositor | Scalar | Scalar |
+---+----------------------+--------------+----------------------+
(1) ifunction
This interface supports zero to 20 input parameters of only the scalar
@ -2198,7 +2254,60 @@ as follows:
(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
construct a function using ExprTk syntax. The functions are limited to
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 the following example, a two input parameter free function named
'compute', and a three input parameter lambda will be registered with
the given symbol_table instance:
'compute1', and a three input parameter lambda named 'compute2' will
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;
}
@ -2372,12 +2481,12 @@ the given symbol_table instance:
symbol_table_t symbol_table;
symbol_table.add_function("compute", compute);
symbol_table.add_function("lambda",
[](double v0, double v1, double v2) -> double
{ return v0 / v1 + v2; });
symbol_table.add_function("compute1", compute1);
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
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.
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)
{
T& v = symbol_table.variable_ref(var_name);
T& v = unknown_var_symbol_table.variable_ref(var_name);
v = ...;
}
@ -2999,6 +3108,24 @@ constructor of the user defined USR.
Note: The primary symbol table for an expression is the first symbol
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]
@ -3710,13 +3837,13 @@ follows:
if (exprtk::collect_variables(expression, variable_list))
{
for (auto var : variable_list)
for (const auto& var : variable_list)
{
...
}
}
else
printf("An error occured.");
printf("An error occurred.");
(b) collect_functions
@ -3734,13 +3861,13 @@ follows:
if (exprtk::collect_functions(expression, function_list))
{
for (auto func : function_list)
for (const auto& func : function_list)
{
...
}
}
else
printf("An error occured.");
printf("An error occurred.");
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
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
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
user defined free function named 'foo' is registered with a
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))
{
for (auto func : function_list)
for (const auto& func : function_list)
{
...
}
}
else
printf("An error occured.");
printf("An error occurred.");
(c) compute
@ -3910,7 +4037,7 @@ function is as follows:
// Differentiate expression at value of x = 12.3 using a reference
// to the x variable
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
// of the x variable
@ -3988,7 +4115,7 @@ is as follows:
// Third derivative of expression where value of x = 12.3 using a
// reference to the x variable
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
// name of the x variable
@ -4168,9 +4295,11 @@ into account when using ExprTk:
function names are case-insensitive.
(07) Variable, vector, string variable and function names must begin
with a letter (A-Z or a-z), then can be comprised of any
combination of letters, digits, underscores and dots. (eg: x,
var1 or power_func99, person.age, item.size.0)
with a letter (A-Z or a-z), then can be comprised of any
combination of letters, digits, underscores and dots, ending in
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
storage capacity.