From 810f02a0529c62d9eb15cc8d7009b7a73ae6414f Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Mon, 1 Jan 2024 00:00:00 +0000 Subject: [PATCH] Update ExprTk 0.0.3 --- src/third_party/exprtk/Makefile | 11 +- src/third_party/exprtk/exprtk.hpp | 13472 +++++++++++----- src/third_party/exprtk/exprtk_benchmark.cpp | 93 +- .../exprtk/exprtk_simple_example_01.cpp | 7 +- .../exprtk/exprtk_simple_example_02.cpp | 25 +- .../exprtk/exprtk_simple_example_03.cpp | 7 +- .../exprtk/exprtk_simple_example_04.cpp | 52 +- .../exprtk/exprtk_simple_example_05.cpp | 11 +- .../exprtk/exprtk_simple_example_06.cpp | 13 +- .../exprtk/exprtk_simple_example_07.cpp | 5 +- .../exprtk/exprtk_simple_example_08.cpp | 27 +- .../exprtk/exprtk_simple_example_09.cpp | 180 +- .../exprtk/exprtk_simple_example_10.cpp | 57 +- .../exprtk/exprtk_simple_example_11.cpp | 17 +- .../exprtk/exprtk_simple_example_12.cpp | 40 +- .../exprtk/exprtk_simple_example_13.cpp | 51 +- .../exprtk/exprtk_simple_example_14.cpp | 21 +- .../exprtk/exprtk_simple_example_15.cpp | 61 +- .../exprtk/exprtk_simple_example_16.cpp | 33 +- .../exprtk/exprtk_simple_example_17.cpp | 7 +- .../exprtk/exprtk_simple_example_18.cpp | 53 +- .../exprtk/exprtk_simple_example_19.cpp | 52 +- .../exprtk/exprtk_simple_example_20.cpp | 109 + .../exprtk/exprtk_simple_example_21.cpp | 117 + .../exprtk/exprtk_simple_example_22.cpp | 144 + .../exprtk/exprtk_simple_example_23.cpp | 136 + .../exprtk/exprtk_simple_example_24.cpp | 143 + src/third_party/exprtk/exprtk_test.cpp | 11574 ++++++++----- src/third_party/exprtk/license.txt | 24 + src/third_party/exprtk/readme.txt | 2391 ++- 30 files changed, 19712 insertions(+), 9221 deletions(-) create mode 100644 src/third_party/exprtk/exprtk_simple_example_20.cpp create mode 100644 src/third_party/exprtk/exprtk_simple_example_21.cpp create mode 100644 src/third_party/exprtk/exprtk_simple_example_22.cpp create mode 100644 src/third_party/exprtk/exprtk_simple_example_23.cpp create mode 100644 src/third_party/exprtk/exprtk_simple_example_24.cpp create mode 100644 src/third_party/exprtk/license.txt diff --git a/src/third_party/exprtk/Makefile b/src/third_party/exprtk/Makefile index 54c776c..a8d7d28 100644 --- a/src/third_party/exprtk/Makefile +++ b/src/third_party/exprtk/Makefile @@ -2,14 +2,15 @@ # ************************************************************** # * C++ Mathematical Expression Toolkit Library * # * * -# * Author: Arash Partow (1999-2023) * +# * Author: Arash Partow (1999-2024) * # * URL: https://www.partow.net/programming/exprtk/index.html * # * * # * Copyright notice: * # * Free use of the Mathematical Expression Toolkit Library is * # * permitted under the guidelines and in accordance with the * # * most current version of the MIT License. * -# * http://www.opensource.org/licenses/MIT * +# * https://www.opensource.org/licenses/MIT * +# * SPDX-License-Identifier: MIT * # * * # ************************************************************** # @@ -17,7 +18,7 @@ COMPILER := -c++ #COMPILER := -clang++ -OPTIMIZATION_OPT := -O1 +OPTIMIZATION_OPT := -O2 -DNDEBUG BASE_OPTIONS := -pedantic-errors -Wall -Wextra -Werror -Wno-long-long OPTIONS := $(BASE_OPTIONS) $(OPTIMIZATION_OPT) LINKER_OPT := -L/usr/lib -lstdc++ -lm @@ -46,9 +47,9 @@ valgrind : fi done; pgo: exprtk_benchmark.cpp exprtk.hpp - $(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-generate -o exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT) + $(COMPILER) $(BASE_OPTIONS) -O3 -DNDEBUG -march=native -fprofile-generate -o exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT) ./exprtk_benchmark - $(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-use -o exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT) + $(COMPILER) $(BASE_OPTIONS) -O3 -DNDEBUG -march=native -fprofile-use -o exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT) clean: rm -f core.* *~ *.o *.bak *stackdump gmon.out *.gcda *.gcno *.gcnor *.gch diff --git a/src/third_party/exprtk/exprtk.hpp b/src/third_party/exprtk/exprtk.hpp index b4530ba..0971498 100644 --- a/src/third_party/exprtk/exprtk.hpp +++ b/src/third_party/exprtk/exprtk.hpp @@ -2,7 +2,7 @@ ****************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -10,6 +10,7 @@ * permitted under the guidelines and in accordance with the most * * current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * * Example expressions: * * (00) (y + x / y) * (x - y / x) * @@ -17,12 +18,12 @@ * (02) sqrt(1 - (x^2)) * * (03) 1 - sin(2 * x) + cos(pi / y) * * (04) a * exp(2 * t) + c * - * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) * + * (05) if(((x + 2) == 3) and ((y + 5) <= 9), 1 + w, 2 / z) * * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x * * (07) z := x + sin(2 * pi / y) * * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) * - * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) * - * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) * + * (09) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1) * + * (10) inrange(-2, m, +2) == if(({-2 <= m} and [m <= +2]), 1, 0) * * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) * * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] * * * @@ -42,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -67,20 +67,6 @@ namespace exprtk #define exprtk_error_location \ "exprtk.hpp:" + details::to_str(__LINE__) \ - #if defined(__GNUC__) && (__GNUC__ >= 7) - - #define exprtk_disable_fallthrough_begin \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \ - - #define exprtk_disable_fallthrough_end \ - _Pragma ("GCC diagnostic pop") \ - - #else - #define exprtk_disable_fallthrough_begin (void)0; - #define exprtk_disable_fallthrough_end (void)0; - #endif - #if __cplusplus >= 201103L #define exprtk_override override #define exprtk_final final @@ -91,6 +77,18 @@ namespace exprtk #define exprtk_delete #endif + #if __cplusplus >= 201603L + #define exprtk_fallthrough [[fallthrough]]; + #elif __cplusplus >= 201103L + #define exprtk_fallthrough [[gnu::fallthrough]]; + #else + #ifndef _MSC_VER + #define exprtk_fallthrough __attribute__ ((fallthrough)); + #else + #define exprtk_fallthrough + #endif + #endif + namespace details { typedef char char_t; @@ -218,15 +216,15 @@ namespace exprtk { const std::size_t length = std::min(s1.size(),s2.size()); - for (std::size_t i = 0; i < length; ++i) + for (std::size_t i = 0; i < length; ++i) { const char_t c1 = static_cast(std::tolower(s1[i])); const char_t c2 = static_cast(std::tolower(s2[i])); - if (c1 > c2) - return false; - else if (c1 < c2) + if (c1 < c2) return true; + else if (c2 < c1) + return false; } return s1.size() < s2.size(); @@ -317,7 +315,7 @@ namespace exprtk if (('0' <= h) && (h <= '9')) return (h - '0'); else - return static_cast(std::toupper(h) - 'A'); + return static_cast(std::toupper(h) - 'A' + 10); } template @@ -364,9 +362,9 @@ namespace exprtk } else if (parse_hex(itr1, end, *itr2)) { - itr1+= 4; - itr2+= 1; - removal_count +=4; + itr1 += 4; + itr2 += 1; + removal_count += 4; } else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } @@ -381,6 +379,7 @@ namespace exprtk (*itr2++) = (*itr1++); ++removal_count; } + continue; } else @@ -432,85 +431,85 @@ namespace exprtk }; static const std::string reserved_words[] = - { - "break", "case", "continue", "default", "false", "for", - "if", "else", "ilike", "in", "like", "and", "nand", "nor", - "not", "null", "or", "repeat", "return", "shl", "shr", - "swap", "switch", "true", "until", "var", "while", "xnor", - "xor", "&", "|" - }; + { + "assert", "break", "case", "continue", "const", "default", + "false", "for", "if", "else", "ilike", "in", "like", "and", + "nand", "nor", "not", "null", "or", "repeat", "return", + "shl", "shr", "swap", "switch", "true", "until", "var", + "while", "xnor", "xor", "&", "|" + }; static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); static const std::string reserved_symbols[] = - { - "abs", "acos", "acosh", "and", "asin", "asinh", "atan", - "atanh", "atan2", "avg", "break", "case", "ceil", "clamp", - "continue", "cos", "cosh", "cot", "csc", "default", - "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", - "expm1", "false", "floor", "for", "frac", "grad2deg", - "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", - "like", "log", "log10", "log2", "logn", "log1p", "mand", - "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", - "not", "not_equal", "null", "or", "pow", "rad2deg", - "repeat", "return", "root", "round", "roundn", "sec", "sgn", - "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", - "switch", "tan", "tanh", "true", "trunc", "until", "var", - "while", "xnor", "xor", "&", "|" - }; + { + "abs", "acos", "acosh", "and", "asin", "asinh", "assert", + "atan", "atanh", "atan2", "avg", "break", "case", "ceil", + "clamp", "continue", "const", "cos", "cosh", "cot", "csc", + "default", "deg2grad", "deg2rad", "equal", "erf", "erfc", + "exp", "expm1", "false", "floor", "for", "frac", "grad2deg", + "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", + "like", "log", "log10", "log2", "logn", "log1p", "mand", + "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", + "not", "not_equal", "null", "or", "pow", "rad2deg", + "repeat", "return", "root", "round", "roundn", "sec", "sgn", + "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", + "switch", "tan", "tanh", "true", "trunc", "until", "var", + "while", "xnor", "xor", "&", "|" + }; static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); static const std::string base_function_list[] = - { - "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", - "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", - "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", - "frac", "hypot", "iclamp", "like", "log", "log10", "log2", - "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", - "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", - "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", - "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", - "rad2deg", "grad2deg" - }; + { + "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", + "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", + "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", + "frac", "hypot", "iclamp", "like", "log", "log10", "log2", + "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", + "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", + "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", + "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", + "rad2deg", "grad2deg" + }; static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); static const std::string logic_ops_list[] = - { - "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" - }; + { + "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" + }; static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); static const std::string cntrl_struct_list[] = - { - "if", "switch", "for", "while", "repeat", "return" - }; + { + "if", "switch", "for", "while", "repeat", "return" + }; static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); static const std::string arithmetic_ops_list[] = - { - "+", "-", "*", "/", "%", "^" - }; + { + "+", "-", "*", "/", "%", "^" + }; static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); static const std::string assignment_ops_list[] = - { - ":=", "+=", "-=", - "*=", "/=", "%=" - }; + { + ":=", "+=", "-=", + "*=", "/=", "%=" + }; static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); static const std::string inequality_ops_list[] = - { - "<", "<=", "==", - "=", "!=", "<>", - ">=", ">" - }; + { + "<", "<=", "==", + "=", "!=", "<>", + ">=", ">" + }; static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); @@ -646,7 +645,7 @@ namespace exprtk } } else if (data_end == d_itr) - return true; + break; if ((data_end == d_itr) || (null_itr == nd_itr)) return false; @@ -661,23 +660,27 @@ namespace exprtk inline bool wc_match(const std::string& wild_card, const std::string& str) { - return match_impl( + return match_impl + ( wild_card.data(), wild_card.data() + wild_card.size(), str.data(), str.data() + str.size(), - '*', '?'); + '*', '?' + ); } inline bool wc_imatch(const std::string& wild_card, const std::string& str) { - return match_impl( + return match_impl + ( wild_card.data(), wild_card.data() + wild_card.size(), str.data(), str.data() + str.size(), - '*', '?'); + '*', '?' + ); } inline bool sequence_match(const std::string& pattern, @@ -750,13 +753,55 @@ namespace exprtk ); } - static const double pow10[] = { - 1.0, - 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, - 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, - 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, - 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 - }; + template + struct set_zero_value_impl + { + static inline void process(T* base_ptr, const std::size_t size) + { + const T zero = T(0); + for (std::size_t i = 0; i < size; ++i) + { + base_ptr[i] = zero; + } + } + }; + + #define pod_set_zero_value(T) \ + template <> \ + struct set_zero_value_impl \ + { \ + static inline void process(T* base_ptr, const std::size_t size) \ + { std::memset(base_ptr, 0x00, size * sizeof(T)); } \ + }; \ + + pod_set_zero_value(float ) + pod_set_zero_value(double ) + pod_set_zero_value(long double) + + #ifdef pod_set_zero_value + #undef pod_set_zero_value + #endif + + template + inline void set_zero_value(T* data, const std::size_t size) + { + set_zero_value_impl::process(data,size); + } + + template + inline void set_zero_value(std::vector& v) + { + set_zero_value(v.data(),v.size()); + } + + static const double pow10[] = + { + 1.0, + 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, + 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, + 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, + 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 + }; static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); @@ -789,17 +834,17 @@ namespace exprtk number_type() {} }; - #define exprtk_register_real_type_tag(T) \ - template <> struct number_type \ - { typedef real_type_tag type; number_type() {} }; \ + #define exprtk_register_real_type_tag(T) \ + template <> struct number_type \ + { typedef real_type_tag type; number_type() {} }; \ - #define exprtk_register_int_type_tag(T) \ - template <> struct number_type \ - { typedef int_type_tag type; number_type() {} }; \ + #define exprtk_register_int_type_tag(T) \ + template <> struct number_type \ + { typedef int_type_tag type; number_type() {} }; \ + exprtk_register_real_type_tag(float ) exprtk_register_real_type_tag(double ) exprtk_register_real_type_tag(long double) - exprtk_register_real_type_tag(float ) exprtk_register_int_type_tag(short ) exprtk_register_int_type_tag(int ) @@ -848,6 +893,12 @@ namespace exprtk return static_cast<_int64_t>(v); } + template + inline _uint64_t to_uint64_impl(const T v, real_type_tag) + { + return static_cast<_uint64_t>(v); + } + template inline bool is_true_impl(const T v) { @@ -982,8 +1033,8 @@ namespace exprtk else return (T(-0.5) * v + T(1)) * v; } - else - return std::numeric_limits::quiet_NaN(); + + return std::numeric_limits::quiet_NaN(); } template @@ -993,22 +1044,21 @@ namespace exprtk { return std::log(T(1) + v); } - else - return std::numeric_limits::quiet_NaN(); + + return std::numeric_limits::quiet_NaN(); } template inline T root_impl(const T v0, const T v1, real_type_tag) { - if (v1 < T(0)) - return std::numeric_limits::quiet_NaN(); - - const std::size_t n = static_cast(v1); - - if ((v0 < T(0)) && (0 == (n % 2))) - return std::numeric_limits::quiet_NaN(); + if (v0 < T(0)) + { + return (v1 == std::trunc(v1)) && (modulus_impl(v1, T(2), real_type_tag()) != T(0)) ? + -std::pow(abs_impl(v0, real_type_tag()), T(1) / v1) : + std::numeric_limits::quiet_NaN(); + } - return std::pow(v0, T(1) / n); + return std::pow(v0, T(1) / v1); } template @@ -1193,9 +1243,9 @@ namespace exprtk #define exprtk_define_erf(TT, impl) \ inline TT erf_impl(const TT v) { return impl(v); } \ - exprtk_define_erf( float,::erff) - exprtk_define_erf( double,::erf ) - exprtk_define_erf(long double,::erfl) + exprtk_define_erf(float , ::erff) + exprtk_define_erf(double , ::erf ) + exprtk_define_erf(long double, ::erfl) #undef exprtk_define_erf #endif @@ -1204,13 +1254,14 @@ namespace exprtk { #if defined(_MSC_VER) && (_MSC_VER < 1900) // Credits: Abramowitz & Stegun Equations 7.1.25-28 - static const T c[] = { - T( 1.26551223), T(1.00002368), - T( 0.37409196), T(0.09678418), - T(-0.18628806), T(0.27886807), - T(-1.13520398), T(1.48851587), - T(-0.82215223), T(0.17087277) - }; + static const T c[] = + { + T( 1.26551223), T(1.00002368), + T( 0.37409196), T(0.09678418), + T(-0.18628806), T(0.27886807), + T(-1.13520398), T(1.48851587), + T(-0.82215223), T(0.17087277) + }; const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); @@ -1262,10 +1313,7 @@ namespace exprtk template inline T ncdf_impl(const T v, real_type_tag) { - const T cnd = T(0.5) * (T(1) + - erf_impl(abs_impl(v,real_type_tag()) / - T(numeric::constant::sqrt2),real_type_tag())); - return (v < T(0)) ? (T(1) - cnd) : cnd; + return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag()); } template @@ -1289,12 +1337,47 @@ namespace exprtk return sinc_impl(static_cast(v),real_type_tag()); } + #if __cplusplus >= 201103L + template + inline T acosh_impl(const T v, real_type_tag) + { + return std::acosh(v); + } + + template + inline T asinh_impl(const T v, real_type_tag) + { + return std::asinh(v); + } + + template + inline T atanh_impl(const T v, real_type_tag) + { + return std::atanh(v); + } + #else + template + inline T acosh_impl(const T v, real_type_tag) + { + return std::log(v + std::sqrt((v * v) - T(1))); + } + + template + inline T asinh_impl(const T v, real_type_tag) + { + return std::log(v + std::sqrt((v * v) + T(1))); + } + + template + inline T atanh_impl(const T v, real_type_tag) + { + return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); + } + #endif + template inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } - template inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); } template inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } - template inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); } template inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } - template inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); } template inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } template inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } template inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } @@ -1390,6 +1473,13 @@ namespace exprtk return to_int64_impl(v, num_type); } + template + inline _uint64_t to_uint64(const T v) + { + const typename details::number_type::type num_type; + return to_uint64_impl(v, num_type); + } + template inline bool is_nan(const T v) { @@ -1629,38 +1719,38 @@ namespace exprtk { static const double fract10[] = { - 0.0, - 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010, - 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020, - 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030, - 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040, - 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050, - 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060, - 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070, - 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080, - 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090, - 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100, - 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110, - 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120, - 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130, - 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140, - 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150, - 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160, - 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170, - 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180, - 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190, - 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200, - 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210, - 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220, - 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230, - 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240, - 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250, - 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260, - 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270, - 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280, - 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290, - 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300, - 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 + 0.0, + 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010, + 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020, + 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030, + 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040, + 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050, + 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060, + 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070, + 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080, + 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090, + 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100, + 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110, + 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120, + 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130, + 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140, + 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150, + 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160, + 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170, + 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180, + 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190, + 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200, + 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210, + 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220, + 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230, + 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240, + 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250, + 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260, + 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270, + 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280, + 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290, + 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300, + 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 }; static const int fract10_size = static_cast(sizeof(fract10) / sizeof(double)); @@ -1710,7 +1800,6 @@ namespace exprtk if (length <= 4) { - exprtk_disable_fallthrough_begin switch (length) { #ifdef exprtk_use_lut @@ -1723,17 +1812,19 @@ namespace exprtk return_result = false; \ break; \ } \ + exprtk_fallthrough \ #else - #define exprtk_process_digit \ - if ((digit = (*itr++ - zero)) < 10) \ - result = result * T(10) + digit; \ - else \ - { \ - return_result = false; \ - break; \ - } \ + #define exprtk_process_digit \ + if ((digit = (*itr++ - zero)) < 10) \ + result = result * T(10) + digit; \ + else \ + { \ + return_result = false; \ + break; \ + } \ + exprtk_fallthrough \ #endif @@ -1748,7 +1839,6 @@ namespace exprtk #undef exprtk_process_digit } - exprtk_disable_fallthrough_end } else return_result = false; @@ -2067,14 +2157,74 @@ namespace exprtk virtual void handle_runtime_violation(const violation_context&) { - throw std::runtime_error("ExprTk Loop run-time violation."); + throw std::runtime_error("ExprTk Loop runtime violation."); } - virtual ~loop_runtime_check() {} + virtual ~loop_runtime_check() + {} }; typedef loop_runtime_check* loop_runtime_check_ptr; + struct vector_access_runtime_check + { + struct violation_context + { + void* base_ptr; + void* end_ptr; + void* access_ptr; + std::size_t type_size; + }; + + virtual ~vector_access_runtime_check() + {} + + virtual bool handle_runtime_violation(violation_context& /*context*/) + { + throw std::runtime_error("ExprTk runtime vector access violation."); + #if !defined(_MSC_VER) && !defined(__NVCOMPILER) + return false; + #endif + } + }; + + typedef vector_access_runtime_check* vector_access_runtime_check_ptr; + + struct assert_check + { + struct assert_context + { + std::string condition; + std::string message; + std::string id; + std::size_t offet; + }; + + virtual ~assert_check() + {} + + virtual void handle_assert(const assert_context& /*context*/) + { + } + }; + + typedef assert_check* assert_check_ptr; + + struct compilation_check + { + struct compilation_context + { + std::string error_message; + }; + + virtual bool continue_compilation(compilation_context& /*context*/) = 0; + + virtual ~compilation_check() + {} + }; + + typedef compilation_check* compilation_check_ptr; + namespace lexer { struct token @@ -2233,6 +2383,21 @@ namespace exprtk } } + static inline std::string seperator_to_str(const token_type t) + { + switch (t) + { + case e_comma : return ","; + case e_colon : return ":"; + case e_eof : return ";"; + default : return "UNKNOWN"; + } + + #if !defined(_MSC_VER) && !defined(__NVCOMPILER) + return "UNKNOWN"; + #endif + } + inline bool is_error() const { return ( @@ -2282,7 +2447,7 @@ namespace exprtk s_itr_ = str.data(); s_end_ = str.data() + str.size(); - eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_); + eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_); token_list_.clear(); while (!is_end(s_itr_)) @@ -2345,7 +2510,9 @@ namespace exprtk inline token_t& operator[](const std::size_t& index) { if (index < token_list_.size()) + { return token_list_[index]; + } else return eof_token_; } @@ -2353,7 +2520,9 @@ namespace exprtk inline token_t operator[](const std::size_t& index) const { if (index < token_list_.size()) + { return token_list_[index]; + } else return eof_token_; } @@ -2497,7 +2666,7 @@ namespace exprtk } } - ++s_itr_; + ++s_itr_; } if (2 == mode) @@ -2509,9 +2678,17 @@ namespace exprtk #endif } + inline bool next_is_digit(const details::char_cptr itr) const + { + return ((itr + 1) != s_end_) && + details::is_digit(*(itr + 1)); + } + inline void scan_token() { - if (details::is_whitespace(*s_itr_)) + const char_t c = *s_itr_; + + if (details::is_whitespace(c)) { skip_whitespace(); return; @@ -2521,34 +2698,39 @@ namespace exprtk skip_comments(); return; } - else if (details::is_operator_char(*s_itr_)) + else if (details::is_operator_char(c)) { scan_operator(); return; } - else if (details::is_letter(*s_itr_)) + else if (details::is_letter(c)) { scan_symbol(); return; } - else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_))) + else if (('.' == c) && !next_is_digit(s_itr_)) + { + scan_operator(); + return; + } + else if (details::is_digit(c) || ('.' == c)) { scan_number(); return; } - else if ('$' == (*s_itr_)) + else if ('$' == c) { scan_special_function(); return; } #ifndef exprtk_disable_string_capabilities - else if ('\'' == (*s_itr_)) + else if ('\'' == c) { scan_string(); return; } #endif - else if ('~' == (*s_itr_)) + else if ('~' == c) { token_t t; t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); @@ -2658,7 +2840,7 @@ namespace exprtk } token_t t; - t.set_symbol(initial_itr,s_itr_,base_itr_); + t.set_symbol(initial_itr, s_itr_, base_itr_); token_list_.push_back(t); } @@ -2858,12 +3040,12 @@ namespace exprtk ((s_itr_ + 4) <= s_end_) ) { - const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1))); + const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1))); const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && details::is_hex_digit(*(s_itr_ + 3)) ; - if (!(x_seperator && both_digits)) + if (!(x_separator && both_digits)) { t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); @@ -2903,8 +3085,8 @@ namespace exprtk } t.set_string( - parsed_string, - static_cast(std::distance(base_itr_,initial_itr))); + parsed_string, + static_cast(std::distance(base_itr_,initial_itr))); } token_list_.push_back(t); @@ -2945,7 +3127,8 @@ namespace exprtk { public: - virtual ~token_scanner() {} + virtual ~token_scanner() + {} explicit token_scanner(const std::size_t& stride) : stride_(stride) @@ -2972,7 +3155,7 @@ namespace exprtk if (!operator()(t0)) { - return i; + return 0; } } break; @@ -2984,7 +3167,7 @@ namespace exprtk if (!operator()(t0, t1)) { - return i; + return 0; } } break; @@ -2997,7 +3180,7 @@ namespace exprtk if (!operator()(t0, t1, t2)) { - return i; + return 0; } } break; @@ -3011,7 +3194,7 @@ namespace exprtk if (!operator()(t0, t1, t2, t3)) { - return i; + return 0; } } break; @@ -3019,7 +3202,7 @@ namespace exprtk } } - return (g.token_list_.size() - stride_ + 1); + return 0; } virtual bool operator() (const token&) @@ -3211,7 +3394,7 @@ namespace exprtk generator::token_list_t token_list; token_list.reserve(10000); - for (int i = 0; i < static_cast(g.token_list_.size() - 1); ++i) + for (int i = 0; i < static_cast(g.token_list_.size() - 1); ++i) { token t; @@ -3227,7 +3410,7 @@ namespace exprtk ++changes; - i+=2; + i += 2; if (static_cast(i) >= (g.token_list_.size() - 1)) break; @@ -3253,7 +3436,7 @@ namespace exprtk generator::token_list_t token_list; token_list.reserve(10000); - for (int i = 0; i < static_cast(g.token_list_.size() - 2); ++i) + for (int i = 0; i < static_cast(g.token_list_.size() - 2); ++i) { token t; @@ -3269,7 +3452,7 @@ namespace exprtk ++changes; - i+=3; + i += 3; if (static_cast(i) >= (g.token_list_.size() - 2)) break; @@ -3367,7 +3550,7 @@ namespace exprtk std::set ignore_set_; }; - class operator_joiner : public token_joiner + class operator_joiner exprtk_final : public token_joiner { public: @@ -3543,7 +3726,7 @@ namespace exprtk } }; - class bracket_checker : public lexer::token_scanner + class bracket_checker exprtk_final : public lexer::token_scanner { public: @@ -3554,7 +3737,7 @@ namespace exprtk , state_(true) {} - bool result() + bool result() exprtk_override { if (!stack_.empty()) { @@ -3575,7 +3758,7 @@ namespace exprtk return error_token_; } - void reset() + void reset() exprtk_override { // Why? because msvc doesn't support swap properly. stack_ = std::stack >(); @@ -3583,7 +3766,7 @@ namespace exprtk error_token_.clear(); } - bool operator() (const lexer::token& t) + bool operator() (const lexer::token& t) exprtk_override { if ( !t.value.empty() && @@ -3640,18 +3823,18 @@ namespace exprtk , current_index_(0) {} - bool result() + bool result() exprtk_override { return error_list_.empty(); } - void reset() + void reset() exprtk_override { error_list_.clear(); current_index_ = 0; } - bool operator() (const lexer::token& t) + bool operator() (const lexer::token& t) exprtk_override { if (token::e_number == t.type) { @@ -3692,7 +3875,7 @@ namespace exprtk std::vector error_list_; }; - class symbol_replacer : public lexer::token_modifier + class symbol_replacer exprtk_final : public lexer::token_modifier { private: @@ -3735,7 +3918,7 @@ namespace exprtk private: - bool modify(lexer::token& t) + bool modify(lexer::token& t) exprtk_override { if (lexer::token::e_symbol == t.type) { @@ -3798,12 +3981,12 @@ namespace exprtk add_invalid_set1(lexer::token::e_ternary); } - bool result() + bool result() exprtk_override { return error_list_.empty(); } - bool operator() (const lexer::token& t0, const lexer::token& t1) + bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override { const set_t::value_type p = std::make_pair(t0.type,t1.type); @@ -3965,12 +4148,12 @@ namespace exprtk add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); } - bool result() + bool result() exprtk_override { return error_list_.empty(); } - bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) + bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override { const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); @@ -4227,6 +4410,11 @@ namespace exprtk return current_token_; } + inline const token_t& peek_next_token() + { + return lexer_.peek_next_token(); + } + enum token_advance_mode { e_hold = 0, @@ -4270,6 +4458,110 @@ namespace exprtk return true; } + inline bool token_is(const std::string& value, + const token_advance_mode mode = e_advance) + { + if (!exprtk::details::imatch(value,current_token().value)) + { + return false; + } + + advance_token(mode); + + return true; + } + + inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance) + { + switch (current_token().type) + { + case token_t::e_add : + case token_t::e_sub : + case token_t::e_div : + case token_t::e_mul : + case token_t::e_mod : + case token_t::e_pow : break; + default : return false; + } + + advance_token(mode); + + return true; + } + + inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance) + { + switch (current_token().type) + { + case token_t::e_eq : + case token_t::e_lte : + case token_t::e_ne : + case token_t::e_gte : + case token_t::e_lt : + case token_t::e_gt : break; + default : return false; + } + + advance_token(mode); + + return true; + } + + inline bool token_is_left_bracket(const token_advance_mode mode = e_advance) + { + switch (current_token().type) + { + case token_t::e_lbracket : + case token_t::e_lcrlbracket : + case token_t::e_lsqrbracket : break; + default : return false; + } + + advance_token(mode); + + return true; + } + + inline bool token_is_right_bracket(const token_advance_mode mode = e_advance) + { + switch (current_token().type) + { + case token_t::e_rbracket : + case token_t::e_rcrlbracket : + case token_t::e_rsqrbracket : break; + default : return false; + } + + advance_token(mode); + + return true; + } + + inline bool token_is_bracket(const token_advance_mode mode = e_advance) + { + switch (current_token().type) + { + case token_t::e_rbracket : + case token_t::e_rcrlbracket : + case token_t::e_rsqrbracket : + case token_t::e_lbracket : + case token_t::e_lcrlbracket : + case token_t::e_lsqrbracket : break; + default : return false; + } + + advance_token(mode); + + return true; + } + + inline bool token_is_loop(const token_advance_mode mode = e_advance) + { + return token_is("for" , mode) || + token_is("while" , mode) || + token_is("repeat", mode) ; + } + inline bool peek_token_is(const token_t::token_type& ttype) { return (lexer_.peek_next_token().type == ttype); @@ -4296,16 +4588,22 @@ namespace exprtk typedef T* data_ptr_t; vector_view(data_ptr_t data, const std::size_t& size) - : size_(size) + : base_size_(size) + , size_(size) , data_(data) , data_ref_(0) - {} + { + assert(size_ > 0); + } vector_view(const vector_view& vv) - : size_(vv.size_) + : base_size_(vv.base_size_) + , size_(vv.size_) , data_(vv.data_) , data_ref_(0) - {} + { + assert(size_ > 0); + } inline void rebase(data_ptr_t data) { @@ -4325,6 +4623,11 @@ namespace exprtk return data_; } + inline std::size_t base_size() const + { + return base_size_; + } + inline std::size_t size() const { return size_; @@ -4332,22 +4635,55 @@ namespace exprtk inline const T& operator[](const std::size_t index) const { + assert(index < size_); return data_[index]; } inline T& operator[](const std::size_t index) { + assert(index < size_); return data_[index]; } void set_ref(data_ptr_t* data_ref) { data_ref_.push_back(data_ref); + exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", + reinterpret_cast(data_ref), + static_cast(data_ref_.size()))); + } + + void remove_ref(data_ptr_t* data_ref) + { + data_ref_.erase( + std::remove(data_ref_.begin(), data_ref_.end(), data_ref), + data_ref_.end()); + exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", + reinterpret_cast(data_ref), + static_cast(data_ref_.size()))); + } + + bool set_size(const std::size_t new_size) + { + if ((new_size > 0) && (new_size <= base_size_)) + { + size_ = new_size; + exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", + reinterpret_cast(data_), + size_)); + return true; + } + + exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", + new_size, + base_size_)); + return false; } private: - const std::size_t size_; + const std::size_t base_size_; + std::size_t size_; data_ptr_t data_; std::vector data_ref_; }; @@ -4523,6 +4859,16 @@ namespace exprtk return v_; } + inline operator value_t() const + { + return v_; + } + + inline operator value_t() + { + return v_; + } + template inline bool to_int(IntType& i) const { @@ -4571,6 +4917,9 @@ namespace exprtk public: typedef type_store type_store_t; + typedef typename type_store_t::scalar_view scalar_t; + typedef typename type_store_t::vector_view vector_t; + typedef typename type_store_t::string_view string_t; results_context() : results_available_(false) @@ -4594,6 +4943,61 @@ namespace exprtk return parameter_list_[index]; } + inline bool get_scalar(const std::size_t& index, T& out) const + { + if ( + (index < parameter_list_.size()) && + (parameter_list_[index].type == type_store_t::e_scalar) + ) + { + const scalar_t scalar(parameter_list_[index]); + out = scalar(); + return true; + } + + return false; + } + + template + inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const + { + if ( + (index < parameter_list_.size()) && + (parameter_list_[index].type == type_store_t::e_vector) + ) + { + const vector_t vector(parameter_list_[index]); + for (std::size_t i = 0; i < vector.size(); ++i) + { + *(out_itr++) = vector[i]; + } + + return true; + } + + return false; + } + + inline bool get_vector(const std::size_t& index, std::vector& out) const + { + return get_vector(index,std::back_inserter(out)); + } + + inline bool get_string(const std::size_t& index, std::string& out) const + { + if ( + (index < parameter_list_.size()) && + (parameter_list_[index].type == type_store_t::e_string) + ) + { + const string_t str(parameter_list_[index]); + out.assign(str.begin(),str.size()); + return true; + } + + return false; + } + private: inline void clear() @@ -4740,10 +5144,11 @@ namespace exprtk namespace loop_unroll { + const unsigned int global_loop_batch_size = #ifndef exprtk_disable_superscalar_unroll - const unsigned int global_loop_batch_size = 16; + 16; #else - const unsigned int global_loop_batch_size = 4; + 4; #endif struct details @@ -4770,11 +5175,28 @@ namespace exprtk ptr, static_cast(size))); else - exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr)); + exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); + } + + template + inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) + { + printf("----- %s (%p) -----\n", + vec_name.c_str(), + static_cast(data)); + printf("[ "); + for (std::size_t i = 0; i < size; ++i) + { + printf("%8.3f\t", data[i]); + } + printf(" ]\n"); + printf("---------------------\n"); } #else inline void dump_ptr(const std::string&, const void*) {} inline void dump_ptr(const std::string&, const void*, const std::size_t) {} + template + inline void dump_vector(const std::string&, const T*, const std::size_t) {} #endif template @@ -4897,7 +5319,7 @@ namespace exprtk { if (this != &vds) { - std::size_t final_size = min_size(control_block_, vds.control_block_); + const std::size_t final_size = min_size(control_block_, vds.control_block_); vds.control_block_->size = final_size; control_block_->size = final_size; @@ -4947,7 +5369,7 @@ namespace exprtk if (5 == i) exprtk_debug(("\n")); - exprtk_debug(("%15.10f ",data()[i])); + exprtk_debug(("%15.10f ", data()[i])); } exprtk_debug(("\n")); #endif @@ -5060,8 +5482,8 @@ namespace exprtk case e_xnor : return xnor_opr(arg0,arg1); case e_root : return root (arg0,arg1); case e_roundn : return roundn (arg0,arg1); - case e_equal : return equal (arg0,arg1); - case e_nequal : return nequal (arg0,arg1); + case e_equal : return equal (arg0,arg1); + case e_nequal : return nequal (arg0,arg1); case e_hypot : return hypot (arg0,arg1); case e_shr : return shr (arg0,arg1); case e_shl : return shl (arg0,arg1); @@ -5130,17 +5552,19 @@ namespace exprtk typedef Node** node_pp_t; typedef std::vector noderef_list_t; - virtual ~node_collector_interface() {} + virtual ~node_collector_interface() + {} - virtual void collect_nodes(noderef_list_t&) {} + virtual void collect_nodes(noderef_list_t&) + {} }; template struct node_depth_base; template - class expression_node : public node_collector_interface >, - public node_depth_base > + class expression_node : public node_collector_interface > + , public node_depth_base > { public: @@ -5177,12 +5601,14 @@ namespace exprtk e_vovovoc , e_vovocov , e_vocovov , e_covovov , e_covocov , e_vocovoc , e_covovoc , e_vococov , e_sf3ext , e_sf4ext , e_nulleq , e_strass , - e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , - e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , - e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , - e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , - e_valvecarith , e_vecunaryop , e_vecondition , e_break , - e_continue , e_swap + e_vector , e_vecsize , e_vecelem , e_veccelem , + e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , + e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , + e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , + e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , + e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , + e_vecondition , e_break , e_continue , e_swap , + e_assert }; typedef T value_type; @@ -5191,7 +5617,8 @@ namespace exprtk typedef typename nci_t::noderef_list_t noderef_list_t; typedef node_depth_base > ndb_t; - virtual ~expression_node() {} + virtual ~expression_node() + {} inline virtual T value() const { @@ -5207,6 +5634,11 @@ namespace exprtk { return e_none; } + + inline virtual bool valid() const + { + return true; + } }; // class expression_node template @@ -5251,6 +5683,12 @@ namespace exprtk return std::equal_to()(T(0),node.first->value()); } + template + inline bool is_literal_node(const expression_node* node) + { + return node && (details::expression_node::e_constant == node->type()); + } + template inline bool is_unary_node(const expression_node* node) { @@ -5280,10 +5718,15 @@ namespace exprtk { return node && ( - details::expression_node::e_variable == node->type() || - details::expression_node::e_vecelem == node->type() || - details::expression_node::e_rbvecelem == node->type() || - details::expression_node::e_rbveccelem == node->type() + details::expression_node::e_variable == node->type() || + details::expression_node::e_vecelem == node->type() || + details::expression_node::e_veccelem == node->type() || + details::expression_node::e_vecelemrtc == node->type() || + details::expression_node::e_veccelemrtc == node->type() || + details::expression_node::e_rbvecelem == node->type() || + details::expression_node::e_rbveccelem == node->type() || + details::expression_node::e_rbvecelemrtc == node->type() || + details::expression_node::e_rbveccelemrtc == node->type() ); } @@ -5293,12 +5736,42 @@ namespace exprtk return node && (details::expression_node::e_vecelem == node->type()); } + template + inline bool is_vector_celem_node(const expression_node* node) + { + return node && (details::expression_node::e_veccelem == node->type()); + } + + template + inline bool is_vector_elem_rtc_node(const expression_node* node) + { + return node && (details::expression_node::e_vecelemrtc == node->type()); + } + + template + inline bool is_vector_celem_rtc_node(const expression_node* node) + { + return node && (details::expression_node::e_veccelemrtc == node->type()); + } + template inline bool is_rebasevector_elem_node(const expression_node* node) { return node && (details::expression_node::e_rbvecelem == node->type()); } + template + inline bool is_rebasevector_elem_rtc_node(const expression_node* node) + { + return node && (details::expression_node::e_rbvecelemrtc == node->type()); + } + + template + inline bool is_rebasevector_celem_rtc_node(const expression_node* node) + { + return node && (details::expression_node::e_rbveccelemrtc == node->type()); + } + template inline bool is_rebasevector_celem_node(const expression_node* node) { @@ -5376,6 +5849,12 @@ namespace exprtk return node && (details::expression_node::e_function == node->type()); } + template + inline bool is_vararg_node(const expression_node* node) + { + return node && (details::expression_node::e_vararg == node->type()); + } + template inline bool is_return_node(const expression_node* node) { @@ -5396,7 +5875,13 @@ namespace exprtk } template - inline bool branch_deletable(expression_node* node) + inline bool is_assert_node(const expression_node* node) + { + return node && (details::expression_node::e_assert == node->type()); + } + + template + inline bool branch_deletable(const expression_node* node) { return (0 != node) && !is_variable_node(node) && @@ -5404,7 +5889,7 @@ namespace exprtk } template - inline bool all_nodes_valid(expression_node* (&b)[N]) + inline bool all_nodes_valid(expression_node* const (&b)[N]) { for (std::size_t i = 0; i < N; ++i) { @@ -5428,7 +5913,7 @@ namespace exprtk } template - inline bool all_nodes_variables(expression_node* (&b)[N]) + inline bool all_nodes_variables(expression_node* const (&b)[N]) { for (std::size_t i = 0; i < N; ++i) { @@ -5444,7 +5929,7 @@ namespace exprtk template class Sequence> - inline bool all_nodes_variables(Sequence*,Allocator>& b) + inline bool all_nodes_variables(const Sequence*,Allocator>& b) { for (std::size_t i = 0; i < b.size(); ++i) { @@ -5478,7 +5963,7 @@ namespace exprtk for (std::size_t i = 0; i < node_delete_list.size(); ++i) { node_ptr_t& node = *node_delete_list[i]; - exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast(node))); + exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast(node))); delete node; node = reinterpret_cast(0); } @@ -5583,7 +6068,8 @@ namespace exprtk , depth(0) {} - virtual ~node_depth_base() {} + virtual ~node_depth_base() + {} virtual std::size_t node_depth() const { return 1; } @@ -5615,6 +6101,7 @@ namespace exprtk if (!depth_set) { depth = 0; + for (std::size_t i = 0; i < N; ++i) { if (branch[i].first) @@ -5622,6 +6109,7 @@ namespace exprtk depth = std::max(depth,branch[i].first->node_depth()); } } + depth += 1; depth_set = true; } @@ -5629,12 +6117,34 @@ namespace exprtk return depth; } + template + std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const + { + return std::max(compute_node_depth(n0), compute_node_depth(n1)); + } + + template + std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const + { + return std::max(compute_node_depth(n0), + std::max(compute_node_depth(n1), compute_node_depth(n2))); + } + + template + std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, + const BranchType& n2, const BranchType& n3) const + { + return std::max( + std::max(compute_node_depth(n0), compute_node_depth(n1)), + std::max(compute_node_depth(n2), compute_node_depth(n3))); + } + template std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const { if (!depth_set) { - depth = 1 + std::max(compute_node_depth(n0), compute_node_depth(n1)); + depth = 1 + max_node_depth(n0, n1); depth_set = true; } @@ -5647,9 +6157,7 @@ namespace exprtk { if (!depth_set) { - depth = 1 + std::max( - std::max(compute_node_depth(n0), compute_node_depth(n1)), - compute_node_depth(n2)); + depth = 1 + max_node_depth(n0, n1, n2); depth_set = true; } @@ -5662,9 +6170,7 @@ namespace exprtk { if (!depth_set) { - depth = 1 + std::max( - std::max(compute_node_depth(n0), compute_node_depth(n1)), - std::max(compute_node_depth(n2), compute_node_depth(n3))); + depth = 1 + max_node_depth(n0, n1, n2, n3); depth_set = true; } @@ -5684,6 +6190,7 @@ namespace exprtk depth = std::max(depth, compute_node_depth(branch_list[i])); } } + depth_set = true; } @@ -5703,6 +6210,7 @@ namespace exprtk depth = std::max(depth, compute_node_depth(branch_list[i].first)); } } + depth_set = true; } @@ -5795,12 +6303,14 @@ namespace exprtk typedef Type value_type; typedef value_type* value_ptr; typedef const value_ptr const_value_ptr; + typedef vector_holder vector_holder_t; class vector_holder_base { public: - virtual ~vector_holder_base() {} + virtual ~vector_holder_base() + {} inline value_ptr operator[](const std::size_t& index) const { @@ -5812,6 +6322,11 @@ namespace exprtk return vector_size(); } + inline std::size_t base_size() const + { + return vector_base_size(); + } + inline value_ptr data() const { return value_at(0); @@ -5822,15 +6337,25 @@ namespace exprtk return false; } - virtual void set_ref(value_ptr*) {} + virtual void set_ref(value_ptr*) + {} + + virtual void remove_ref(value_ptr*) + {} + + virtual vector_view* rebaseable_instance() + { + return reinterpret_cast*>(0); + } protected: virtual value_ptr value_at(const std::size_t&) const = 0; virtual std::size_t vector_size() const = 0; + virtual std::size_t vector_base_size() const = 0; }; - class array_vector_impl : public vector_holder_base + class array_vector_impl exprtk_final : public vector_holder_base { public: @@ -5841,19 +6366,22 @@ namespace exprtk protected: - value_ptr value_at(const std::size_t& index) const + value_ptr value_at(const std::size_t& index) const exprtk_override { - if (index < size_) - return const_cast(vec_ + index); - else - return const_value_ptr(0); + assert(index < size_); + return const_cast(vec_ + index); } - std::size_t vector_size() const + std::size_t vector_size() const exprtk_override { return size_; } + std::size_t vector_base_size() const exprtk_override + { + return vector_size(); + } + private: array_vector_impl(const array_vector_impl&) exprtk_delete; @@ -5865,28 +6393,34 @@ namespace exprtk template class Sequence> - class sequence_vector_impl : public vector_holder_base + class sequence_vector_impl exprtk_final : public vector_holder_base { public: typedef Sequence sequence_t; - sequence_vector_impl(sequence_t& seq) + explicit sequence_vector_impl(sequence_t& seq) : sequence_(seq) {} protected: - value_ptr value_at(const std::size_t& index) const + value_ptr value_at(const std::size_t& index) const exprtk_override { - return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0); + assert(index < sequence_.size()); + return (&sequence_[index]); } - std::size_t vector_size() const + std::size_t vector_size() const exprtk_override { return sequence_.size(); } + std::size_t vector_base_size() const exprtk_override + { + return vector_size(); + } + private: sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; @@ -5895,7 +6429,7 @@ namespace exprtk sequence_t& sequence_; }; - class vector_view_impl : public vector_holder_base + class vector_view_impl exprtk_final : public vector_holder_base { public: @@ -5903,30 +6437,48 @@ namespace exprtk vector_view_impl(vector_view_t& vec_view) : vec_view_(vec_view) - {} + { + assert(vec_view_.size() > 0); + } - void set_ref(value_ptr* ref) + void set_ref(value_ptr* ref) exprtk_override { vec_view_.set_ref(ref); } - virtual inline bool rebaseable() const + void remove_ref(value_ptr* ref) exprtk_override + { + vec_view_.remove_ref(ref); + } + + bool rebaseable() const exprtk_override { return true; } + vector_view* rebaseable_instance() exprtk_override + { + return &vec_view_; + } + protected: - value_ptr value_at(const std::size_t& index) const + value_ptr value_at(const std::size_t& index) const exprtk_override { - return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0); + assert(index < vec_view_.size()); + return (&vec_view_[index]); } - std::size_t vector_size() const + std::size_t vector_size() const exprtk_override { return vec_view_.size(); } + std::size_t vector_base_size() const exprtk_override + { + return vec_view_.base_size(); + } + private: vector_view_impl(const vector_view_impl&) exprtk_delete; @@ -5935,6 +6487,62 @@ namespace exprtk vector_view_t& vec_view_; }; + class resizable_vector_impl exprtk_final : public vector_holder_base + { + public: + + resizable_vector_impl(vector_holder& vec_view_holder, + const Type* vec, + const std::size_t& vec_size) + : vec_(vec) + , size_(vec_size) + , vec_view_holder_(*vec_view_holder.rebaseable_instance()) + { + assert(vec_view_holder.rebaseable_instance()); + assert(size_ <= vector_base_size()); + } + + virtual ~resizable_vector_impl() + {} + + protected: + + value_ptr value_at(const std::size_t& index) const exprtk_override + { + assert(index < vector_size()); + return const_cast(vec_ + index); + } + + std::size_t vector_size() const exprtk_override + { + return vec_view_holder_.size(); + } + + std::size_t vector_base_size() const exprtk_override + { + return vec_view_holder_.base_size(); + } + + bool rebaseable() const exprtk_override + { + return true; + } + + virtual vector_view* rebaseable_instance() exprtk_override + { + return &vec_view_holder_; + } + + private: + + resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; + resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; + + const Type* vec_; + const std::size_t size_; + vector_view& vec_view_holder_; + }; + public: typedef typename details::vec_data_store vds_t; @@ -5956,6 +6564,10 @@ namespace exprtk : vector_holder_base_(new(buffer)vector_view_impl(vec)) {} + explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) + : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) + {} + inline value_ptr operator[](const std::size_t& index) const { return (*vector_holder_base_)[index]; @@ -5966,6 +6578,11 @@ namespace exprtk return vector_holder_base_->size(); } + inline std::size_t base_size() const + { + return vector_holder_base_->base_size(); + } + inline value_ptr data() const { return vector_holder_base_->data(); @@ -5973,7 +6590,18 @@ namespace exprtk void set_ref(value_ptr* ref) { - vector_holder_base_->set_ref(ref); + if (rebaseable()) + { + vector_holder_base_->set_ref(ref); + } + } + + void remove_ref(value_ptr* ref) + { + if (rebaseable()) + { + vector_holder_base_->remove_ref(ref); + } } bool rebaseable() const @@ -5981,8 +6609,16 @@ namespace exprtk return vector_holder_base_->rebaseable(); } + vector_view* rebaseable_instance() + { + return vector_holder_base_->rebaseable_instance(); + } + private: + vector_holder(const vector_holder&) exprtk_delete; + vector_holder& operator=(const vector_holder&) exprtk_delete; + mutable vector_holder_base* vector_holder_base_; uchar_t buffer[64]; }; @@ -6060,12 +6696,11 @@ namespace exprtk : equality_(equality) { construct_branch_pair(branch_, branch); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_.first); - const T v = branch_.first->value(); const bool result = details::numeric::is_nan(v); @@ -6085,6 +6720,11 @@ namespace exprtk return branch_.first; } + inline bool valid() const exprtk_override + { + return branch_.first; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(branch_, node_delete_list); @@ -6146,7 +6786,8 @@ namespace exprtk typedef range_pack range_t; - virtual ~range_interface() {} + virtual ~range_interface() + {} virtual range_t& range_ref() = 0; @@ -6161,7 +6802,8 @@ namespace exprtk typedef range_data_type range_data_type_t; - virtual ~string_base_node() {} + virtual ~string_base_node() + {} virtual std::string str () const = 0; @@ -6172,9 +6814,9 @@ namespace exprtk template class string_literal_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface + : public expression_node + , public string_base_node + , public range_interface { public: @@ -6183,8 +6825,8 @@ namespace exprtk explicit string_literal_node(const std::string& v) : value_(v) { - rp_.n0_c = std::make_pair(true,0); - rp_.n1_c = std::make_pair(true,v.size() - 1); + rp_.n0_c = std::make_pair(true, 0); + rp_.n1_c = std::make_pair(true, v.size()); rp_.cache.first = rp_.n0_c.second; rp_.cache.second = rp_.n1_c.second; } @@ -6251,13 +6893,13 @@ namespace exprtk : operation_(opr) { construct_branch_pair(branch_,branch); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_.first); - const T arg = branch_.first->value(); - return numeric::process(operation_,arg); + return numeric::process + (operation_,branch_.first->value()); } inline typename expression_node::node_type type() const exprtk_override @@ -6275,6 +6917,11 @@ namespace exprtk return branch_.first; } + inline bool valid() const exprtk_override + { + return branch_.first && branch_.first->valid(); + } + inline void release() { branch_.second = false; @@ -6310,17 +6957,17 @@ namespace exprtk : operation_(opr) { init_branches<2>(branch_, branch0, branch1); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_[0].first); - assert(branch_[1].first); - - const T arg0 = branch_[0].first->value(); - const T arg1 = branch_[1].first->value(); - - return numeric::process(operation_, arg0, arg1); + return numeric::process + ( + operation_, + branch_[0].first->value(), + branch_[1].first->value() + ); } inline typename expression_node::node_type type() const exprtk_override @@ -6335,17 +6982,20 @@ namespace exprtk inline expression_node* branch(const std::size_t& index = 0) const exprtk_override { - if (0 == index) - return branch_[0].first; - else if (1 == index) - return branch_[1].first; - else - return reinterpret_cast(0); + assert(index < 2); + return branch_[index].first; + } + + inline bool valid() const exprtk_override + { + return + branch_[0].first && branch_[0].first->valid() && + branch_[1].first && branch_[1].first->valid() ; } void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_final @@ -6370,16 +7020,13 @@ namespace exprtk binary_ext_node(expression_ptr branch0, expression_ptr branch1) { init_branches<2>(branch_, branch0, branch1); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_[0].first); - assert(branch_[1].first); - const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); - return Operation::process(arg0,arg1); } @@ -6395,17 +7042,20 @@ namespace exprtk inline expression_node* branch(const std::size_t& index = 0) const exprtk_override { - if (0 == index) - return branch_[0].first; - else if (1 == index) - return branch_[1].first; - else - return reinterpret_cast(0); + assert(index < 2); + return branch_[index].first; + } + + inline bool valid() const exprtk_override + { + return + branch_[0].first && branch_[0].first->valid() && + branch_[1].first && branch_[1].first->valid() ; } void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override @@ -6433,14 +7083,11 @@ namespace exprtk : operation_(opr) { init_branches<3>(branch_, branch0, branch1, branch2); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_[0].first); - assert(branch_[1].first); - assert(branch_[2].first); - const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); const T arg2 = branch_[2].first->value(); @@ -6466,9 +7113,17 @@ namespace exprtk return expression_node::e_trinary; } + inline bool valid() const exprtk_override + { + return + branch_[0].first && branch_[0].first->valid() && + branch_[1].first && branch_[1].first->valid() && + branch_[2].first && branch_[2].first->valid() ; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override exprtk_final @@ -6512,7 +7167,7 @@ namespace exprtk void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override exprtk_final @@ -6520,6 +7175,15 @@ namespace exprtk return expression_node::ndb_t::template compute_node_depth<4>(branch_); } + inline bool valid() const exprtk_override + { + return + branch_[0].first && branch_[0].first->valid() && + branch_[1].first && branch_[1].first->valid() && + branch_[2].first && branch_[2].first->valid() && + branch_[3].first && branch_[3].first->valid() ; + } + protected: operator_type operation_; @@ -6541,14 +7205,11 @@ namespace exprtk construct_branch_pair(condition_ , condition ); construct_branch_pair(consequent_ , consequent ); construct_branch_pair(alternative_, alternative); + assert(valid()); } inline T value() const exprtk_override { - assert(condition_ .first); - assert(consequent_ .first); - assert(alternative_.first); - if (is_true(condition_)) return consequent_.first->value(); else @@ -6560,6 +7221,14 @@ namespace exprtk return expression_node::e_conditional; } + inline bool valid() const exprtk_override + { + return + condition_ .first && condition_ .first->valid() && + consequent_ .first && consequent_ .first->valid() && + alternative_.first && alternative_.first->valid() ; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(condition_ , node_delete_list); @@ -6594,13 +7263,11 @@ namespace exprtk { construct_branch_pair(condition_ , condition ); construct_branch_pair(consequent_, consequent); + assert(valid()); } inline T value() const exprtk_override { - assert(condition_ .first); - assert(consequent_.first); - if (is_true(condition_)) return consequent_.first->value(); else @@ -6612,6 +7279,13 @@ namespace exprtk return expression_node::e_conditional; } + inline bool valid() const exprtk_override + { + return + condition_ .first && condition_ .first->valid() && + consequent_.first && consequent_.first->valid() ; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(condition_ , node_delete_list); @@ -6653,7 +7327,7 @@ namespace exprtk typedef expression_node* expression_ptr; typedef std::pair branch_t; - break_node(expression_ptr ret = expression_ptr(0)) + explicit break_node(expression_ptr ret = expression_ptr(0)) { construct_branch_pair(return_, ret); } @@ -6666,7 +7340,7 @@ namespace exprtk throw break_exception(result); - #ifndef _MSC_VER + #if !defined(_MSC_VER) && !defined(__NVCOMPILER) return std::numeric_limits::quiet_NaN(); #endif } @@ -6699,7 +7373,7 @@ namespace exprtk inline T value() const exprtk_override { throw continue_exception(); - #ifndef _MSC_VER + #if !defined(_MSC_VER) && !defined(__NVCOMPILER) return std::numeric_limits::quiet_NaN(); #endif } @@ -6730,9 +7404,11 @@ namespace exprtk inline bool check() const { + assert(loop_runtime_check_); + if ( - (0 == loop_runtime_check_) || - ((++iteration_count_ <= max_loop_iterations_) && loop_runtime_check_->check()) + (++iteration_count_ <= max_loop_iterations_) && + loop_runtime_check_->check() ) { return true; @@ -6747,6 +7423,11 @@ namespace exprtk return false; } + bool valid() const + { + return 0 != loop_runtime_check_; + } + mutable _uint64_t iteration_count_; mutable loop_runtime_check_ptr loop_runtime_check_; const details::_uint64_t& max_loop_iterations_; @@ -6766,13 +7447,11 @@ namespace exprtk { construct_branch_pair(condition_, condition); construct_branch_pair(loop_body_, loop_body); + assert(valid()); } inline T value() const exprtk_override { - assert(condition_.first); - assert(loop_body_.first); - T result = T(0); while (is_true(condition_)) @@ -6788,6 +7467,13 @@ namespace exprtk return expression_node::e_while; } + inline bool valid() const exprtk_override + { + return + condition_.first && condition_.first->valid() && + loop_body_.first && loop_body_.first->valid() ; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(condition_ , node_delete_list); @@ -6820,12 +7506,12 @@ namespace exprtk loop_runtime_check_ptr loop_rt_chk) : parent_t(condition, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) - {} + { + assert(valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); T result = T(0); @@ -6838,6 +7524,14 @@ namespace exprtk return result; } + + using parent_t::valid; + + bool valid() const exprtk_override exprtk_final + { + return parent_t::valid() && + loop_runtime_checker::valid(); + } }; template @@ -6853,13 +7547,11 @@ namespace exprtk { construct_branch_pair(condition_, condition); construct_branch_pair(loop_body_, loop_body); + assert(valid()); } inline T value() const exprtk_override { - assert(condition_.first); - assert(loop_body_.first); - T result = T(0); do @@ -6876,6 +7568,13 @@ namespace exprtk return expression_node::e_repeat; } + inline bool valid() const exprtk_override + { + return + condition_.first && condition_.first->valid() && + loop_body_.first && loop_body_.first->valid() ; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(condition_ , node_delete_list); @@ -6908,13 +7607,12 @@ namespace exprtk loop_runtime_check_ptr loop_rt_chk) : parent_t(condition, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) - {} + { + assert(valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); - T result = T(0); loop_runtime_checker::reset(1); @@ -6927,6 +7625,14 @@ namespace exprtk return result; } + + using parent_t::valid; + + inline bool valid() const exprtk_override exprtk_final + { + return parent_t::valid() && + loop_runtime_checker::valid(); + } }; template @@ -6946,13 +7652,11 @@ namespace exprtk construct_branch_pair(condition_ , condition ); construct_branch_pair(incrementor_, incrementor); construct_branch_pair(loop_body_ , loop_body ); + assert(valid()); } inline T value() const exprtk_override { - assert(condition_.first); - assert(loop_body_.first); - T result = T(0); if (initialiser_.first) @@ -6982,6 +7686,11 @@ namespace exprtk return expression_node::e_for; } + inline bool valid() const exprtk_override + { + return condition_.first && loop_body_.first; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(initialiser_ , node_delete_list); @@ -7021,13 +7730,12 @@ namespace exprtk loop_runtime_check_ptr loop_rt_chk) : parent_t(initialiser, condition, incrementor, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) - {} + { + assert(valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); - T result = T(0); loop_runtime_checker::reset(); @@ -7053,6 +7761,14 @@ namespace exprtk return result; } + + using parent_t::valid; + + inline bool valid() const exprtk_override exprtk_final + { + return parent_t::valid() && + loop_runtime_checker::valid(); + } }; #ifndef exprtk_disable_break_continue @@ -7067,13 +7783,12 @@ namespace exprtk while_loop_bc_node(expression_ptr condition, expression_ptr loop_body) : parent_t(condition, loop_body) - {} + { + assert(parent_t::valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); - T result = T(0); while (is_true(parent_t::condition_)) @@ -7109,13 +7824,12 @@ namespace exprtk loop_runtime_check_ptr loop_rt_chk) : parent_t(condition, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) - {} + { + assert(valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); - T result = T(0); loop_runtime_checker::reset(); @@ -7136,6 +7850,14 @@ namespace exprtk return result; } + + using parent_t::valid; + + inline bool valid() const exprtk_override exprtk_final + { + return parent_t::valid() && + loop_runtime_checker::valid(); + } }; template @@ -7149,13 +7871,12 @@ namespace exprtk repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body) : parent_t(condition, loop_body) - {} + { + assert(parent_t::valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); - T result = T(0); do @@ -7179,8 +7900,8 @@ namespace exprtk template class repeat_until_loop_bc_rtc_node exprtk_final - : public repeat_until_loop_bc_node, - public loop_runtime_checker + : public repeat_until_loop_bc_node + , public loop_runtime_checker { public: @@ -7192,13 +7913,12 @@ namespace exprtk loop_runtime_check_ptr loop_rt_chk) : parent_t(condition, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) - {} + { + assert(valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); - T result = T(0); loop_runtime_checker::reset(); @@ -7220,6 +7940,14 @@ namespace exprtk return result; } + + using parent_t::valid; + + inline bool valid() const exprtk_override exprtk_final + { + return parent_t::valid() && + loop_runtime_checker::valid(); + } }; template @@ -7235,13 +7963,12 @@ namespace exprtk expression_ptr incrementor, expression_ptr loop_body) : parent_t(initialiser, condition, incrementor, loop_body) - {} + { + assert(parent_t::valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); - T result = T(0); if (parent_t::initialiser_.first) @@ -7303,13 +8030,12 @@ namespace exprtk loop_runtime_check_ptr loop_rt_chk) : parent_t(initialiser, condition, incrementor, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) - {} + { + assert(valid()); + } inline T value() const exprtk_override { - assert(parent_t::condition_.first); - assert(parent_t::loop_body_.first); - T result = T(0); loop_runtime_checker::reset(); @@ -7354,6 +8080,14 @@ namespace exprtk return result; } + + using parent_t::valid; + + inline bool valid() const exprtk_override exprtk_final + { + return parent_t::valid() && + loop_runtime_checker::valid(); + } }; #endif @@ -7376,7 +8110,7 @@ namespace exprtk for (std::size_t i = 0; i < arg_list.size(); ++i) { - if (arg_list[i]) + if (arg_list[i] && arg_list[i]->valid()) { construct_branch_pair(arg_list_[i], arg_list[i]); } @@ -7386,29 +8120,26 @@ namespace exprtk return; } } + + assert(valid()); } inline T value() const exprtk_override { - if (!arg_list_.empty()) + const std::size_t upper_bound = (arg_list_.size() - 1); + + for (std::size_t i = 0; i < upper_bound; i += 2) { - const std::size_t upper_bound = (arg_list_.size() - 1); + expression_ptr condition = arg_list_[i ].first; + expression_ptr consequent = arg_list_[i + 1].first; - for (std::size_t i = 0; i < upper_bound; i += 2) + if (is_true(condition)) { - expression_ptr condition = arg_list_[i ].first; - expression_ptr consequent = arg_list_[i + 1].first; - - if (is_true(condition)) - { - return consequent->value(); - } + return consequent->value(); } - - return arg_list_[upper_bound].first->value(); } - else - return std::numeric_limits::quiet_NaN(); + + return arg_list_[upper_bound].first->value(); } inline typename expression_node::node_type type() const exprtk_override exprtk_final @@ -7416,6 +8147,11 @@ namespace exprtk return expression_node::e_switch; } + inline bool valid() const exprtk_override + { + return !arg_list_.empty(); + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(arg_list_, node_delete_list); @@ -7469,7 +8205,7 @@ namespace exprtk for (std::size_t i = 0; i < arg_list.size(); ++i) { - if (arg_list[i]) + if (arg_list[i] && arg_list[i]->valid()) { construct_branch_pair(arg_list_[i], arg_list[i]); } @@ -7479,19 +8215,16 @@ namespace exprtk return; } } + + assert(valid()); } inline T value() const exprtk_override { - T result = T(0); - - if (arg_list_.empty()) - { - return std::numeric_limits::quiet_NaN(); - } - const std::size_t upper_bound = (arg_list_.size() - 1); + T result = T(0); + for (std::size_t i = 0; i < upper_bound; i += 2) { expression_ptr condition = arg_list_[i ].first; @@ -7511,6 +8244,11 @@ namespace exprtk return expression_node::e_mswitch; } + inline bool valid() const exprtk_override + { + return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(arg_list_, node_delete_list); @@ -7531,7 +8269,8 @@ namespace exprtk { public: - virtual ~ivariable() {} + virtual ~ivariable() + {} virtual T& ref() = 0; virtual const T& ref() const = 0; @@ -7539,8 +8278,8 @@ namespace exprtk template class variable_node exprtk_final - : public expression_node, - public ivariable + : public expression_node + , public ivariable { public: @@ -7677,7 +8416,7 @@ namespace exprtk (std::numeric_limits::max() == r1 ) ) { - r1 = size - 1; + r1 = size; } cache.first = r0; @@ -7692,12 +8431,12 @@ namespace exprtk inline std::size_t const_size() const { - return (n1_c.second - n0_c.second + 1); + return (n1_c.second - n0_c.second); } inline std::size_t cache_size() const { - return (cache.second - cache.first + 1); + return (cache.second - cache.first); } std::pair n0_e; @@ -7711,16 +8450,20 @@ namespace exprtk const std::size_t r1, const std::size_t size) const { - if (r0 >= size) + if (r0 > size) { - throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)"); + throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); + #if !defined(_MSC_VER) && !defined(__NVCOMPILER) return false; + #endif } - if (r1 >= size) + if (r1 > size) { - throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)"); + throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); + #if !defined(_MSC_VER) && !defined(__NVCOMPILER) return false; + #endif } return (r0 <= r1); @@ -7762,19 +8505,22 @@ namespace exprtk typedef vector_node* vector_node_ptr; typedef vec_data_store vds_t; - virtual ~vector_interface() {} + virtual ~vector_interface() + {} + + virtual std::size_t size () const = 0; - virtual std::size_t size () const = 0; + virtual std::size_t base_size() const = 0; - virtual vector_node_ptr vec() const = 0; + virtual vector_node_ptr vec () const = 0; - virtual vector_node_ptr vec() = 0; + virtual vector_node_ptr vec () = 0; - virtual vds_t& vds () = 0; + virtual vds_t& vds () = 0; - virtual const vds_t& vds () const = 0; + virtual const vds_t& vds () const = 0; - virtual bool side_effect () const { return false; } + virtual bool side_effect () const { return false; } }; template @@ -7801,6 +8547,12 @@ namespace exprtk , vds_(vds) {} + ~vector_node() + { + assert(valid()); + vector_holder_->remove_ref(&vds_.ref()); + } + inline T value() const exprtk_override { return vds().data()[0]; @@ -7821,9 +8573,19 @@ namespace exprtk return expression_node::e_vector; } + inline bool valid() const exprtk_override + { + return vector_holder_; + } + std::size_t size() const exprtk_override { - return vds().size(); + return vec_holder().size(); + } + + std::size_t base_size() const exprtk_override + { + return vec_holder().base_size(); } vds_t& vds() exprtk_override @@ -7841,16 +8603,65 @@ namespace exprtk return (*vector_holder_); } + inline vector_holder_t& vec_holder() const + { + return (*vector_holder_); + } + private: vector_holder_t* vector_holder_; vds_t vds_; }; + template + class vector_size_node exprtk_final + : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + + explicit vector_size_node(vector_holder_t* vh) + : vector_holder_(vh) + {} + + ~vector_size_node() + { + assert(valid()); + } + + inline T value() const exprtk_override + { + assert(vector_holder_); + return static_cast(vector_holder_->size()); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecsize; + } + + inline bool valid() const exprtk_override + { + return vector_holder_ && vector_holder_->size(); + } + + inline vector_holder_t* vec_holder() + { + return vector_holder_; + } + + private: + + vector_holder_t* vector_holder_; + }; + template class vector_elem_node exprtk_final - : public expression_node, - public ivariable + : public expression_node + , public ivariable { public: @@ -7859,26 +8670,30 @@ namespace exprtk typedef vector_holder_t* vector_holder_ptr; typedef std::pair branch_t; - vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) - : vec_holder_(vec_holder) + vector_elem_node(expression_ptr vec_node, + expression_ptr index, + vector_holder_ptr vec_holder) + : vector_holder_(vec_holder) , vector_base_((*vec_holder)[0]) { - construct_branch_pair(index_, index); + construct_branch_pair(vector_node_, vec_node); + construct_branch_pair(index_ , index ); + assert(valid()); } inline T value() const exprtk_override { - return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); + return *access_vector(); } inline T& ref() exprtk_override { - return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); + return *access_vector(); } inline const T& ref() const exprtk_override { - return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); + return *access_vector(); } inline typename expression_node::node_type type() const exprtk_override @@ -7886,67 +8701,96 @@ namespace exprtk return expression_node::e_vecelem; } + inline bool valid() const exprtk_override + { + return + vector_holder_ && + index_.first && + vector_node_.first && + index_.first->valid() && + vector_node_.first->valid(); + } + inline vector_holder_t& vec_holder() { - return (*vec_holder_); + return (*vector_holder_); } void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::collect(index_, node_delete_list); + expression_node::ndb_t::collect(vector_node_, node_delete_list); + expression_node::ndb_t::collect(index_ , node_delete_list); } std::size_t node_depth() const exprtk_override { - return expression_node::ndb_t::compute_node_depth(index_); + return expression_node::ndb_t::compute_node_depth + (vector_node_, index_); } private: - vector_holder_ptr vec_holder_; + inline T* access_vector() const + { + vector_node_.first->value(); + return (vector_base_ + details::numeric::to_uint64(index_.first->value())); + } + + vector_holder_ptr vector_holder_; T* vector_base_; + branch_t vector_node_; branch_t index_; }; template - class rebasevector_elem_node exprtk_final - : public expression_node, - public ivariable + class vector_celem_node exprtk_final + : public expression_node + , public ivariable { public: typedef expression_node* expression_ptr; typedef vector_holder vector_holder_t; typedef vector_holder_t* vector_holder_ptr; - typedef vec_data_store vds_t; typedef std::pair branch_t; - rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) - : vector_holder_(vec_holder) - , vds_((*vector_holder_).size(),(*vector_holder_)[0]) + vector_celem_node(expression_ptr vec_node, + const std::size_t index, + vector_holder_ptr vec_holder) + : index_(index) + , vector_holder_(vec_holder) + , vector_base_((*vec_holder)[0]) { - vector_holder_->set_ref(&vds_.ref()); - construct_branch_pair(index_, index); + construct_branch_pair(vector_node_, vec_node); + assert(valid()); } inline T value() const exprtk_override { - return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); + return *access_vector(); } inline T& ref() exprtk_override { - return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); + return *access_vector(); } inline const T& ref() const exprtk_override { - return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); + return *access_vector(); } inline typename expression_node::node_type type() const exprtk_override { - return expression_node::e_rbvecelem; + return expression_node::e_veccelem; + } + + inline bool valid() const exprtk_override + { + return + vector_holder_ && + vector_node_.first && + vector_node_.first->valid(); } inline vector_holder_t& vec_holder() @@ -7956,59 +8800,82 @@ namespace exprtk void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(index_, node_delete_list); + expression_node::ndb_t::collect(vector_node_, node_delete_list); } std::size_t node_depth() const exprtk_override { - return expression_node::ndb_t::compute_node_depth(index_); + return expression_node::ndb_t::compute_node_depth(vector_node_); } private: + inline T* access_vector() const + { + vector_node_.first->value(); + return (vector_base_ + index_); + } + + const std::size_t index_; vector_holder_ptr vector_holder_; - vds_t vds_; - branch_t index_; + T* vector_base_; + branch_t vector_node_; }; template - class rebasevector_celem_node exprtk_final - : public expression_node, - public ivariable + class vector_elem_rtc_node exprtk_final + : public expression_node + , public ivariable { public: - typedef expression_node* expression_ptr; - typedef vector_holder vector_holder_t; - typedef vector_holder_t* vector_holder_ptr; - typedef vec_data_store vds_t; + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef std::pair branch_t; - rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder) - : index_(index) - , vector_holder_(vec_holder) - , vds_((*vector_holder_).size(),(*vector_holder_)[0]) + vector_elem_rtc_node(expression_ptr vec_node, + expression_ptr index, + vector_holder_ptr vec_holder, + vector_access_runtime_check_ptr vec_rt_chk) + : vector_holder_(vec_holder) + , vector_base_((*vec_holder)[0]) + , vec_rt_chk_(vec_rt_chk) + , max_vector_index_(vector_holder_->size() - 1) { - vector_holder_->set_ref(&vds_.ref()); + construct_branch_pair(vector_node_, vec_node); + construct_branch_pair(index_ , index ); + assert(valid()); } inline T value() const exprtk_override { - return *(vds_.data() + index_); + return *access_vector(); } inline T& ref() exprtk_override { - return *(vds_.data() + index_); + return *access_vector(); } inline const T& ref() const exprtk_override { - return *(vds_.data() + index_); + return *access_vector(); } inline typename expression_node::node_type type() const exprtk_override { - return expression_node::e_rbveccelem; + return expression_node::e_vecelemrtc; + } + + inline bool valid() const exprtk_override + { + return + vector_holder_ && + index_.first && + vector_node_.first && + index_.first->valid() && + vector_node_.first->valid(); } inline vector_holder_t& vec_holder() @@ -8016,398 +8883,1379 @@ namespace exprtk return (*vector_holder_); } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(vector_node_, node_delete_list); + expression_node::ndb_t::collect(index_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth + (vector_node_, index_); + } + private: - const std::size_t index_; + inline T* access_vector() const + { + const _uint64_t index = details::numeric::to_uint64(index_.first->value()); + vector_node_.first->value(); + + if (index <= max_vector_index_) + { + return (vector_holder_->data() + index); + } + + assert(vec_rt_chk_); + + vector_access_runtime_check::violation_context context; + context.base_ptr = reinterpret_cast(vector_base_); + context.end_ptr = reinterpret_cast(vector_base_ + vector_holder_->size()); + context.access_ptr = reinterpret_cast(vector_base_ + index); + context.type_size = sizeof(T); + + return vec_rt_chk_->handle_runtime_violation(context) ? + reinterpret_cast(context.access_ptr) : + vector_base_ ; + } + vector_holder_ptr vector_holder_; - vds_t vds_; + T* vector_base_; + branch_t vector_node_; + branch_t index_; + vector_access_runtime_check_ptr vec_rt_chk_; + const std::size_t max_vector_index_; }; template - class vector_assignment_node exprtk_final : public expression_node + class vector_celem_rtc_node exprtk_final + : public expression_node + , public ivariable { public: - typedef expression_node* expression_ptr; + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef std::pair branch_t; - vector_assignment_node(T* vector_base, - const std::size_t& size, - const std::vector& initialiser_list, - const bool single_value_initialse) - : vector_base_(vector_base) - , initialiser_list_(initialiser_list) - , size_(size) - , single_value_initialse_(single_value_initialse) - {} + vector_celem_rtc_node(expression_ptr vec_node, + const std::size_t index, + vector_holder_ptr vec_holder, + vector_access_runtime_check_ptr vec_rt_chk) + : index_(index) + , max_vector_index_(vec_holder->size() - 1) + , vector_holder_(vec_holder) + , vector_base_((*vec_holder)[0]) + , vec_rt_chk_(vec_rt_chk) + { + construct_branch_pair(vector_node_, vec_node); + assert(valid()); + } inline T value() const exprtk_override { - if (single_value_initialse_) - { - for (std::size_t i = 0; i < size_; ++i) - { - *(vector_base_ + i) = initialiser_list_[0]->value(); - } - } - else - { - const std::size_t initialiser_list_size = initialiser_list_.size(); - - for (std::size_t i = 0; i < initialiser_list_size; ++i) - { - *(vector_base_ + i) = initialiser_list_[i]->value(); - } + return *access_vector(); + } - if (initialiser_list_size < size_) - { - for (std::size_t i = initialiser_list_size; i < size_; ++i) - { - *(vector_base_ + i) = T(0); - } - } - } + inline T& ref() exprtk_override + { + return *access_vector(); + } - return *(vector_base_); + inline const T& ref() const exprtk_override + { + return *access_vector(); } inline typename expression_node::node_type type() const exprtk_override { - return expression_node::e_vecdefass; + return expression_node::e_veccelemrtc; + } + + inline bool valid() const exprtk_override + { + return + vector_holder_ && + vector_node_.first && + vector_node_.first->valid(); + } + + inline vector_holder_t& vec_holder() + { + return (*vector_holder_); } void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + expression_node::ndb_t::collect(vector_node_, node_delete_list); } std::size_t node_depth() const exprtk_override { - return expression_node::ndb_t::compute_node_depth(initialiser_list_); + return expression_node::ndb_t::compute_node_depth(vector_node_); } private: - vector_assignment_node(const vector_assignment_node&) exprtk_delete; - vector_assignment_node& operator=(const vector_assignment_node&) exprtk_delete; + inline T* access_vector() const + { + vector_node_.first->value(); + + if (index_ <= max_vector_index_) + { + return (vector_holder_->data() + index_); + } - mutable T* vector_base_; - std::vector initialiser_list_; - const std::size_t size_; - const bool single_value_initialse_; + assert(vec_rt_chk_); + + vector_access_runtime_check::violation_context context; + context.base_ptr = reinterpret_cast(vector_base_); + context.end_ptr = reinterpret_cast(vector_base_ + vector_holder_->size()); + context.access_ptr = reinterpret_cast(vector_base_ + index_); + context.type_size = sizeof(T); + + return vec_rt_chk_->handle_runtime_violation(context) ? + reinterpret_cast(context.access_ptr) : + vector_base_ ; + } + + const std::size_t index_; + const std::size_t max_vector_index_; + vector_holder_ptr vector_holder_; + T* vector_base_; + branch_t vector_node_; + vector_access_runtime_check_ptr vec_rt_chk_; }; template - class swap_node exprtk_final : public expression_node + class rebasevector_elem_node exprtk_final + : public expression_node + , public ivariable { public: - typedef expression_node* expression_ptr; - typedef variable_node* variable_node_ptr; + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef vec_data_store vds_t; + typedef std::pair branch_t; - swap_node(variable_node_ptr var0, variable_node_ptr var1) - : var0_(var0) - , var1_(var1) - {} + rebasevector_elem_node(expression_ptr vec_node, + expression_ptr index, + vector_holder_ptr vec_holder) + : vector_holder_(vec_holder) + { + construct_branch_pair(vector_node_, vec_node); + construct_branch_pair(index_ , index ); + assert(valid()); + } inline T value() const exprtk_override { - std::swap(var0_->ref(),var1_->ref()); - return var1_->ref(); + return *access_vector(); } - inline typename expression_node::node_type type() const exprtk_override + inline T& ref() exprtk_override { - return expression_node::e_swap; + return *access_vector(); } - private: - - variable_node_ptr var0_; - variable_node_ptr var1_; - }; + inline const T& ref() const exprtk_override + { + return *access_vector(); + } - template - class swap_generic_node exprtk_final : public binary_node - { - public: + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_rbvecelem; + } - typedef expression_node* expression_ptr; - typedef ivariable* ivariable_ptr; + inline bool valid() const exprtk_override + { + return + vector_holder_ && + index_.first && + vector_node_.first && + index_.first->valid() && + vector_node_.first->valid(); + } - swap_generic_node(expression_ptr var0, expression_ptr var1) - : binary_node(details::e_swap, var0, var1) - , var0_(dynamic_cast(var0)) - , var1_(dynamic_cast(var1)) - {} + inline vector_holder_t& vec_holder() + { + return (*vector_holder_); + } - inline T value() const exprtk_override + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - std::swap(var0_->ref(),var1_->ref()); - return var1_->ref(); + expression_node::ndb_t::collect(vector_node_, node_delete_list); + expression_node::ndb_t::collect(index_, node_delete_list); } - inline typename expression_node::node_type type() const exprtk_override + std::size_t node_depth() const exprtk_override { - return expression_node::e_swap; + return expression_node::ndb_t::compute_node_depth + (vector_node_, index_); } private: - ivariable_ptr var0_; - ivariable_ptr var1_; + inline T* access_vector() const + { + vector_node_.first->value(); + return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); + } + + vector_holder_ptr vector_holder_; + branch_t vector_node_; + branch_t index_; }; template - class swap_vecvec_node exprtk_final - : public binary_node - , public vector_interface + class rebasevector_celem_node exprtk_final + : public expression_node + , public ivariable { public: typedef expression_node* expression_ptr; - typedef vector_node * vector_node_ptr; - typedef vec_data_store vds_t; - - using binary_node::branch; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef std::pair branch_t; - swap_vecvec_node(expression_ptr branch0, - expression_ptr branch1) - : binary_node(details::e_swap, branch0, branch1) - , vec0_node_ptr_(0) - , vec1_node_ptr_(0) - , vec_size_ (0) - , initialised_ (false) + rebasevector_celem_node(expression_ptr vec_node, + const std::size_t index, + vector_holder_ptr vec_holder) + : index_(index) + , vector_holder_(vec_holder) { - if (is_ivector_node(branch(0))) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(branch(0)))) - { - vec0_node_ptr_ = vi->vec(); - vds() = vi->vds(); - } - } - - if (is_ivector_node(branch(1))) - { - vector_interface* vi = reinterpret_cast*>(0); - - if (0 != (vi = dynamic_cast*>(branch(1)))) - { - vec1_node_ptr_ = vi->vec(); - } - } - - if (vec0_node_ptr_ && vec1_node_ptr_) - { - vec_size_ = std::min(vec0_node_ptr_->vds().size(), - vec1_node_ptr_->vds().size()); - - initialised_ = true; - } - - assert(initialised_); + construct_branch_pair(vector_node_, vec_node); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) - { - assert(branch(0)); - assert(branch(1)); - - binary_node::branch(0)->value(); - binary_node::branch(1)->value(); - - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); - - for (std::size_t i = 0; i < vec_size_; ++i) - { - std::swap(vec0[i],vec1[i]); - } - - return vec1_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); + vector_node_.first->value(); + return ref();; } - vector_node_ptr vec() const exprtk_override + inline T& ref() exprtk_override { - return vec0_node_ptr_; + return *(vector_holder_->data() + index_); } - vector_node_ptr vec() exprtk_override + inline const T& ref() const exprtk_override { - return vec0_node_ptr_; + return *(vector_holder_->data() + index_); } inline typename expression_node::node_type type() const exprtk_override { - return expression_node::e_vecvecswap; + return expression_node::e_rbveccelem; } - std::size_t size() const exprtk_override + inline bool valid() const exprtk_override { - return vec_size_; + return + vector_holder_ && + vector_node_.first && + vector_node_.first->valid(); } - vds_t& vds() exprtk_override + inline vector_holder_t& vec_holder() { - return vds_; + return (*vector_holder_); } - const vds_t& vds() const exprtk_override + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - return vds_; + expression_node::ndb_t::collect(vector_node_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(vector_node_); } private: - vector_node* vec0_node_ptr_; - vector_node* vec1_node_ptr_; - std::size_t vec_size_; - bool initialised_; - vds_t vds_; + const std::size_t index_; + vector_holder_ptr vector_holder_; + branch_t vector_node_; }; - #ifndef exprtk_disable_string_capabilities template - class stringvar_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface + class rebasevector_elem_rtc_node exprtk_final + : public expression_node + , public ivariable { public: - typedef typename range_interface::range_t range_t; - - static std::string null_value; - - explicit stringvar_node() - : value_(&null_value) - {} - - explicit stringvar_node(std::string& v) - : value_(&v) - { - rp_.n0_c = std::make_pair(true,0); - rp_.n1_c = std::make_pair(true,v.size() - 1); - rp_.cache.first = rp_.n0_c.second; - rp_.cache.second = rp_.n1_c.second; - } + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef std::pair branch_t; - inline bool operator <(const stringvar_node& v) const + rebasevector_elem_rtc_node(expression_ptr vec_node, + expression_ptr index, + vector_holder_ptr vec_holder, + vector_access_runtime_check_ptr vec_rt_chk) + : vector_holder_(vec_holder) + , vec_rt_chk_(vec_rt_chk) { - return this < (&v); + construct_branch_pair(vector_node_, vec_node); + construct_branch_pair(index_ , index ); + assert(valid()); } inline T value() const exprtk_override { - rp_.n1_c.second = (*value_).size() - 1; - rp_.cache.second = rp_.n1_c.second; - - return std::numeric_limits::quiet_NaN(); + return *access_vector(); } - std::string str() const exprtk_override + inline T& ref() exprtk_override { - return ref(); + return *access_vector(); } - char_cptr base() const exprtk_override + inline const T& ref() const exprtk_override { - return &(*value_)[0]; + return *access_vector(); } - std::size_t size() const exprtk_override + inline typename expression_node::node_type type() const exprtk_override { - return ref().size(); + return expression_node::e_rbvecelemrtc; } - std::string& ref() + inline bool valid() const exprtk_override { - return (*value_); + return + vector_holder_ && + index_.first && + vector_node_.first && + index_.first->valid() && + vector_node_.first->valid(); } - const std::string& ref() const + inline vector_holder_t& vec_holder() { - return (*value_); + return (*vector_holder_); } - range_t& range_ref() exprtk_override + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - return rp_; + expression_node::ndb_t::collect(vector_node_, node_delete_list); + expression_node::ndb_t::collect(index_ , node_delete_list); } - const range_t& range_ref() const exprtk_override + std::size_t node_depth() const exprtk_override { - return rp_; + return expression_node::ndb_t::compute_node_depth + (vector_node_, index_); } - inline typename expression_node::node_type type() const exprtk_override - { - return expression_node::e_stringvar; - } + private: - void rebase(std::string& s) + inline T* access_vector() const { - value_ = &s; - rp_.n0_c = std::make_pair(true,0); - rp_.n1_c = std::make_pair(true,value_->size() - 1); - rp_.cache.first = rp_.n0_c.second; - rp_.cache.second = rp_.n1_c.second; - } + vector_node_.first->value(); + const _uint64_t index = details::numeric::to_uint64(index_.first->value()); - private: + if (index <= (vector_holder_->size() - 1)) + { + return (vector_holder_->data() + index); + } - std::string* value_; - mutable range_t rp_; - }; + assert(vec_rt_chk_); - template - std::string stringvar_node::null_value = std::string(""); + vector_access_runtime_check::violation_context context; + context.base_ptr = reinterpret_cast(vector_holder_->data()); + context.end_ptr = reinterpret_cast(vector_holder_->data() + vector_holder_->size()); + context.access_ptr = reinterpret_cast(vector_holder_->data() + index); + context.type_size = sizeof(T); + + return vec_rt_chk_->handle_runtime_violation(context) ? + reinterpret_cast(context.access_ptr) : + vector_holder_->data() ; + } + + vector_holder_ptr vector_holder_; + branch_t vector_node_; + branch_t index_; + vector_access_runtime_check_ptr vec_rt_chk_; + }; template - class string_range_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface + class rebasevector_celem_rtc_node exprtk_final + : public expression_node + , public ivariable { public: - typedef typename range_interface::range_t range_t; - - static std::string null_value; - - explicit string_range_node(std::string& v, const range_t& rp) - : value_(&v) - , rp_(rp) - {} + typedef expression_node* expression_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef std::pair branch_t; - virtual ~string_range_node() + rebasevector_celem_rtc_node(expression_ptr vec_node, + const std::size_t index, + vector_holder_ptr vec_holder, + vector_access_runtime_check_ptr vec_rt_chk) + : index_(index) + , vector_holder_(vec_holder) + , vector_base_((*vec_holder)[0]) + , vec_rt_chk_(vec_rt_chk) { - rp_.free(); + construct_branch_pair(vector_node_, vec_node); + assert(valid()); } - inline bool operator <(const string_range_node& v) const + inline T value() const exprtk_override { - return this < (&v); + return *access_vector(); } - inline T value() const exprtk_override + inline T& ref() exprtk_override { - return std::numeric_limits::quiet_NaN(); + return *access_vector(); } - inline std::string str() const exprtk_override + inline const T& ref() const exprtk_override { - return (*value_); + return *access_vector(); } - char_cptr base() const exprtk_override + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_rbveccelemrtc; + } + + inline bool valid() const exprtk_override + { + return + vector_holder_ && + vector_node_.first && + vector_node_.first->valid(); + } + + inline vector_holder_t& vec_holder() + { + return (*vector_holder_); + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(vector_node_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(vector_node_); + } + + private: + + inline T* access_vector() const + { + vector_node_.first->value(); + + if (index_ <= vector_holder_->size() - 1) + { + return (vector_holder_->data() + index_); + } + + assert(vec_rt_chk_); + + vector_access_runtime_check::violation_context context; + context.base_ptr = reinterpret_cast(vector_base_); + context.end_ptr = reinterpret_cast(vector_base_ + vector_holder_->size()); + context.access_ptr = reinterpret_cast(vector_base_ + index_); + context.type_size = sizeof(T); + + return vec_rt_chk_->handle_runtime_violation(context) ? + reinterpret_cast(context.access_ptr) : + vector_base_ ; + } + + const std::size_t index_; + vector_holder_ptr vector_holder_; + T* vector_base_; + branch_t vector_node_; + vector_access_runtime_check_ptr vec_rt_chk_; + }; + + template + class vector_initialisation_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_initialisation_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list, + const bool single_value_initialse) + : vector_base_(vector_base) + , initialiser_list_(initialiser_list) + , size_(size) + , single_value_initialse_(single_value_initialse) + , zero_value_initialse_(false) + , const_nonzero_literal_value_initialse_(false) + , single_initialiser_value_(T(0)) + { + if (single_value_initialse_) + { + if (initialiser_list_.empty()) + zero_value_initialse_ = true; + else if ( + (initialiser_list_.size() == 1) && + details::is_constant_node(initialiser_list_[0]) && + (T(0) == initialiser_list_[0]->value()) + ) + { + zero_value_initialse_ = true; + } + else + { + assert(initialiser_list_.size() == 1); + + if (details::is_constant_node(initialiser_list_[0])) + { + const_nonzero_literal_value_initialse_ = true; + single_initialiser_value_ = initialiser_list_[0]->value(); + assert(T(0) != single_initialiser_value_); + } + } + } + } + + inline T value() const exprtk_override + { + if (single_value_initialse_) + { + if (zero_value_initialse_) + { + details::set_zero_value(vector_base_, size_); + } + else if (const_nonzero_literal_value_initialse_) + { + for (std::size_t i = 0; i < size_; ++i) + { + *(vector_base_ + i) = single_initialiser_value_; + } + } + else + { + for (std::size_t i = 0; i < size_; ++i) + { + *(vector_base_ + i) = initialiser_list_[0]->value(); + } + } + } + else + { + const std::size_t initialiser_list_size = initialiser_list_.size(); + + for (std::size_t i = 0; i < initialiser_list_size; ++i) + { + *(vector_base_ + i) = initialiser_list_[i]->value(); + } + + if (initialiser_list_size < size_) + { + details::set_zero_value( + vector_base_ + initialiser_list_size, + (size_ - initialiser_list_size)); + } + } + + return *(vector_base_); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecinit; + } + + inline bool valid() const exprtk_override + { + return vector_base_; + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(initialiser_list_); + } + + private: + + vector_initialisation_node(const vector_initialisation_node&) exprtk_delete; + vector_initialisation_node& operator=(const vector_initialisation_node&) exprtk_delete; + + mutable T* vector_base_; + std::vector initialiser_list_; + const std::size_t size_; + const bool single_value_initialse_; + bool zero_value_initialse_; + bool const_nonzero_literal_value_initialse_; + T single_initialiser_value_; + }; + + template + class vector_init_zero_value_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_init_zero_value_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list) + : vector_base_(vector_base) + , size_(size) + , initialiser_list_(initialiser_list) + {} + + inline T value() const exprtk_override + { + details::set_zero_value(vector_base_, size_); + return *(vector_base_); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecinit; + } + + inline bool valid() const exprtk_override + { + return vector_base_; + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(initialiser_list_); + } + + private: + + vector_init_zero_value_node(const vector_init_zero_value_node&) exprtk_delete; + vector_init_zero_value_node& operator=(const vector_init_zero_value_node&) exprtk_delete; + + mutable T* vector_base_; + const std::size_t size_; + std::vector initialiser_list_; + }; + + template + class vector_init_single_constvalue_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_init_single_constvalue_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list) + : vector_base_(vector_base) + , size_(size) + , initialiser_list_(initialiser_list) + { + single_initialiser_value_ = initialiser_list_[0]->value(); + assert(valid()); + } + + inline T value() const exprtk_override + { + for (std::size_t i = 0; i < size_; ++i) + { + *(vector_base_ + i) = single_initialiser_value_; + } + + return *(vector_base_); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecinit; + } + + inline bool valid() const exprtk_override + { + return vector_base_ && + (initialiser_list_.size() == 1) && + (details::is_constant_node(initialiser_list_[0])) && + (single_initialiser_value_ != T(0)); + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(initialiser_list_); + } + + private: + + vector_init_single_constvalue_node(const vector_init_single_constvalue_node&) exprtk_delete; + vector_init_single_constvalue_node& operator=(const vector_init_single_constvalue_node&) exprtk_delete; + + mutable T* vector_base_; + const std::size_t size_; + std::vector initialiser_list_; + T single_initialiser_value_; + }; + + template + class vector_init_single_value_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_init_single_value_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list) + : vector_base_(vector_base) + , size_(size) + , initialiser_list_(initialiser_list) + { + assert(valid()); + } + + inline T value() const exprtk_override + { + expression_node& node = *initialiser_list_[0]; + + for (std::size_t i = 0; i < size_; ++i) + { + *(vector_base_ + i) = node.value(); + } + + return *(vector_base_); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecinit; + } + + inline bool valid() const exprtk_override + { + return vector_base_ && + (initialiser_list_.size() == 1) && + !details::is_constant_node(initialiser_list_[0]); + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(initialiser_list_); + } + + private: + + vector_init_single_value_node(const vector_init_single_value_node&) exprtk_delete; + vector_init_single_value_node& operator=(const vector_init_single_value_node&) exprtk_delete; + + mutable T* vector_base_; + const std::size_t size_; + std::vector initialiser_list_; + }; + + template + class vector_init_iota_constconst_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_init_iota_constconst_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list) + : vector_base_(vector_base) + , size_(size) + , initialiser_list_(initialiser_list) + { + base_value_ = initialiser_list_[0]->value(); + increment_value_ = initialiser_list_[1]->value(); + + assert(valid()); + } + + inline T value() const exprtk_override + { + T value = base_value_; + + for (std::size_t i = 0; i < size_; ++i, value += increment_value_) + { + *(vector_base_ + i) = value; + } + + return *(vector_base_); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecinit; + } + + inline bool valid() const exprtk_override + { + return vector_base_ && + (initialiser_list_.size() == 2) && + (details::is_constant_node(initialiser_list_[0])) && + (details::is_constant_node(initialiser_list_[1])) ; + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(initialiser_list_); + } + + private: + + vector_init_iota_constconst_node(const vector_init_iota_constconst_node&) exprtk_delete; + vector_init_iota_constconst_node& operator=(const vector_init_iota_constconst_node&) exprtk_delete; + + mutable T* vector_base_; + const std::size_t size_; + std::vector initialiser_list_; + T base_value_; + T increment_value_; + }; + + template + class vector_init_iota_constnconst_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_init_iota_constnconst_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list) + : vector_base_(vector_base) + , size_(size) + , initialiser_list_(initialiser_list) + { + assert(valid()); + base_value_ = initialiser_list_[0]->value(); + } + + inline T value() const exprtk_override + { + T value = base_value_; + expression_node& increment = *initialiser_list_[1]; + + for (std::size_t i = 0; i < size_; ++i, value += increment.value()) + { + *(vector_base_ + i) = value; + } + + return *(vector_base_); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecinit; + } + + inline bool valid() const exprtk_override + { + return vector_base_ && + (initialiser_list_.size() == 2) && + ( details::is_constant_node(initialiser_list_[0])) && + (!details::is_constant_node(initialiser_list_[1])); + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(initialiser_list_); + } + + private: + + vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node&) exprtk_delete; + vector_init_iota_constnconst_node& operator=(const vector_init_iota_constnconst_node&) exprtk_delete; + + mutable T* vector_base_; + const std::size_t size_; + std::vector initialiser_list_; + T base_value_; + }; + + template + class vector_init_iota_nconstconst_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_init_iota_nconstconst_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list) + : vector_base_(vector_base) + , size_(size) + , initialiser_list_(initialiser_list) + { + assert(valid()); + } + + inline T value() const exprtk_override + { + T value = initialiser_list_[0]->value(); + const T increment = initialiser_list_[1]->value(); + + for (std::size_t i = 0; i < size_; ++i, value += increment) + { + *(vector_base_ + i) = value; + } + + return *(vector_base_); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecinit; + } + + inline bool valid() const exprtk_override + { + return vector_base_ && + (initialiser_list_.size() == 2) && + (!details::is_constant_node(initialiser_list_[0])) && + (details::is_constant_node(initialiser_list_[1])); + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(initialiser_list_); + } + + private: + + vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node&) exprtk_delete; + vector_init_iota_nconstconst_node& operator=(const vector_init_iota_nconstconst_node&) exprtk_delete; + + mutable T* vector_base_; + const std::size_t size_; + std::vector initialiser_list_; + }; + + template + class vector_init_iota_nconstnconst_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vector_init_iota_nconstnconst_node(T* vector_base, + const std::size_t& size, + const std::vector& initialiser_list) + : vector_base_(vector_base) + , size_(size) + , initialiser_list_(initialiser_list) + { + assert(valid()); + } + + inline T value() const exprtk_override + { + T value = initialiser_list_[0]->value(); + expression_node& increment = *initialiser_list_[1]; + + for (std::size_t i = 0; i < size_; ++i, value += increment.value()) + { + *(vector_base_ + i) = value; + } + + return *(vector_base_); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecinit; + } + + inline bool valid() const exprtk_override + { + return vector_base_ && + (initialiser_list_.size() == 2) && + (!details::is_constant_node(initialiser_list_[0])) && + (!details::is_constant_node(initialiser_list_[1])); + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(initialiser_list_); + } + + private: + + vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node&) exprtk_delete; + vector_init_iota_nconstnconst_node& operator=(const vector_init_iota_nconstnconst_node&) exprtk_delete; + + mutable T* vector_base_; + const std::size_t size_; + std::vector initialiser_list_; + }; + + template + class swap_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef variable_node* variable_node_ptr; + + swap_node(variable_node_ptr var0, variable_node_ptr var1) + : var0_(var0) + , var1_(var1) + {} + + inline T value() const exprtk_override + { + std::swap(var0_->ref(),var1_->ref()); + return var1_->ref(); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_swap; + } + + private: + + variable_node_ptr var0_; + variable_node_ptr var1_; + }; + + template + class swap_generic_node exprtk_final : public binary_node + { + public: + + typedef expression_node* expression_ptr; + typedef ivariable* ivariable_ptr; + + swap_generic_node(expression_ptr var0, expression_ptr var1) + : binary_node(details::e_swap, var0, var1) + , var0_(dynamic_cast(var0)) + , var1_(dynamic_cast(var1)) + {} + + inline T value() const exprtk_override + { + std::swap(var0_->ref(),var1_->ref()); + return var1_->ref(); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_swap; + } + + private: + + ivariable_ptr var0_; + ivariable_ptr var1_; + }; + + template + class swap_vecvec_node exprtk_final + : public binary_node + , public vector_interface + { + public: + + typedef expression_node* expression_ptr; + typedef vector_node * vector_node_ptr; + typedef vec_data_store vds_t; + + using binary_node::branch; + + swap_vecvec_node(expression_ptr branch0, + expression_ptr branch1) + : binary_node(details::e_swap, branch0, branch1) + , vec0_node_ptr_(0) + , vec1_node_ptr_(0) + , initialised_ (false) + { + if (is_ivector_node(branch(0))) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(branch(0)))) + { + vec0_node_ptr_ = vi->vec(); + vds() = vi->vds(); + } + } + + if (is_ivector_node(branch(1))) + { + vector_interface* vi = reinterpret_cast*>(0); + + if (0 != (vi = dynamic_cast*>(branch(1)))) + { + vec1_node_ptr_ = vi->vec(); + } + } + + if (vec0_node_ptr_ && vec1_node_ptr_) + { + initialised_ = size() <= base_size(); + } + + assert(valid()); + } + + inline T value() const exprtk_override + { + binary_node::branch(0)->value(); + binary_node::branch(1)->value(); + + T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vec1_node_ptr_->vds().data(); + + assert(size() <= base_size()); + const std::size_t n = size(); + + for (std::size_t i = 0; i < n; ++i) + { + std::swap(vec0[i],vec1[i]); + } + + return vec1_node_ptr_->value(); + } + + vector_node_ptr vec() const exprtk_override + { + return vec0_node_ptr_; + } + + vector_node_ptr vec() exprtk_override + { + return vec0_node_ptr_; + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_vecvecswap; + } + + inline bool valid() const exprtk_override + { + return initialised_ && binary_node::valid(); + } + + std::size_t size() const exprtk_override + { + return std::min( + vec0_node_ptr_->vec_holder().size(), + vec1_node_ptr_->vec_holder().size()); + } + + std::size_t base_size() const exprtk_override + { + return std::min( + vec0_node_ptr_->vec_holder().base_size(), + vec1_node_ptr_->vec_holder().base_size()); + } + + vds_t& vds() exprtk_override + { + return vds_; + } + + const vds_t& vds() const exprtk_override + { + return vds_; + } + + private: + + vector_node* vec0_node_ptr_; + vector_node* vec1_node_ptr_; + bool initialised_; + vds_t vds_; + }; + + #ifndef exprtk_disable_string_capabilities + template + class stringvar_node exprtk_final + : public expression_node + , public string_base_node + , public range_interface + { + public: + + typedef typename range_interface::range_t range_t; + + static std::string null_value; + + explicit stringvar_node() + : value_(&null_value) + {} + + explicit stringvar_node(std::string& v) + : value_(&v) + { + rp_.n0_c = std::make_pair(true,0); + rp_.n1_c = std::make_pair(true,v.size()); + rp_.cache.first = rp_.n0_c.second; + rp_.cache.second = rp_.n1_c.second; + } + + inline bool operator <(const stringvar_node& v) const + { + return this < (&v); + } + + inline T value() const exprtk_override + { + rp_.n1_c.second = (*value_).size(); + rp_.cache.second = rp_.n1_c.second; + + return std::numeric_limits::quiet_NaN(); + } + + std::string str() const exprtk_override + { + return ref(); + } + + char_cptr base() const exprtk_override + { + return &(*value_)[0]; + } + + std::size_t size() const exprtk_override + { + return ref().size(); + } + + std::string& ref() + { + return (*value_); + } + + const std::string& ref() const + { + return (*value_); + } + + range_t& range_ref() exprtk_override + { + return rp_; + } + + const range_t& range_ref() const exprtk_override + { + return rp_; + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_stringvar; + } + + void rebase(std::string& s) + { + value_ = &s; + rp_.n0_c = std::make_pair(true,0); + rp_.n1_c = std::make_pair(true,value_->size() - 1); + rp_.cache.first = rp_.n0_c.second; + rp_.cache.second = rp_.n1_c.second; + } + + private: + + std::string* value_; + mutable range_t rp_; + }; + + template + std::string stringvar_node::null_value = std::string(""); + + template + class string_range_node exprtk_final + : public expression_node + , public string_base_node + , public range_interface + { + public: + + typedef typename range_interface::range_t range_t; + + static std::string null_value; + + explicit string_range_node(std::string& v, const range_t& rp) + : value_(&v) + , rp_(rp) + {} + + virtual ~string_range_node() + { + rp_.free(); + } + + inline bool operator <(const string_range_node& v) const + { + return this < (&v); + } + + inline T value() const exprtk_override + { + return std::numeric_limits::quiet_NaN(); + } + + inline std::string str() const exprtk_override + { + return (*value_); + } + + char_cptr base() const exprtk_override { return &(*value_)[0]; } @@ -8458,9 +10306,9 @@ namespace exprtk template class const_string_range_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface + : public expression_node + , public string_base_node + , public range_interface { public: @@ -8527,9 +10375,9 @@ namespace exprtk template class generic_string_range_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface + : public expression_node + , public string_base_node + , public range_interface { public: @@ -8569,8 +10417,7 @@ namespace exprtk } initialised_ = (str_base_ptr_ && str_range_ptr_); - - assert(initialised_); + assert(valid()); } ~generic_string_range_node() @@ -8580,34 +10427,184 @@ namespace exprtk inline T value() const exprtk_override { - if (initialised_) + branch_.first->value(); + + std::size_t str_r0 = 0; + std::size_t str_r1 = 0; + + std::size_t r0 = 0; + std::size_t r1 = 0; + + const range_t& range = str_range_ptr_->range_ref(); + + const std::size_t base_str_size = str_base_ptr_->size(); + + if ( + range (str_r0, str_r1, base_str_size ) && + base_range_(r0 , r1 , base_str_size - str_r0) + ) { - assert(branch_.first); + const std::size_t size = r1 - r0; - branch_.first->value(); + range_.n1_c.second = size; + range_.cache.second = range_.n1_c.second; - std::size_t str_r0 = 0; - std::size_t str_r1 = 0; + value_.assign(str_base_ptr_->base() + str_r0 + r0, size); + } - std::size_t r0 = 0; - std::size_t r1 = 0; + return std::numeric_limits::quiet_NaN(); + } - const range_t& range = str_range_ptr_->range_ref(); + std::string str() const exprtk_override + { + return value_; + } - const std::size_t base_str_size = str_base_ptr_->size(); + char_cptr base() const exprtk_override + { + return &value_[0]; + } - if ( - range (str_r0, str_r1, base_str_size) && - base_range_( r0, r1, base_str_size - str_r0) - ) - { - const std::size_t size = (r1 - r0) + 1; + std::size_t size() const exprtk_override + { + return value_.size(); + } - range_.n1_c.second = size - 1; - range_.cache.second = range_.n1_c.second; + range_t& range_ref() exprtk_override + { + return range_; + } - value_.assign(str_base_ptr_->base() + str_r0 + r0, size); - } + const range_t& range_ref() const exprtk_override + { + return range_; + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_strgenrange; + } + + inline bool valid() const exprtk_override + { + return initialised_ && branch_.first; + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth(branch_); + } + + private: + + bool initialised_; + branch_t branch_; + str_base_ptr str_base_ptr_; + irange_ptr str_range_ptr_; + mutable range_t base_range_; + mutable range_t range_; + mutable std::string value_; + }; + + template + class string_concat_node exprtk_final + : public binary_node + , public string_base_node + , public range_interface + { + public: + + typedef typename range_interface::range_t range_t; + typedef range_interface irange_t; + typedef irange_t* irange_ptr; + typedef range_t* range_ptr; + typedef expression_node * expression_ptr; + typedef string_base_node* str_base_ptr; + + using binary_node::branch; + + string_concat_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + , initialised_(false) + , str0_base_ptr_ (0) + , str1_base_ptr_ (0) + , str0_range_ptr_(0) + , str1_range_ptr_(0) + { + range_.n0_c = std::make_pair(true,0); + range_.n1_c = std::make_pair(true,0); + + range_.cache.first = range_.n0_c.second; + range_.cache.second = range_.n1_c.second; + + if (is_generally_string_node(branch(0))) + { + str0_base_ptr_ = dynamic_cast(branch(0)); + + if (0 == str0_base_ptr_) + return; + + str0_range_ptr_ = dynamic_cast(branch(0)); + + if (0 == str0_range_ptr_) + return; + } + + if (is_generally_string_node(branch(1))) + { + str1_base_ptr_ = dynamic_cast(branch(1)); + + if (0 == str1_base_ptr_) + return; + + str1_range_ptr_ = dynamic_cast(branch(1)); + + if (0 == str1_range_ptr_) + return; + } + + initialised_ = str0_base_ptr_ && + str1_base_ptr_ && + str0_range_ptr_ && + str1_range_ptr_ ; + + assert(valid()); + } + + inline T value() const exprtk_override + { + branch(0)->value(); + branch(1)->value(); + + std::size_t str0_r0 = 0; + std::size_t str0_r1 = 0; + + std::size_t str1_r0 = 0; + std::size_t str1_r1 = 0; + + const range_t& range0 = str0_range_ptr_->range_ref(); + const range_t& range1 = str1_range_ptr_->range_ref(); + + if ( + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) + ) + { + const std::size_t size0 = (str0_r1 - str0_r0); + const std::size_t size1 = (str1_r1 - str1_r0); + + value_.assign(str0_base_ptr_->base() + str0_r0, size0); + value_.append(str1_base_ptr_->base() + str1_r0, size1); + + range_.n1_c.second = value_.size(); + range_.cache.second = range_.n1_c.second; } return std::numeric_limits::quiet_NaN(); @@ -8640,163 +10637,12 @@ namespace exprtk inline typename expression_node::node_type type() const exprtk_override { - return expression_node::e_strgenrange; - } - - void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override - { - expression_node::ndb_t::collect(branch_, node_delete_list); - } - - std::size_t node_depth() const exprtk_override - { - return expression_node::ndb_t::compute_node_depth(branch_); - } - - private: - - bool initialised_; - branch_t branch_; - str_base_ptr str_base_ptr_; - irange_ptr str_range_ptr_; - mutable range_t base_range_; - mutable range_t range_; - mutable std::string value_; - }; - - template - class string_concat_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface - { - public: - - typedef typename range_interface::range_t range_t; - typedef range_interface irange_t; - typedef irange_t* irange_ptr; - typedef range_t* range_ptr; - typedef expression_node * expression_ptr; - typedef string_base_node* str_base_ptr; - - using binary_node::branch; - - string_concat_node(const operator_type& opr, - expression_ptr branch0, - expression_ptr branch1) - : binary_node(opr, branch0, branch1) - , initialised_(false) - , str0_base_ptr_ (0) - , str1_base_ptr_ (0) - , str0_range_ptr_(0) - , str1_range_ptr_(0) - { - range_.n0_c = std::make_pair(true,0); - range_.n1_c = std::make_pair(true,0); - - range_.cache.first = range_.n0_c.second; - range_.cache.second = range_.n1_c.second; - - if (is_generally_string_node(branch(0))) - { - str0_base_ptr_ = dynamic_cast(branch(0)); - - if (0 == str0_base_ptr_) - return; - - str0_range_ptr_ = dynamic_cast(branch(0)); - - if (0 == str0_range_ptr_) - return; - } - - if (is_generally_string_node(branch(1))) - { - str1_base_ptr_ = dynamic_cast(branch(1)); - - if (0 == str1_base_ptr_) - return; - - str1_range_ptr_ = dynamic_cast(branch(1)); - - if (0 == str1_range_ptr_) - return; - } - - initialised_ = str0_base_ptr_ && - str1_base_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ ; - - assert(initialised_); - } - - inline T value() const exprtk_override - { - if (initialised_) - { - assert(branch(0)); - assert(branch(1)); - - branch(0)->value(); - branch(1)->value(); - - std::size_t str0_r0 = 0; - std::size_t str0_r1 = 0; - - std::size_t str1_r0 = 0; - std::size_t str1_r1 = 0; - - const range_t& range0 = str0_range_ptr_->range_ref(); - const range_t& range1 = str1_range_ptr_->range_ref(); - - if ( - range0(str0_r0, str0_r1, str0_base_ptr_->size()) && - range1(str1_r0, str1_r1, str1_base_ptr_->size()) - ) - { - const std::size_t size0 = (str0_r1 - str0_r0) + 1; - const std::size_t size1 = (str1_r1 - str1_r0) + 1; - - value_.assign(str0_base_ptr_->base() + str0_r0, size0); - value_.append(str1_base_ptr_->base() + str1_r0, size1); - - range_.n1_c.second = value_.size() - 1; - range_.cache.second = range_.n1_c.second; - } - } - - return std::numeric_limits::quiet_NaN(); - } - - std::string str() const exprtk_override - { - return value_; - } - - char_cptr base() const exprtk_override - { - return &value_[0]; - } - - std::size_t size() const exprtk_override - { - return value_.size(); - } - - range_t& range_ref() exprtk_override - { - return range_; - } - - const range_t& range_ref() const exprtk_override - { - return range_; + return expression_node::e_strconcat; } - inline typename expression_node::node_type type() const exprtk_override + inline bool valid() const exprtk_override { - return expression_node::e_strconcat; + return initialised_ && binary_node::valid(); } private: @@ -8812,9 +10658,9 @@ namespace exprtk template class swap_string_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface + : public binary_node + , public string_base_node + , public range_interface { public: @@ -8829,10 +10675,10 @@ namespace exprtk using binary_node::branch; swap_string_node(expression_ptr branch0, expression_ptr branch1) - : binary_node(details::e_swap, branch0, branch1), - initialised_(false), - str0_node_ptr_(0), - str1_node_ptr_(0) + : binary_node(details::e_swap, branch0, branch1) + , initialised_(false) + , str0_node_ptr_(0) + , str1_node_ptr_(0) { if (is_string_node(branch(0))) { @@ -8845,22 +10691,15 @@ namespace exprtk } initialised_ = (str0_node_ptr_ && str1_node_ptr_); - - assert(initialised_); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) - { - assert(branch(0)); - assert(branch(1)); - - branch(0)->value(); - branch(1)->value(); + branch(0)->value(); + branch(1)->value(); - std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); - } + std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); return std::numeric_limits::quiet_NaN(); } @@ -8895,6 +10734,11 @@ namespace exprtk return expression_node::e_strswap; } + inline bool valid() const exprtk_override + { + return initialised_ && binary_node::valid(); + } + private: bool initialised_; @@ -8960,87 +10804,81 @@ namespace exprtk str0_range_ptr_ && str1_range_ptr_ ; - assert(initialised_); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) - { - assert(branch(0)); - assert(branch(1)); + branch(0)->value(); + branch(1)->value(); - branch(0)->value(); - branch(1)->value(); + std::size_t str0_r0 = 0; + std::size_t str0_r1 = 0; - std::size_t str0_r0 = 0; - std::size_t str0_r1 = 0; + std::size_t str1_r0 = 0; + std::size_t str1_r1 = 0; - std::size_t str1_r0 = 0; - std::size_t str1_r1 = 0; + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); - const range_t& range0 = (*str0_range_ptr_); - const range_t& range1 = (*str1_range_ptr_); + if ( + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) + ) + { + const std::size_t size0 = range0.cache_size(); + const std::size_t size1 = range1.cache_size(); + const std::size_t max_size = std::min(size0,size1); - if ( - range0(str0_r0, str0_r1, str0_base_ptr_->size()) && - range1(str1_r0, str1_r1, str1_base_ptr_->size()) - ) - { - const std::size_t size0 = range0.cache_size(); - const std::size_t size1 = range1.cache_size(); - const std::size_t max_size = std::min(size0,size1); + char_ptr s0 = const_cast(str0_base_ptr_->base() + str0_r0); + char_ptr s1 = const_cast(str1_base_ptr_->base() + str1_r0); - char_ptr s0 = const_cast(str0_base_ptr_->base() + str0_r0); - char_ptr s1 = const_cast(str1_base_ptr_->base() + str1_r0); + loop_unroll::details lud(max_size); + char_cptr upper_bound = s0 + lud.upper_bound; - loop_unroll::details lud(max_size); - char_cptr upper_bound = s0 + lud.upper_bound; + while (s0 < upper_bound) + { + #define exprtk_loop(N) \ + std::swap(s0[N], s1[N]); \ - while (s0 < upper_bound) - { - #define exprtk_loop(N) \ - std::swap(s0[N], s1[N]); \ - - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif - - s0 += lud.batch_size; - s1 += lud.batch_size; - } + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - int i = 0; + s0 += lud.batch_size; + s1 += lud.batch_size; + } - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { std::swap(s0[i], s1[i]); ++i; } \ - - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + int i = 0; - #undef exprtk_loop - #undef case_stmt + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { std::swap(s0[i], s1[i]); ++i; } \ + exprtk_fallthrough \ + + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + default: break; } + + #undef exprtk_loop + #undef case_stmt } return std::numeric_limits::quiet_NaN(); @@ -9051,6 +10889,11 @@ namespace exprtk return expression_node::e_strswap; } + inline bool valid() const exprtk_override + { + return initialised_ && binary_node::valid(); + } + private: swap_genstrings_node(const swap_genstrings_node&) exprtk_delete; @@ -9068,7 +10911,7 @@ namespace exprtk { public: - static std::string null_value; + static const std::string null_value; explicit stringvar_size_node() : value_(&null_value) @@ -9090,11 +10933,11 @@ namespace exprtk private: - std::string* value_; + const std::string* value_; }; template - std::string stringvar_size_node::null_value = std::string(""); + const std::string stringvar_size_node::null_value = std::string(""); template class string_size_node exprtk_final : public expression_node @@ -9113,23 +10956,15 @@ namespace exprtk if (is_generally_string_node(branch_.first)) { str_base_ptr_ = dynamic_cast(branch_.first); - - if (0 == str_base_ptr_) - return; } + + assert(valid()); } inline T value() const exprtk_override { - T result = std::numeric_limits::quiet_NaN(); - - if (str_base_ptr_) - { - branch_.first->value(); - result = T(str_base_ptr_->size()); - } - - return result; + branch_.first->value(); + return T(str_base_ptr_->size()); } inline typename expression_node::node_type type() const exprtk_override @@ -9137,6 +10972,11 @@ namespace exprtk return expression_node::e_stringsize; } + inline bool valid() const exprtk_override + { + return str_base_ptr_; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(branch_, node_delete_list); @@ -9149,7 +10989,7 @@ namespace exprtk private: - branch_t branch_; + branch_t branch_; str_base_ptr str_base_ptr_; }; @@ -9167,9 +11007,9 @@ namespace exprtk template class assignment_string_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface + : public binary_node + , public string_base_node + , public range_interface { public: @@ -9219,31 +11059,25 @@ namespace exprtk str0_node_ptr_ && str1_range_ptr_ ; - assert(initialised_); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) - { - assert(branch(0)); - assert(branch(1)); + branch(1)->value(); - branch(1)->value(); - - std::size_t r0 = 0; - std::size_t r1 = 0; + std::size_t r0 = 0; + std::size_t r1 = 0; - const range_t& range = (*str1_range_ptr_); + const range_t& range = (*str1_range_ptr_); - if (range(r0, r1, str1_base_ptr_->size())) - { - AssignmentProcess::execute(str0_node_ptr_->ref(), - str1_base_ptr_->base() + r0, - (r1 - r0) + 1); + if (range(r0, r1, str1_base_ptr_->size())) + { + AssignmentProcess::execute( + str0_node_ptr_->ref(), + str1_base_ptr_->base() + r0, (r1 - r0)); - branch(0)->value(); - } + branch(0)->value(); } return std::numeric_limits::quiet_NaN(); @@ -9279,6 +11113,11 @@ namespace exprtk return expression_node::e_strass; } + inline bool valid() const exprtk_override + { + return initialised_ && binary_node::valid(); + } + private: bool initialised_; @@ -9290,9 +11129,9 @@ namespace exprtk template class assignment_string_range_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface + : public binary_node + , public string_base_node + , public range_interface { public: @@ -9351,39 +11190,34 @@ namespace exprtk str0_range_ptr_ && str1_range_ptr_ ; - assert(initialised_); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) - { - assert(branch(0)); - assert(branch(1)); + branch(0)->value(); + branch(1)->value(); - branch(0)->value(); - branch(1)->value(); - - std::size_t s0_r0 = 0; - std::size_t s0_r1 = 0; + std::size_t s0_r0 = 0; + std::size_t s0_r1 = 0; - std::size_t s1_r0 = 0; - std::size_t s1_r1 = 0; + std::size_t s1_r0 = 0; + std::size_t s1_r1 = 0; - const range_t& range0 = (*str0_range_ptr_); - const range_t& range1 = (*str1_range_ptr_); + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); - if ( - range0(s0_r0, s0_r1, str0_base_ptr_->size()) && - range1(s1_r0, s1_r1, str1_base_ptr_->size()) - ) - { - const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1; + if ( + range0(s0_r0, s0_r1, str0_base_ptr_->size()) && + range1(s1_r0, s1_r1, str1_base_ptr_->size()) + ) + { + const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); - std::copy(str1_base_ptr_->base() + s1_r0, - str1_base_ptr_->base() + s1_r0 + size, - const_cast(base() + s0_r0)); - } + std::copy( + str1_base_ptr_->base() + s1_r0, + str1_base_ptr_->base() + s1_r0 + size, + const_cast(base() + s0_r0)); } return std::numeric_limits::quiet_NaN(); @@ -9419,6 +11253,11 @@ namespace exprtk return expression_node::e_strass; } + inline bool valid() const exprtk_override + { + return initialised_ && binary_node::valid(); + } + private: bool initialised_; @@ -9431,9 +11270,9 @@ namespace exprtk template class conditional_string_node exprtk_final - : public trinary_node , - public string_base_node, - public range_interface + : public trinary_node + , public string_base_node + , public range_interface { public: @@ -9494,55 +11333,48 @@ namespace exprtk str0_range_ptr_ && str1_range_ptr_ ; - assert(initialised_); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) + std::size_t r0 = 0; + std::size_t r1 = 0; + + if (is_true(condition_)) { - assert(condition_ ); - assert(consequent_ ); - assert(alternative_); + consequent_->value(); - std::size_t r0 = 0; - std::size_t r1 = 0; + const range_t& range = str0_range_ptr_->range_ref(); - if (is_true(condition_)) + if (range(r0, r1, str0_base_ptr_->size())) { - consequent_->value(); - - const range_t& range = str0_range_ptr_->range_ref(); + const std::size_t size = (r1 - r0); - if (range(r0, r1, str0_base_ptr_->size())) - { - const std::size_t size = (r1 - r0) + 1; + value_.assign(str0_base_ptr_->base() + r0, size); - value_.assign(str0_base_ptr_->base() + r0, size); - - range_.n1_c.second = value_.size() - 1; - range_.cache.second = range_.n1_c.second; + range_.n1_c.second = value_.size(); + range_.cache.second = range_.n1_c.second; - return T(1); - } + return T(1); } - else - { - alternative_->value(); + } + else + { + alternative_->value(); - const range_t& range = str1_range_ptr_->range_ref(); + const range_t& range = str1_range_ptr_->range_ref(); - if (range(r0, r1, str1_base_ptr_->size())) - { - const std::size_t size = (r1 - r0) + 1; + if (range(r0, r1, str1_base_ptr_->size())) + { + const std::size_t size = (r1 - r0); - value_.assign(str1_base_ptr_->base() + r0, size); + value_.assign(str1_base_ptr_->base() + r0, size); - range_.n1_c.second = value_.size() - 1; - range_.cache.second = range_.n1_c.second; + range_.n1_c.second = value_.size(); + range_.cache.second = range_.n1_c.second; - return T(0); - } + return T(0); } } @@ -9579,6 +11411,15 @@ namespace exprtk return expression_node::e_strcondition; } + inline bool valid() const exprtk_override + { + return + initialised_ && + condition_ && condition_ ->valid() && + consequent_ && consequent_ ->valid() && + alternative_&& alternative_->valid() ; + } + private: bool initialised_; @@ -9596,9 +11437,9 @@ namespace exprtk template class cons_conditional_str_node exprtk_final - : public binary_node , - public string_base_node, - public range_interface + : public binary_node + , public string_base_node + , public range_interface { public: @@ -9640,37 +11481,30 @@ namespace exprtk } initialised_ = str0_base_ptr_ && str0_range_ptr_ ; - - assert(initialised_); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) + if (is_true(condition_)) { - assert(condition_ ); - assert(consequent_); - - if (is_true(condition_)) - { - consequent_->value(); + consequent_->value(); - const range_t& range = str0_range_ptr_->range_ref(); + const range_t& range = str0_range_ptr_->range_ref(); - std::size_t r0 = 0; - std::size_t r1 = 0; + std::size_t r0 = 0; + std::size_t r1 = 0; - if (range(r0, r1, str0_base_ptr_->size())) - { - const std::size_t size = (r1 - r0) + 1; + if (range(r0, r1, str0_base_ptr_->size())) + { + const std::size_t size = (r1 - r0); - value_.assign(str0_base_ptr_->base() + r0, size); + value_.assign(str0_base_ptr_->base() + r0, size); - range_.n1_c.second = value_.size() - 1; - range_.cache.second = range_.n1_c.second; + range_.n1_c.second = value_.size(); + range_.cache.second = range_.n1_c.second; - return T(1); - } + return T(1); } } @@ -9707,6 +11541,14 @@ namespace exprtk return expression_node::e_strccondition; } + inline bool valid() const exprtk_override + { + return + initialised_ && + condition_ && condition_ ->valid() && + consequent_ && consequent_ ->valid() ; + } + private: bool initialised_; @@ -9721,9 +11563,9 @@ namespace exprtk template class str_vararg_node exprtk_final - : public expression_node , - public string_base_node, - public range_interface + : public expression_node + , public string_base_node + , public range_interface { public: @@ -9759,8 +11601,6 @@ namespace exprtk if (0 == str_range_ptr_) return; - initialised_ = str_base_ptr_ && str_range_ptr_; - if (arg_list.size() > 1) { const std::size_t arg_list_size = arg_list.size() - 1; @@ -9769,7 +11609,7 @@ namespace exprtk for (std::size_t i = 0; i < arg_list_size; ++i) { - if (arg_list[i]) + if (arg_list[i] && arg_list[i]->valid()) { construct_branch_pair(arg_list_[i], arg_list[i]); } @@ -9779,7 +11619,12 @@ namespace exprtk return; } } + + initialised_ = true; } + + initialised_ &= str_base_ptr_ && str_range_ptr_; + assert(valid()); } inline T value() const exprtk_override @@ -9824,6 +11669,13 @@ namespace exprtk return expression_node::e_stringvararg; } + inline bool valid() const exprtk_override + { + return + initialised_ && + final_node_.first && final_node_.first->valid(); + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(final_node_ , node_delete_list); @@ -9847,6 +11699,104 @@ namespace exprtk }; #endif + template + class assert_node exprtk_final : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + typedef string_base_node* str_base_ptr; + typedef assert_check::assert_context assert_context_t; + + assert_node(expression_ptr assert_condition_node, + expression_ptr assert_message_node, + assert_check_ptr assert_check, + assert_context_t context) + : assert_message_str_base_(0) + , assert_check_(assert_check) + , context_(context) + { + construct_branch_pair(assert_condition_node_, assert_condition_node); + construct_branch_pair(assert_message_node_ , assert_message_node ); + + #ifndef exprtk_disable_string_capabilities + if ( + assert_message_node_.first && + details::is_generally_string_node(assert_message_node_.first) + ) + { + assert_message_str_base_ = dynamic_cast(assert_message_node_.first); + } + #endif + + assert(valid()); + } + + inline T value() const exprtk_override + { + if (details::is_true(assert_condition_node_.first->value())) + { + return T(1); + } + + #ifndef exprtk_disable_string_capabilities + if (assert_message_node_.first) + { + assert_message_node_.first->value(); + assert(assert_message_str_base_); + context_.message = assert_message_str_base_->str(); + } + #endif + + assert_check_->handle_assert(context_); + return T(0); + } + + inline typename expression_node::node_type type() const exprtk_override + { + return expression_node::e_assert; + } + + inline bool valid() const exprtk_override + { + return ( + assert_check_ && + assert_condition_node_.first && + assert_condition_node_.first->valid() + ) && + ( + (0 == assert_message_node_.first) || + ( + assert_message_node_.first && + assert_message_str_base_ && + assert_message_node_.first->valid() && + details::is_generally_string_node(assert_message_node_.first) + ) + ); + } + + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override + { + expression_node::ndb_t::collect(assert_condition_node_, node_delete_list); + expression_node::ndb_t::collect(assert_message_node_ , node_delete_list); + } + + std::size_t node_depth() const exprtk_override + { + return expression_node::ndb_t::compute_node_depth + (assert_condition_node_, assert_message_node_); + } + + private: + + branch_t assert_condition_node_; + branch_t assert_message_node_; + str_base_ptr assert_message_str_base_; + assert_check_ptr assert_check_; + mutable assert_context_t context_; + }; + template inline T axn(const T a, const T x) { @@ -10087,10 +12037,6 @@ namespace exprtk inline T value() const exprtk_override { - assert(trinary_node::branch_[0].first); - assert(trinary_node::branch_[1].first); - assert(trinary_node::branch_[2].first); - const T x = trinary_node::branch_[0].first->value(); const T y = trinary_node::branch_[1].first->value(); const T z = trinary_node::branch_[2].first->value(); @@ -10116,11 +12062,6 @@ namespace exprtk inline T value() const exprtk_override { - assert(quaternary_node::branch_[0].first); - assert(quaternary_node::branch_[1].first); - assert(quaternary_node::branch_[2].first); - assert(quaternary_node::branch_[3].first); - const T x = quaternary_node::branch_[0].first->value(); const T y = quaternary_node::branch_[1].first->value(); const T z = quaternary_node::branch_[2].first->value(); @@ -10209,12 +12150,13 @@ namespace exprtk template class Sequence> explicit vararg_node(const Sequence& arg_list) + : initialised_(false) { arg_list_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { - if (arg_list[i]) + if (arg_list[i] && arg_list[i]->valid()) { construct_branch_pair(arg_list_[i],arg_list[i]); } @@ -10224,6 +12166,9 @@ namespace exprtk return; } } + + initialised_ = (arg_list_.size() == arg_list.size()); + assert(valid()); } inline T value() const exprtk_override @@ -10236,6 +12181,11 @@ namespace exprtk return expression_node::e_vararg; } + inline bool valid() const exprtk_override + { + return initialised_; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(arg_list_, node_delete_list); @@ -10246,9 +12196,20 @@ namespace exprtk return expression_node::ndb_t::compute_node_depth(arg_list_); } + std::size_t size() const + { + return arg_list_.size(); + } + + expression_ptr operator[](const std::size_t& index) const + { + return arg_list_[index].first; + } + private: std::vector arg_list_; + bool initialised_; }; template @@ -10261,12 +12222,13 @@ namespace exprtk template class Sequence> explicit vararg_varnode(const Sequence& arg_list) + : initialised_(false) { arg_list_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { - if (arg_list[i] && is_variable_node(arg_list[i])) + if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) { variable_node* var_node_ptr = static_cast*>(arg_list[i]); arg_list_[i] = (&var_node_ptr->ref()); @@ -10277,14 +12239,14 @@ namespace exprtk return; } } + + initialised_ = (arg_list.size() == arg_list_.size()); + assert(valid()); } inline T value() const exprtk_override { - if (!arg_list_.empty()) - return VarArgFunction::process(arg_list_); - else - return std::numeric_limits::quiet_NaN(); + return VarArgFunction::process(arg_list_); } inline typename expression_node::node_type type() const exprtk_override @@ -10292,9 +12254,15 @@ namespace exprtk return expression_node::e_vararg; } + inline bool valid() const exprtk_override + { + return initialised_; + } + private: std::vector arg_list_; + bool initialised_; }; template @@ -10314,22 +12282,12 @@ namespace exprtk { ivec_ptr_ = dynamic_cast*>(v_.first); } - else - ivec_ptr_ = 0; } inline T value() const exprtk_override { - if (ivec_ptr_) - { - assert(v_.first); - - v_.first->value(); - - return VecFunction::process(ivec_ptr_); - } - else - return std::numeric_limits::quiet_NaN(); + v_.first->value(); + return VecFunction::process(ivec_ptr_); } inline typename expression_node::node_type type() const exprtk_override @@ -10337,6 +12295,11 @@ namespace exprtk return expression_node::e_vecfunc; } + inline bool valid() const exprtk_override + { + return ivec_ptr_ && v_.first && v_.first->valid(); + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(v_, node_delete_list); @@ -10375,17 +12338,15 @@ namespace exprtk inline T value() const exprtk_override { - if (var_node_ptr_) - { - assert(branch(1)); - - T& result = var_node_ptr_->ref(); + T& result = var_node_ptr_->ref(); result = branch(1)->value(); - return result; - } - else - return std::numeric_limits::quiet_NaN(); + return result; + } + + inline bool valid() const exprtk_override + { + return var_node_ptr_ && binary_node::valid(); } private: @@ -10411,26 +12372,66 @@ namespace exprtk { vec_node_ptr_ = static_cast*>(branch(0)); } + + assert(valid()); } inline T value() const exprtk_override { - if (vec_node_ptr_) + T& result = vec_node_ptr_->ref(); + result = branch(1)->value(); + + return result; + } + + inline bool valid() const exprtk_override + { + return vec_node_ptr_ && binary_node::valid(); + } + + private: + + vector_elem_node* vec_node_ptr_; + }; + + template + class assignment_vec_elem_rtc_node exprtk_final : public binary_node + { + public: + + typedef expression_node* expression_ptr; + using binary_node::branch; + + assignment_vec_elem_rtc_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + , vec_node_ptr_(0) + { + if (is_vector_elem_rtc_node(branch(0))) { - assert(branch(1)); + vec_node_ptr_ = static_cast*>(branch(0)); + } + + assert(valid()); + } - T& result = vec_node_ptr_->ref(); + inline T value() const exprtk_override + { + T& result = vec_node_ptr_->ref(); result = branch(1)->value(); - return result; - } - else - return std::numeric_limits::quiet_NaN(); + return result; + } + + inline bool valid() const exprtk_override + { + return vec_node_ptr_ && binary_node::valid(); } private: - vector_elem_node* vec_node_ptr_; + vector_elem_rtc_node* vec_node_ptr_; }; template @@ -10451,27 +12452,66 @@ namespace exprtk { rbvec_node_ptr_ = static_cast*>(branch(0)); } + + assert(valid()); } inline T value() const exprtk_override { - if (rbvec_node_ptr_) + T& result = rbvec_node_ptr_->ref(); + result = branch(1)->value(); + + return result; + } + + inline bool valid() const exprtk_override + { + return rbvec_node_ptr_ && binary_node::valid(); + } + + private: + + rebasevector_elem_node* rbvec_node_ptr_; + }; + + template + class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node + { + public: + + typedef expression_node* expression_ptr; + using expression_node::branch; + + assignment_rebasevec_elem_rtc_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + , rbvec_node_ptr_(0) + { + if (is_rebasevector_elem_rtc_node(branch(0))) { - assert(branch(1)); + rbvec_node_ptr_ = static_cast*>(branch(0)); + } - T& result = rbvec_node_ptr_->ref(); + assert(valid()); + } + inline T value() const exprtk_override + { + T& result = rbvec_node_ptr_->ref(); result = branch(1)->value(); - return result; - } - else - return std::numeric_limits::quiet_NaN(); + return result; + } + + inline bool valid() const exprtk_override + { + return rbvec_node_ptr_ && binary_node::valid(); } private: - rebasevector_elem_node* rbvec_node_ptr_; + rebasevector_elem_rtc_node* rbvec_node_ptr_; }; template @@ -10492,21 +12532,21 @@ namespace exprtk { rbvec_node_ptr_ = static_cast*>(branch(0)); } + + assert(valid()); } inline T value() const exprtk_override { - if (rbvec_node_ptr_) - { - assert(branch(1)); - - T& result = rbvec_node_ptr_->ref(); + T& result = rbvec_node_ptr_->ref(); result = branch(1)->value(); - return result; - } - else - return std::numeric_limits::quiet_NaN(); + return result; + } + + inline bool valid() const exprtk_override + { + return rbvec_node_ptr_ && binary_node::valid(); } private: @@ -10538,66 +12578,60 @@ namespace exprtk vec_node_ptr_ = static_cast*>(branch(0)); vds() = vec_node_ptr_->vds(); } + + assert(valid()); } inline T value() const exprtk_override { - if (vec_node_ptr_) - { - assert(branch(1)); + const T v = branch(1)->value(); - const T v = branch(1)->value(); + T* vec = vds().data(); - T* vec = vds().data(); - - loop_unroll::details lud(size()); - const T* upper_bound = vec + lud.upper_bound; + loop_unroll::details lud(size()); + const T* upper_bound = vec + lud.upper_bound; - while (vec < upper_bound) - { - #define exprtk_loop(N) \ - vec[N] = v; \ + while (vec < upper_bound) + { + #define exprtk_loop(N) \ + vec[N] = v; \ - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - vec += lud.batch_size; - } + vec += lud.batch_size; + } - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : *vec++ = v; \ + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : *vec++ = v; \ + exprtk_fallthrough \ - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case 1 : *vec++ = v; + } - #undef exprtk_loop - #undef case_stmt + #undef exprtk_loop + #undef case_stmt - return vec_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); + return vec_node_ptr_->value(); } vector_node_ptr vec() const exprtk_override @@ -10615,9 +12649,22 @@ namespace exprtk return expression_node::e_vecvalass; } + inline bool valid() const exprtk_override + { + return + vec_node_ptr_ && + (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && + binary_node::valid(); + } + std::size_t size() const exprtk_override { - return vds().size(); + return vec_node_ptr_->vec_holder().size(); + } + + std::size_t base_size() const exprtk_override + { + return vec_node_ptr_->vec_holder().base_size(); } vds_t& vds() exprtk_override @@ -10687,74 +12734,71 @@ namespace exprtk } } - initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); + initialised_ = + vec0_node_ptr_ && + vec1_node_ptr_ && + (size() <= base_size()) && + (vds_.size() <= base_size()) && + binary_node::valid(); - assert(initialised_); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) - { - assert(branch(1)); + branch(1)->value(); - branch(1)->value(); - - if (src_is_ivec_) - return vec0_node_ptr_->value(); + if (src_is_ivec_) + return vec0_node_ptr_->value(); - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); + T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vec1_node_ptr_->vds().data(); - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec0[N] = vec1[N]; \ + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec0[N] = vec1[N]; \ - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : *vec0++ = *vec1++; \ + switch (lud.remainder) + { + #define case_stmt(N,fall_through) \ + case N : *vec0++ = *vec1++; \ + fall_through \ - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) + case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) + case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) + case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) + case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) + case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) + #endif + case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) + case_stmt( 1, (void)0;) + } - #undef exprtk_loop - #undef case_stmt + #undef exprtk_loop + #undef case_stmt - return vec0_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); + return vec0_node_ptr_->value(); } vector_node_ptr vec() exprtk_override @@ -10772,9 +12816,23 @@ namespace exprtk return expression_node::e_vecvecass; } + inline bool valid() const exprtk_override + { + return initialised_; + } + std::size_t size() const exprtk_override { - return vds().size(); + return std::min( + vec0_node_ptr_->vec_holder().size(), + vec1_node_ptr_->vec_holder().size()); + } + + std::size_t base_size() const exprtk_override + { + return std::min( + vec0_node_ptr_->vec_holder().base_size(), + vec1_node_ptr_->vec_holder().base_size()); } vds_t& vds() exprtk_override @@ -10814,21 +12872,21 @@ namespace exprtk { var_node_ptr_ = static_cast*>(branch(0)); } + + assert(valid()); } inline T value() const exprtk_override { - if (var_node_ptr_) - { - assert(branch(1)); + T& v = var_node_ptr_->ref(); + v = Operation::process(v,branch(1)->value()); - T& v = var_node_ptr_->ref(); - v = Operation::process(v,branch(1)->value()); + return v; + } - return v; - } - else - return std::numeric_limits::quiet_NaN(); + inline bool valid() const exprtk_override + { + return var_node_ptr_ && binary_node::valid(); } private: @@ -10854,26 +12912,106 @@ namespace exprtk { vec_node_ptr_ = static_cast*>(branch(0)); } + + assert(valid()); } inline T value() const exprtk_override { - if (vec_node_ptr_) + T& v = vec_node_ptr_->ref(); + v = Operation::process(v,branch(1)->value()); + + return v; + } + + inline bool valid() const exprtk_override + { + return vec_node_ptr_ && binary_node::valid(); + } + + private: + + vector_elem_node* vec_node_ptr_; + }; + + template + class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node + { + public: + + typedef expression_node* expression_ptr; + using binary_node::branch; + + assignment_vec_elem_op_rtc_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + , vec_node_ptr_(0) + { + if (is_vector_elem_rtc_node(branch(0))) { - assert(branch(1)); + vec_node_ptr_ = static_cast*>(branch(0)); + } + + assert(valid()); + } + + inline T value() const exprtk_override + { + T& v = vec_node_ptr_->ref(); + v = Operation::process(v,branch(1)->value()); + + return v; + } + + inline bool valid() const exprtk_override + { + return vec_node_ptr_ && binary_node::valid(); + } + + private: + + vector_elem_rtc_node* vec_node_ptr_; + }; + + template + class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node + { + public: - T& v = vec_node_ptr_->ref(); - v = Operation::process(v,branch(1)->value()); + typedef expression_node* expression_ptr; + using binary_node::branch; - return v; + assignment_vec_celem_op_rtc_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + , vec_node_ptr_(0) + { + if (is_vector_celem_rtc_node(branch(0))) + { + vec_node_ptr_ = static_cast*>(branch(0)); } - else - return std::numeric_limits::quiet_NaN(); + + assert(valid()); + } + + inline T value() const exprtk_override + { + T& v = vec_node_ptr_->ref(); + v = Operation::process(v,branch(1)->value()); + + return v; + } + + inline bool valid() const exprtk_override + { + return vec_node_ptr_ && binary_node::valid(); } private: - vector_elem_node* vec_node_ptr_; + vector_celem_rtc_node* vec_node_ptr_; }; template @@ -10894,21 +13032,21 @@ namespace exprtk { rbvec_node_ptr_ = static_cast*>(branch(0)); } + + assert(valid()); } inline T value() const exprtk_override { - if (rbvec_node_ptr_) - { - assert(branch(1)); + T& v = rbvec_node_ptr_->ref(); + v = Operation::process(v,branch(1)->value()); - T& v = rbvec_node_ptr_->ref(); - v = Operation::process(v,branch(1)->value()); + return v; + } - return v; - } - else - return std::numeric_limits::quiet_NaN(); + inline bool valid() const exprtk_override + { + return rbvec_node_ptr_ && binary_node::valid(); } private: @@ -10934,26 +13072,106 @@ namespace exprtk { rbvec_node_ptr_ = static_cast*>(branch(0)); } + + assert(valid()); } inline T value() const exprtk_override { - if (rbvec_node_ptr_) + T& v = rbvec_node_ptr_->ref(); + v = Operation::process(v,branch(1)->value()); + + return v; + } + + inline bool valid() const exprtk_override + { + return rbvec_node_ptr_ && binary_node::valid(); + } + + private: + + rebasevector_celem_node* rbvec_node_ptr_; + }; + + template + class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node + { + public: + + typedef expression_node* expression_ptr; + using binary_node::branch; + + assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + , rbvec_node_ptr_(0) + { + if (is_rebasevector_elem_rtc_node(branch(0))) { - assert(branch(1)); + rbvec_node_ptr_ = static_cast*>(branch(0)); + } + + assert(valid()); + } + + inline T value() const exprtk_override + { + T& v = rbvec_node_ptr_->ref(); + v = Operation::process(v,branch(1)->value()); + + return v; + } + + inline bool valid() const exprtk_override + { + return rbvec_node_ptr_ && binary_node::valid(); + } - T& v = rbvec_node_ptr_->ref(); - v = Operation::process(v,branch(1)->value()); + private: + + rebasevector_elem_rtc_node* rbvec_node_ptr_; + }; + + template + class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node + { + public: + + typedef expression_node* expression_ptr; + using binary_node::branch; - return v; + assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(opr, branch0, branch1) + , rbvec_node_ptr_(0) + { + if (is_rebasevector_celem_rtc_node(branch(0))) + { + rbvec_node_ptr_ = static_cast*>(branch(0)); } - else - return std::numeric_limits::quiet_NaN(); + + assert(valid()); + } + + inline T value() const exprtk_override + { + T& v = rbvec_node_ptr_->ref(); + v = Operation::process(v,branch(1)->value()); + + return v; + } + + inline bool valid() const exprtk_override + { + return rbvec_node_ptr_ && binary_node::valid(); } private: - rebasevector_celem_node* rbvec_node_ptr_; + rebasevector_celem_rtc_node* rbvec_node_ptr_; }; template @@ -10980,66 +13198,60 @@ namespace exprtk vec_node_ptr_ = static_cast*>(branch(0)); vds() = vec_node_ptr_->vds(); } + + assert(valid()); } inline T value() const exprtk_override { - if (vec_node_ptr_) - { - assert(branch(1)); - - const T v = branch(1)->value(); + const T v = branch(1)->value(); - T* vec = vds().data(); + T* vec = vds().data(); - loop_unroll::details lud(size()); - const T* upper_bound = vec + lud.upper_bound; + loop_unroll::details lud(size()); + const T* upper_bound = vec + lud.upper_bound; - while (vec < upper_bound) - { - #define exprtk_loop(N) \ - Operation::assign(vec[N],v); \ + while (vec < upper_bound) + { + #define exprtk_loop(N) \ + Operation::assign(vec[N],v); \ - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - vec += lud.batch_size; - } + vec += lud.batch_size; + } - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : Operation::assign(*vec++,v); \ + switch (lud.remainder) + { + #define case_stmt(N,fall_through) \ + case N : Operation::assign(*vec++,v); \ + fall_through \ - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) + case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) + case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) + case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) + case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) + case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) + #endif + case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) + case_stmt( 1, (void)0;) + } - #undef exprtk_loop - #undef case_stmt + #undef exprtk_loop + #undef case_stmt - return vec_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); + return vec_node_ptr_->value(); } vector_node_ptr vec() const exprtk_override @@ -11057,9 +13269,22 @@ namespace exprtk return expression_node::e_vecopvalass; } + inline bool valid() const exprtk_override + { + return + vec_node_ptr_ && + (size() <= base_size()) && + binary_node::valid() ; + } + std::size_t size() const exprtk_override { - return vds().size(); + return vec_node_ptr_->vec_holder().size(); + } + + std::size_t base_size() const exprtk_override + { + return vec_node_ptr_->vec_holder().base_size(); } vds_t& vds() exprtk_override @@ -11122,81 +13347,76 @@ namespace exprtk if (0 != (vi = dynamic_cast*>(branch(1)))) { vec1_node_ptr_ = vi->vec(); - vec1_node_ptr_->vds() = vds(); + vec1_node_ptr_->vds() = vi->vds(); } else vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); } - initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); + initialised_ = + vec0_node_ptr_ && + vec1_node_ptr_ && + (size() <= base_size()) && + binary_node::valid(); - assert(initialised_); + assert(valid()); } inline T value() const exprtk_override { - if (initialised_) - { - assert(branch(0)); - assert(branch(1)); - - branch(0)->value(); - branch(1)->value(); + branch(0)->value(); + branch(1)->value(); - T* vec0 = vec0_node_ptr_->vds().data(); - const T* vec1 = vec1_node_ptr_->vds().data(); + T* vec0 = vec0_node_ptr_->vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec0[N] = Operation::process(vec0[N], vec1[N]); \ + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec0[N] = Operation::process(vec0[N], vec1[N]); \ - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } - int i = 0; + int i = 0; - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ + switch (lud.remainder) + { + #define case_stmt(N,fall_through) \ + case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ + fall_through \ - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) + case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) + case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) + case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) + case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) + case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) + #endif + case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) + case_stmt( 1, (void)0;) + } - #undef exprtk_loop - #undef case_stmt + #undef exprtk_loop + #undef case_stmt - return vec0_node_ptr_->value(); - } - else - return std::numeric_limits::quiet_NaN(); + return vec0_node_ptr_->value(); } vector_node_ptr vec() const exprtk_override @@ -11214,9 +13434,23 @@ namespace exprtk return expression_node::e_vecopvecass; } + inline bool valid() const exprtk_override + { + return initialised_; + } + std::size_t size() const exprtk_override { - return vds().size(); + return std::min( + vec0_node_ptr_->vec_holder().size(), + vec1_node_ptr_->vec_holder().size()); + } + + std::size_t base_size() const exprtk_override + { + return std::min( + vec0_node_ptr_->vec_holder().base_size(), + vec1_node_ptr_->vec_holder().base_size()); } vds_t& vds() exprtk_override @@ -11242,6 +13476,64 @@ namespace exprtk vds_t vds_; }; + template + struct memory_context_t + { + typedef vector_node* vector_node_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + + memory_context_t() + : temp_(0) + , temp_vec_node_(0) + {} + + void clear() + { + delete temp_vec_node_; + delete temp_; + } + + vector_holder_ptr temp_; + vector_node_ptr temp_vec_node_; + }; + + template + inline memory_context_t make_memory_context(vector_holder& vec_holder, + vec_data_store& vds) + { + memory_context_t result_ctxt; + result_ctxt.temp_ = (vec_holder.rebaseable()) ? + new vector_holder(vec_holder,vds) : + new vector_holder(vds) ; + result_ctxt.temp_vec_node_ = new vector_node (vds,result_ctxt.temp_); + return result_ctxt; + } + + template + inline memory_context_t make_memory_context(vector_holder& vec_holder0, + vector_holder& vec_holder1, + vec_data_store& vds) + { + memory_context_t result_ctxt; + + if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) + result_ctxt.temp_ = new vector_holder(vds); + else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) + result_ctxt.temp_ = new vector_holder(vec_holder0,vds); + else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) + result_ctxt.temp_ = new vector_holder(vec_holder1,vds); + else + { + result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? + new vector_holder(vec_holder0, vds) : + new vector_holder(vec_holder1, vds) ; + } + + result_ctxt.temp_vec_node_ = new vector_node (vds,result_ctxt.temp_); + return result_ctxt; + } + template class vec_binop_vecvec_node exprtk_final : public binary_node @@ -11251,8 +13543,10 @@ namespace exprtk typedef expression_node* expression_ptr; typedef vector_node* vector_node_ptr; - typedef vector_holder* vector_holder_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; typedef vec_data_store vds_t; + typedef memory_context_t memory_context; using binary_node::branch; @@ -11262,8 +13556,6 @@ namespace exprtk : binary_node(opr, branch0, branch1) , vec0_node_ptr_(0) , vec1_node_ptr_(0) - , temp_ (0) - , temp_vec_node_(0) , initialised_(false) { bool v0_is_ivec = false; @@ -11304,104 +13596,102 @@ namespace exprtk vector_holder& vec0 = vec0_node_ptr_->vec_holder(); vector_holder& vec1 = vec1_node_ptr_->vec_holder(); - if (v0_is_ivec && (vec0.size() <= vec1.size())) + if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) + { vds_ = vds_t(vec0_node_ptr_->vds()); - else if (v1_is_ivec && (vec1.size() <= vec0.size())) + } + else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) + { vds_ = vds_t(vec1_node_ptr_->vds()); + } else - vds_ = vds_t(std::min(vec0.size(),vec1.size())); + { + vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); + } - temp_ = new vector_holder(vds().data(),vds().size()); - temp_vec_node_ = new vector_node (vds(),temp_); + memory_context_ = make_memory_context(vec0, vec1, vds()); - initialised_ = true; + initialised_ = + (size() <= base_size()) && + binary_node::valid(); } - assert(initialised_); + assert(valid()); } ~vec_binop_vecvec_node() { - delete temp_; - delete temp_vec_node_; + memory_context_.clear(); } inline T value() const exprtk_override { - if (initialised_) - { - assert(branch(0)); - assert(branch(1)); - - branch(0)->value(); - branch(1)->value(); + branch(0)->value(); + branch(1)->value(); - const T* vec0 = vec0_node_ptr_->vds().data(); - const T* vec1 = vec1_node_ptr_->vds().data(); - T* vec2 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); + T* vec2 = vds().data(); - loop_unroll::details lud(size()); - const T* upper_bound = vec2 + lud.upper_bound; + loop_unroll::details lud(size()); + const T* upper_bound = vec2 + lud.upper_bound; - while (vec2 < upper_bound) - { - #define exprtk_loop(N) \ - vec2[N] = Operation::process(vec0[N], vec1[N]); \ + while (vec2 < upper_bound) + { + #define exprtk_loop(N) \ + vec2[N] = Operation::process(vec0[N], vec1[N]); \ - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - vec0 += lud.batch_size; - vec1 += lud.batch_size; - vec2 += lud.batch_size; - } + vec0 += lud.batch_size; + vec1 += lud.batch_size; + vec2 += lud.batch_size; + } - int i = 0; + int i = 0; - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ + exprtk_fallthrough \ - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + default: break; + } - #undef exprtk_loop - #undef case_stmt + #undef exprtk_loop + #undef case_stmt - return (vds().data())[0]; - } - else - return std::numeric_limits::quiet_NaN(); + return (vds().data())[0]; } vector_node_ptr vec() const exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } vector_node_ptr vec() exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } inline typename expression_node::node_type type() const exprtk_override @@ -11409,9 +13699,23 @@ namespace exprtk return expression_node::e_vecvecarith; } + inline bool valid() const exprtk_override + { + return initialised_; + } + std::size_t size() const exprtk_override { - return vds_.size(); + return std::min( + vec0_node_ptr_->vec_holder().size(), + vec1_node_ptr_->vec_holder().size()); + } + + std::size_t base_size() const exprtk_override + { + return std::min( + vec0_node_ptr_->vec_holder().base_size(), + vec1_node_ptr_->vec_holder().base_size()); } vds_t& vds() exprtk_override @@ -11426,12 +13730,11 @@ namespace exprtk private: - vector_node_ptr vec0_node_ptr_; - vector_node_ptr vec1_node_ptr_; - vector_holder_ptr temp_; - vector_node_ptr temp_vec_node_; - bool initialised_; - vds_t vds_; + vector_node_ptr vec0_node_ptr_; + vector_node_ptr vec1_node_ptr_; + bool initialised_; + vds_t vds_; + memory_context memory_context_; }; template @@ -11443,8 +13746,10 @@ namespace exprtk typedef expression_node* expression_ptr; typedef vector_node* vector_node_ptr; - typedef vector_holder* vector_holder_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; typedef vec_data_store vds_t; + typedef memory_context_t memory_context; using binary_node::branch; @@ -11453,8 +13758,6 @@ namespace exprtk expression_ptr branch1) : binary_node(opr, branch0, branch1) , vec0_node_ptr_(0) - , temp_ (0) - , temp_vec_node_(0) { bool v0_is_ivec = false; @@ -11478,93 +13781,84 @@ namespace exprtk if (v0_is_ivec) vds() = vec0_node_ptr_->vds(); else - vds() = vds_t(vec0_node_ptr_->size()); + vds() = vds_t(vec0_node_ptr_->base_size()); - temp_ = new vector_holder(vds()); - temp_vec_node_ = new vector_node (vds(),temp_); + memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); } + + assert(valid()); } ~vec_binop_vecval_node() { - delete temp_; - delete temp_vec_node_; + memory_context_.clear(); } inline T value() const exprtk_override { - if (vec0_node_ptr_) - { - assert(branch(0)); - assert(branch(1)); - - branch(0)->value(); - const T v = branch(1)->value(); + branch(0)->value(); + const T v = branch(1)->value(); - const T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vds().data(); - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec1[N] = Operation::process(vec0[N], v); \ + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec1[N] = Operation::process(vec0[N], v); \ - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } - int i = 0; + int i = 0; - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ + switch (lud.remainder) + { + #define case_stmt(N,fall_through) \ + case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ + fall_through \ - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) + case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) + case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) + case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) + case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) + case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) + #endif + case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) + case_stmt( 1, (void)0;) + } - #undef exprtk_loop - #undef case_stmt + #undef exprtk_loop + #undef case_stmt - return (vds().data())[0]; - } - else - return std::numeric_limits::quiet_NaN(); + return (vds().data())[0]; } vector_node_ptr vec() const exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } vector_node_ptr vec() exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } inline typename expression_node::node_type type() const exprtk_override @@ -11572,9 +13866,22 @@ namespace exprtk return expression_node::e_vecvalarith; } + inline bool valid() const exprtk_override + { + return + vec0_node_ptr_ && + (size() <= base_size()) && + binary_node::valid(); + } + std::size_t size() const exprtk_override { - return vds().size(); + return vec0_node_ptr_->size(); + } + + std::size_t base_size() const exprtk_override + { + return vec0_node_ptr_->vec_holder().base_size(); } vds_t& vds() exprtk_override @@ -11590,9 +13897,8 @@ namespace exprtk private: vector_node_ptr vec0_node_ptr_; - vector_holder_ptr temp_; - vector_node_ptr temp_vec_node_; vds_t vds_; + memory_context memory_context_; }; template @@ -11604,8 +13910,10 @@ namespace exprtk typedef expression_node* expression_ptr; typedef vector_node* vector_node_ptr; - typedef vector_holder* vector_holder_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; typedef vec_data_store vds_t; + typedef memory_context_t memory_context; using binary_node::branch; @@ -11614,8 +13922,6 @@ namespace exprtk expression_ptr branch1) : binary_node(opr, branch0, branch1) , vec1_node_ptr_(0) - , temp_ (0) - , temp_vec_node_(0) { bool v1_is_ivec = false; @@ -11639,93 +13945,84 @@ namespace exprtk if (v1_is_ivec) vds() = vec1_node_ptr_->vds(); else - vds() = vds_t(vec1_node_ptr_->size()); + vds() = vds_t(vec1_node_ptr_->base_size()); - temp_ = new vector_holder(vds()); - temp_vec_node_ = new vector_node (vds(),temp_); + memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); } + + assert(valid()); } ~vec_binop_valvec_node() { - delete temp_; - delete temp_vec_node_; + memory_context_.clear(); } inline T value() const exprtk_override { - if (vec1_node_ptr_) - { - assert(branch(0)); - assert(branch(1)); - - const T v = branch(0)->value(); - branch(1)->value(); + const T v = branch(0)->value(); + branch(1)->value(); - T* vec0 = vds().data(); - const T* vec1 = vec1_node_ptr_->vds().data(); + T* vec0 = vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec0[N] = Operation::process(v, vec1[N]); \ + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec0[N] = Operation::process(v, vec1[N]); \ - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } - int i = 0; + int i = 0; - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ + switch (lud.remainder) + { + #define case_stmt(N,fall_through) \ + case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ + fall_through \ - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) + case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) + case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) + case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) + case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) + case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) + #endif + case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) + case_stmt( 1, (void)0;) + } - #undef exprtk_loop - #undef case_stmt + #undef exprtk_loop + #undef case_stmt - return (vds().data())[0]; - } - else - return std::numeric_limits::quiet_NaN(); + return (vds().data())[0]; } vector_node_ptr vec() const exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } vector_node_ptr vec() exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } inline typename expression_node::node_type type() const exprtk_override @@ -11733,9 +14030,23 @@ namespace exprtk return expression_node::e_vecvalarith; } + inline bool valid() const exprtk_override + { + return + vec1_node_ptr_ && + (size() <= base_size()) && + (vds_.size() <= base_size()) && + binary_node::valid(); + } + std::size_t size() const exprtk_override { - return vds().size(); + return vec1_node_ptr_->vec_holder().size(); + } + + std::size_t base_size() const exprtk_override + { + return vec1_node_ptr_->vec_holder().base_size(); } vds_t& vds() exprtk_override @@ -11751,9 +14062,8 @@ namespace exprtk private: vector_node_ptr vec1_node_ptr_; - vector_holder_ptr temp_; - vector_node_ptr temp_vec_node_; vds_t vds_; + memory_context memory_context_; }; template @@ -11765,28 +14075,28 @@ namespace exprtk typedef expression_node* expression_ptr; typedef vector_node* vector_node_ptr; - typedef vector_holder* vector_holder_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; typedef vec_data_store vds_t; + typedef memory_context_t memory_context; using expression_node::branch; unary_vector_node(const operator_type& opr, expression_ptr branch0) : unary_node(opr, branch0) , vec0_node_ptr_(0) - , temp_ (0) - , temp_vec_node_(0) { bool vec0_is_ivec = false; - if (is_vector_node(branch())) + if (is_vector_node(branch(0))) { - vec0_node_ptr_ = static_cast(branch()); + vec0_node_ptr_ = static_cast(branch(0)); } - else if (is_ivector_node(branch())) + else if (is_ivector_node(branch(0))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(branch()))) + if (0 != (vi = dynamic_cast*>(branch(0)))) { vec0_node_ptr_ = vi->vec(); vec0_is_ivec = true; @@ -11798,91 +14108,84 @@ namespace exprtk if (vec0_is_ivec) vds_ = vec0_node_ptr_->vds(); else - vds_ = vds_t(vec0_node_ptr_->size()); + vds_ = vds_t(vec0_node_ptr_->base_size()); - temp_ = new vector_holder(vds()); - temp_vec_node_ = new vector_node (vds(),temp_); + memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); } + + assert(valid()); } ~unary_vector_node() { - delete temp_; - delete temp_vec_node_; + memory_context_.clear(); } inline T value() const exprtk_override { - assert(branch()); - branch()->value(); - if (vec0_node_ptr_) - { - const T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vds().data(); - loop_unroll::details lud(size()); - const T* upper_bound = vec0 + lud.upper_bound; + loop_unroll::details lud(size()); + const T* upper_bound = vec0 + lud.upper_bound; - while (vec0 < upper_bound) - { - #define exprtk_loop(N) \ - vec1[N] = Operation::process(vec0[N]); \ + while (vec0 < upper_bound) + { + #define exprtk_loop(N) \ + vec1[N] = Operation::process(vec0[N]); \ - exprtk_loop( 0) exprtk_loop( 1) - exprtk_loop( 2) exprtk_loop( 3) - #ifndef exprtk_disable_superscalar_unroll - exprtk_loop( 4) exprtk_loop( 5) - exprtk_loop( 6) exprtk_loop( 7) - exprtk_loop( 8) exprtk_loop( 9) - exprtk_loop(10) exprtk_loop(11) - exprtk_loop(12) exprtk_loop(13) - exprtk_loop(14) exprtk_loop(15) - #endif + exprtk_loop( 0) exprtk_loop( 1) + exprtk_loop( 2) exprtk_loop( 3) + #ifndef exprtk_disable_superscalar_unroll + exprtk_loop( 4) exprtk_loop( 5) + exprtk_loop( 6) exprtk_loop( 7) + exprtk_loop( 8) exprtk_loop( 9) + exprtk_loop(10) exprtk_loop(11) + exprtk_loop(12) exprtk_loop(13) + exprtk_loop(14) exprtk_loop(15) + #endif - vec0 += lud.batch_size; - vec1 += lud.batch_size; - } + vec0 += lud.batch_size; + vec1 += lud.batch_size; + } - int i = 0; + int i = 0; - exprtk_disable_fallthrough_begin - switch (lud.remainder) - { - #define case_stmt(N) \ - case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ + switch (lud.remainder) + { + #define case_stmt(N) \ + case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ + exprtk_fallthrough \ - #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) - #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) - } - exprtk_disable_fallthrough_end + #ifndef exprtk_disable_superscalar_unroll + case_stmt(15) case_stmt(14) + case_stmt(13) case_stmt(12) + case_stmt(11) case_stmt(10) + case_stmt( 9) case_stmt( 8) + case_stmt( 7) case_stmt( 6) + case_stmt( 5) case_stmt( 4) + #endif + case_stmt( 3) case_stmt( 2) + case_stmt( 1) + default: break; + } - #undef exprtk_loop - #undef case_stmt + #undef exprtk_loop + #undef case_stmt - return (vds().data())[0]; - } - else - return std::numeric_limits::quiet_NaN(); + return (vds().data())[0]; } vector_node_ptr vec() const exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } vector_node_ptr vec() exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } inline typename expression_node::node_type type() const exprtk_override @@ -11890,9 +14193,19 @@ namespace exprtk return expression_node::e_vecunaryop; } + inline bool valid() const exprtk_override + { + return vec0_node_ptr_ && unary_node::valid(); + } + std::size_t size() const exprtk_override { - return vds().size(); + return vec0_node_ptr_->vec_holder().size(); + } + + std::size_t base_size() const exprtk_override + { + return vec0_node_ptr_->vec_holder().base_size(); } vds_t& vds() exprtk_override @@ -11907,10 +14220,9 @@ namespace exprtk private: - vector_node_ptr vec0_node_ptr_; - vector_holder_ptr temp_; - vector_node_ptr temp_vec_node_; - vds_t vds_; + vector_node_ptr vec0_node_ptr_; + vds_t vds_; + memory_context memory_context_; }; template @@ -11923,8 +14235,10 @@ namespace exprtk typedef expression_node * expression_ptr; typedef vector_interface* vec_interface_ptr; typedef vector_node * vector_node_ptr; - typedef vector_holder * vector_holder_ptr; + typedef vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; typedef vec_data_store vds_t; + typedef memory_context_t memory_context; typedef std::pair branch_t; conditional_vector_node(expression_ptr condition, @@ -11934,7 +14248,7 @@ namespace exprtk , alternative_node_ptr_(0) , temp_vec_node_ (0) , temp_ (0) - , vec_size_ (0) + , result_vec_size_ (0) , initialised_ (false) { construct_branch_pair(condition_ , condition ); @@ -11963,67 +14277,62 @@ namespace exprtk if (consequent_node_ptr_ && alternative_node_ptr_) { - vec_size_ = std::min(consequent_node_ptr_ ->vds().size(), - alternative_node_ptr_->vds().size()); + const std::size_t vec_size = + std::max(consequent_node_ptr_ ->vec_holder().base_size(), + alternative_node_ptr_->vec_holder().base_size()); - vds_ = vds_t(vec_size_); - temp_ = new vector_holder(vds_); - temp_vec_node_ = new vector_node (vds(),temp_); + vds_ = vds_t(vec_size); + memory_context_ = make_memory_context( + consequent_node_ptr_ ->vec_holder(), + alternative_node_ptr_->vec_holder(), + vds()); - initialised_ = true; + initialised_ = (vec_size > 0); } - assert(initialised_ && (vec_size_ > 0)); + assert(initialised_); } ~conditional_vector_node() { - delete temp_; - delete temp_vec_node_; + memory_context_.clear(); } inline T value() const exprtk_override { - if (initialised_) - { - assert(condition_ .first); - assert(consequent_ .first); - assert(alternative_.first); - - T result = T(0); - T* source_vector = 0; - T* result_vector = vds().data(); - - if (is_true(condition_)) - { - result = consequent_.first->value(); - source_vector = consequent_node_ptr_->vds().data(); - } - else - { - result = alternative_.first->value(); - source_vector = alternative_node_ptr_->vds().data(); - } + T result = T(0); + T* source_vector = 0; + T* result_vector = vds().data(); - for (std::size_t i = 0; i < vec_size_; ++i) - { - result_vector[i] = source_vector[i]; - } + if (is_true(condition_)) + { + result = consequent_.first->value(); + source_vector = consequent_node_ptr_->vds().data(); + result_vec_size_ = consequent_node_ptr_->size(); + } + else + { + result = alternative_.first->value(); + source_vector = alternative_node_ptr_->vds().data(); + result_vec_size_ = alternative_node_ptr_->size(); + } - return result; + for (std::size_t i = 0; i < result_vec_size_; ++i) + { + result_vector[i] = source_vector[i]; } - return std::numeric_limits::quiet_NaN(); + return result; } vector_node_ptr vec() const exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } vector_node_ptr vec() exprtk_override { - return temp_vec_node_; + return memory_context_.temp_vec_node_; } inline typename expression_node::node_type type() const exprtk_override @@ -12031,9 +14340,26 @@ namespace exprtk return expression_node::e_vecondition; } + inline bool valid() const exprtk_override + { + return + initialised_ && + condition_ .first && condition_ .first->valid() && + consequent_ .first && consequent_ .first->valid() && + alternative_.first && alternative_.first->valid() && + size() <= base_size(); + } + std::size_t size() const exprtk_override { - return vec_size_; + return result_vec_size_; + } + + std::size_t base_size() const exprtk_override + { + return std::min( + consequent_node_ptr_ ->vec_holder().base_size(), + alternative_node_ptr_->vec_holder().base_size()); } vds_t& vds() exprtk_override @@ -12061,16 +14387,17 @@ namespace exprtk private: - branch_t condition_; - branch_t consequent_; - branch_t alternative_; - vector_node_ptr consequent_node_ptr_; - vector_node_ptr alternative_node_ptr_; - vector_node_ptr temp_vec_node_; - vector_holder_ptr temp_; - vds_t vds_; - std::size_t vec_size_; - bool initialised_; + branch_t condition_; + branch_t consequent_; + branch_t alternative_; + vector_node_ptr consequent_node_ptr_; + vector_node_ptr alternative_node_ptr_; + vector_node_ptr temp_vec_node_; + vector_holder_ptr temp_; + vds_t vds_; + mutable std::size_t result_vec_size_; + bool initialised_; + memory_context memory_context_; }; template @@ -12085,13 +14412,12 @@ namespace exprtk expression_ptr branch0, expression_ptr branch1) : binary_node(opr, branch0, branch1) - {} + { + assert(binary_node::valid()); + } inline T value() const exprtk_override { - assert(branch(0)); - assert(branch(1)); - return ( std::not_equal_to() (T(0),branch(0)->value()) && @@ -12113,13 +14439,12 @@ namespace exprtk expression_ptr branch0, expression_ptr branch1) : binary_node(opr, branch0, branch1) - {} + { + assert(binary_node::valid()); + } inline T value() const exprtk_override { - assert(branch(0)); - assert(branch(1)); - return ( std::not_equal_to() (T(0),branch(0)->value()) || @@ -12134,7 +14459,7 @@ namespace exprtk { public: - // Function of N paramters. + // Function of N parameters. typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef IFunction ifunction; @@ -12142,6 +14467,7 @@ namespace exprtk explicit function_N_node(ifunction* func) : function_((N == func->param_count) ? func : reinterpret_cast(0)) , parameter_count_(func->param_count) + , initialised_(false) {} template @@ -12152,19 +14478,24 @@ namespace exprtk #pragma warning(push) #pragma warning(disable: 4127) #endif + if (N != NumBranches) + { return false; - else + } + + for (std::size_t i = 0; i < NumBranches; ++i) { - for (std::size_t i = 0; i < NumBranches; ++i) - { - if (b[i]) - branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); - else - return false; - } - return true; + if (b[i] && b[i]->valid()) + branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); + else + return false; } + + initialised_ = function_; + assert(valid()); + return initialised_; + #ifdef _MSC_VER #pragma warning(pop) #endif @@ -12182,14 +14513,11 @@ namespace exprtk #pragma warning(push) #pragma warning(disable: 4127) #endif - if ((0 == function_) || (0 == N)) - return std::numeric_limits::quiet_NaN(); - else - { - T v[N]; - evaluate_branches::execute(v,branch_); - return invoke::execute(*function_,v); - } + + T v[N]; + evaluate_branches::execute(v,branch_); + return invoke::execute(*function_,v); + #ifdef _MSC_VER #pragma warning(pop) #endif @@ -12200,9 +14528,14 @@ namespace exprtk return expression_node::e_function; } + inline bool valid() const exprtk_override + { + return initialised_; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override @@ -12222,6 +14555,20 @@ namespace exprtk } }; + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + v[2] = b[2].first->value(); + v[3] = b[3].first->value(); + v[4] = b[4].first->value(); + v[5] = b[5].first->value(); + } + }; + template struct evaluate_branches { @@ -12425,6 +14772,7 @@ namespace exprtk ifunction* function_; std::size_t parameter_count_; branch_t branch_[N]; + bool initialised_; }; template @@ -12437,7 +14785,9 @@ namespace exprtk explicit function_N_node(ifunction* func) : function_((0 == func->param_count) ? func : reinterpret_cast(0)) - {} + { + assert(valid()); + } inline bool operator <(const function_N_node& fn) const { @@ -12446,10 +14796,7 @@ namespace exprtk inline T value() const exprtk_override { - if (function_) - return (*function_)(); - else - return std::numeric_limits::quiet_NaN(); + return (*function_)(); } inline typename expression_node::node_type type() const exprtk_override @@ -12457,6 +14804,11 @@ namespace exprtk return expression_node::e_function; } + inline bool valid() const exprtk_override + { + return function_; + } + private: ifunction* function_; @@ -12475,6 +14827,7 @@ namespace exprtk , arg_list_(arg_list) { value_list_.resize(arg_list.size(),std::numeric_limits::quiet_NaN()); + assert(valid()); } inline bool operator <(const vararg_function_node& fn) const @@ -12484,13 +14837,8 @@ namespace exprtk inline T value() const exprtk_override { - if (function_) - { - populate_value_list(); - return (*function_)(value_list_); - } - else - return std::numeric_limits::quiet_NaN(); + populate_value_list(); + return (*function_)(value_list_); } inline typename expression_node::node_type type() const exprtk_override @@ -12498,6 +14846,11 @@ namespace exprtk return expression_node::e_vafunction; } + inline bool valid() const exprtk_override + { + return function_; + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { for (std::size_t i = 0; i < arg_list_.size(); ++i) @@ -12545,7 +14898,8 @@ namespace exprtk typedef typename range_interface::range_t range_t; typedef std::pair branch_t; - typedef std::pair void_t; + typedef vector_holder* vh_t; + typedef vector_view* vecview_t; typedef std::vector tmp_vs_t; typedef std::vector typestore_list_t; @@ -12557,7 +14911,18 @@ namespace exprtk , arg_list_(arg_list) {} - virtual ~generic_function_node() {} + virtual ~generic_function_node() + { + for (std::size_t i = 0; i < vv_list_.size(); ++i) + { + vecview_t& vv = vv_list_[i]; + if (vv && typestore_list_[i].vec_data) + { + vv->remove_ref(&typestore_list_[i].vec_data); + typestore_list_[i].vec_data = 0; + } + } + } void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { @@ -12571,10 +14936,11 @@ namespace exprtk virtual bool init_branches() { - expr_as_vec1_store_.resize(arg_list_.size(),T(0) ); - typestore_list_ .resize(arg_list_.size(),type_store_t() ); - range_list_ .resize(arg_list_.size(),range_data_type_t()); - branch_ .resize(arg_list_.size(),branch_t(reinterpret_cast(0),false)); + expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); + typestore_list_ .resize(arg_list_.size(), type_store_t() ); + range_list_ .resize(arg_list_.size(), range_data_type_t()); + branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast(0),false)); + vv_list_ .resize(arg_list_.size(), vecview_t(0)); for (std::size_t i = 0; i < arg_list_.size(); ++i) { @@ -12592,7 +14958,15 @@ namespace exprtk ts.size = vi->size(); ts.data = vi->vds().data(); ts.type = type_store_t::e_vector; - vi->vec()->vec_holder().set_ref(&ts.vec_data); + + if ( + vi->vec()->vec_holder().rebaseable() && + vi->vec()->vec_holder().rebaseable_instance() + ) + { + vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); + vv_list_[i]->set_ref(&ts.vec_data); + } } #ifndef exprtk_disable_string_capabilities else if (is_generally_string_node(arg_list_[i])) @@ -12628,7 +15002,10 @@ namespace exprtk range_list_[i].range = reinterpret_cast(0); } else + { range_list_[i].range = &(ri->range_ref()); + range_param_list_.push_back(i); + } } #endif else if (is_variable_node(arg_list_[i])) @@ -12662,14 +15039,11 @@ namespace exprtk inline T value() const exprtk_override { - if (function_) + if (populate_value_list()) { - if (populate_value_list()) - { - typedef typename GenericFunction::parameter_list_t parameter_list_t; + typedef typename GenericFunction::parameter_list_t parameter_list_t; - return (*function_)(parameter_list_t(typestore_list_)); - } + return (*function_)(parameter_list_t(typestore_list_)); } return std::numeric_limits::quiet_NaN(); @@ -12680,6 +15054,11 @@ namespace exprtk return expression_node::e_genfunction; } + inline bool valid() const exprtk_override + { + return function_; + } + protected: inline virtual bool populate_value_list() const @@ -12689,30 +15068,40 @@ namespace exprtk expr_as_vec1_store_[i] = branch_[i].first->value(); } - for (std::size_t i = 0; i < branch_.size(); ++i) + if (!range_param_list_.empty()) { - range_data_type_t& rdt = range_list_[i]; + assert(range_param_list_.size() <= branch_.size()); - if (rdt.range) + for (std::size_t i = 0; i < range_param_list_.size(); ++i) { + const std::size_t index = range_param_list_[i]; + range_data_type_t& rdt = range_list_[index]; + const range_t& rp = (*rdt.range); std::size_t r0 = 0; std::size_t r1 = 0; - if (rp(r0, r1, rdt.size)) - { - type_store_t& ts = typestore_list_[i]; + const std::size_t data_size = + #ifndef exprtk_disable_string_capabilities + rdt.str_node ? rdt.str_node->size() : rdt.size; + #else + rdt.size; + #endif - ts.size = rp.cache_size(); - #ifndef exprtk_disable_string_capabilities - if (ts.type == type_store_t::e_string) - ts.data = const_cast(rdt.str_node->base()) + rp.cache.first; - else - #endif - ts.data = static_cast(rdt.data) + (rp.cache.first * rdt.type_size); + if (!rp(r0, r1, data_size)) + { + return false; } + + type_store_t& ts = typestore_list_[index]; + + ts.size = rp.cache_size(); + #ifndef exprtk_disable_string_capabilities + if (ts.type == type_store_t::e_string) + ts.data = const_cast(rdt.str_node->base()) + rp.cache.first; else - return false; + #endif + ts.data = static_cast(rdt.data) + (rp.cache.first * rdt.type_size); } } @@ -12725,16 +15114,18 @@ namespace exprtk private: std::vector arg_list_; - std::vector branch_; - mutable tmp_vs_t expr_as_vec1_store_; - mutable range_list_t range_list_; + std::vector branch_; + std::vector vv_list_; + mutable tmp_vs_t expr_as_vec1_store_; + mutable range_list_t range_list_; + std::vector range_param_list_; }; #ifndef exprtk_disable_string_capabilities template - class string_function_node : public generic_function_node, - public string_base_node, - public range_interface + class string_function_node : public generic_function_node + , public string_base_node + , public range_interface { public: @@ -12749,6 +15140,7 @@ namespace exprtk range_.n1_c = std::make_pair(true,0); range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; + assert(valid()); } inline bool operator <(const string_function_node& fn) const @@ -12758,23 +15150,21 @@ namespace exprtk inline T value() const exprtk_override { - if (gen_function_t::function_) + if (gen_function_t::populate_value_list()) { - if (gen_function_t::populate_value_list()) - { - typedef typename StringFunction::parameter_list_t parameter_list_t; + typedef typename StringFunction::parameter_list_t parameter_list_t; - const T result = (*gen_function_t::function_) - ( - ret_string_, - parameter_list_t(gen_function_t::typestore_list_) - ); + const T result = + (*gen_function_t::function_) + ( + ret_string_, + parameter_list_t(gen_function_t::typestore_list_) + ); - range_.n1_c.second = ret_string_.size() - 1; - range_.cache.second = range_.n1_c.second; + range_.n1_c.second = ret_string_.size(); + range_.cache.second = range_.n1_c.second; - return result; - } + return result; } return std::numeric_limits::quiet_NaN(); @@ -12785,6 +15175,11 @@ namespace exprtk return expression_node::e_strfunction; } + inline bool valid() const exprtk_override + { + return gen_function_t::function_; + } + std::string str() const exprtk_override { return ret_string_; @@ -12834,18 +15229,18 @@ namespace exprtk inline T value() const exprtk_override { - if (gen_function_t::function_) + assert(gen_function_t::valid()); + + if (gen_function_t::populate_value_list()) { - if (gen_function_t::populate_value_list()) - { - typedef typename GenericFunction::parameter_list_t parameter_list_t; + typedef typename GenericFunction::parameter_list_t parameter_list_t; - return (*gen_function_t::function_) - ( - param_seq_index_, - parameter_list_t(gen_function_t::typestore_list_) - ); - } + return + (*gen_function_t::function_) + ( + param_seq_index_, + parameter_list_t(gen_function_t::typestore_list_) + ); } return std::numeric_limits::quiet_NaN(); @@ -12879,24 +15274,22 @@ namespace exprtk inline T value() const exprtk_override { - if (str_function_t::function_) + if (str_function_t::populate_value_list()) { - if (str_function_t::populate_value_list()) - { - typedef typename StringFunction::parameter_list_t parameter_list_t; + typedef typename StringFunction::parameter_list_t parameter_list_t; - const T result = (*str_function_t::function_) - ( - param_seq_index_, - str_function_t::ret_string_, - parameter_list_t(str_function_t::typestore_list_) - ); + const T result = + (*str_function_t::function_) + ( + param_seq_index_, + str_function_t::ret_string_, + parameter_list_t(str_function_t::typestore_list_) + ); - str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1; - str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; + str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); + str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; - return result; - } + return result; } return std::numeric_limits::quiet_NaN(); @@ -12913,15 +15306,15 @@ namespace exprtk }; #endif - class return_exception - {}; + class return_exception {}; template class null_igenfunc { public: - virtual ~null_igenfunc() {} + virtual ~null_igenfunc() + {} typedef type_store generic_type; typedef typename generic_type::parameter_list parameter_list_t; @@ -12947,14 +15340,13 @@ namespace exprtk results_context_t& rc) : gen_function_t (arg_list) , results_context_(&rc) - {} + { + assert(valid()); + } inline T value() const exprtk_override { - if ( - (0 != results_context_) && - gen_function_t::populate_value_list() - ) + if (gen_function_t::populate_value_list()) { typedef typename type_store::parameter_list parameter_list_t; @@ -12972,6 +15364,11 @@ namespace exprtk return expression_node::e_return; } + inline bool valid() const exprtk_override + { + return results_context_; + } + private: results_context_t* results_context_; @@ -12991,12 +15388,11 @@ namespace exprtk , return_invoked_ (false) { construct_branch_pair(body_, body); + assert(valid()); } inline T value() const exprtk_override { - assert(body_.first); - try { return_invoked_ = false; @@ -13007,6 +15403,7 @@ namespace exprtk catch(const return_exception&) { return_invoked_ = true; + return std::numeric_limits::quiet_NaN(); } } @@ -13016,6 +15413,11 @@ namespace exprtk return expression_node::e_retenv; } + inline bool valid() const exprtk_override + { + return results_context_ && body_.first; + } + inline bool* retinvk_ptr() { return &return_invoked_; @@ -13400,7 +15802,7 @@ namespace exprtk } template - struct vararg_add_op : public opr_base + struct vararg_add_op exprtk_final : public opr_base { typedef typename opr_base::Type Type; @@ -13423,7 +15825,7 @@ namespace exprtk for (std::size_t i = 0; i < arg_list.size(); ++i) { - result += value(arg_list[i]); + result += value(arg_list[i]); } return result; @@ -13467,7 +15869,7 @@ namespace exprtk }; template - struct vararg_mul_op : public opr_base + struct vararg_mul_op exprtk_final : public opr_base { typedef typename opr_base::Type Type; @@ -13534,7 +15936,7 @@ namespace exprtk }; template - struct vararg_avg_op : public opr_base + struct vararg_avg_op exprtk_final : public opr_base { typedef typename opr_base::Type Type; @@ -13590,7 +15992,7 @@ namespace exprtk }; template - struct vararg_min_op : public opr_base + struct vararg_min_op exprtk_final : public opr_base { typedef typename opr_base::Type Type; @@ -13661,7 +16063,7 @@ namespace exprtk }; template - struct vararg_max_op : public opr_base + struct vararg_max_op exprtk_final : public opr_base { typedef typename opr_base::Type Type; @@ -13732,7 +16134,7 @@ namespace exprtk }; template - struct vararg_mand_op : public opr_base + struct vararg_mand_op exprtk_final : public opr_base { typedef typename opr_base::Type Type; @@ -13812,7 +16214,7 @@ namespace exprtk }; template - struct vararg_mor_op : public opr_base + struct vararg_mor_op exprtk_final : public opr_base { typedef typename opr_base::Type Type; @@ -13892,7 +16294,7 @@ namespace exprtk }; template - struct vararg_multi_op : public opr_base + struct vararg_multi_op exprtk_final : public opr_base { typedef typename opr_base::Type Type; @@ -13913,14 +16315,13 @@ namespace exprtk case 7 : return process_7(arg_list); case 8 : return process_8(arg_list); default : - { - for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) - { - value(arg_list[i]); - } - - return value(arg_list.back()); - } + { + for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) + { + value(arg_list[i]); + } + return value(arg_list.back()); + } } } @@ -14009,7 +16410,7 @@ namespace exprtk static inline T process(const ivector_ptr v) { const T* vec = v->vec()->vds().data(); - const std::size_t vec_size = v->vec()->vds().size(); + const std::size_t vec_size = v->size(); loop_unroll::details lud(vec_size); @@ -14018,24 +16419,24 @@ namespace exprtk T result = T(0); int i = 0; - exprtk_disable_fallthrough_begin switch (vec_size) { - #define case_stmt(N) \ - case N : result += vec[i++]; \ + #define case_stmt(N,fall_through) \ + case N : result += vec[i++]; \ + fall_through \ #ifndef exprtk_disable_superscalar_unroll - case_stmt(16) case_stmt(15) - case_stmt(14) case_stmt(13) - case_stmt(12) case_stmt(11) - case_stmt(10) case_stmt( 9) - case_stmt( 8) case_stmt( 7) - case_stmt( 6) case_stmt( 5) + case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) + case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) + case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) + case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) + case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) + case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) + #endif - case_stmt( 4) case_stmt( 3) - case_stmt( 2) case_stmt( 1) + case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) + case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) } - exprtk_disable_fallthrough_end #undef case_stmt @@ -14070,24 +16471,23 @@ namespace exprtk int i = 0; - exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : r[0] += vec[i++]; \ + #define case_stmt(N,fall_through) \ + case N : r[0] += vec[i++]; \ + fall_through \ #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) + case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) + case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) + case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) + case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) + case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) + case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) + case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) + case_stmt( 1, (void)0;) } - exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt @@ -14110,7 +16510,7 @@ namespace exprtk static inline T process(const ivector_ptr v) { const T* vec = v->vec()->vds().data(); - const std::size_t vec_size = v->vec()->vds().size(); + const std::size_t vec_size = v->vec()->size(); loop_unroll::details lud(vec_size); @@ -14119,24 +16519,23 @@ namespace exprtk T result = T(1); int i = 0; - exprtk_disable_fallthrough_begin switch (vec_size) { - #define case_stmt(N) \ - case N : result *= vec[i++]; \ + #define case_stmt(N,fall_through) \ + case N : result *= vec[i++]; \ + fall_through \ #ifndef exprtk_disable_superscalar_unroll - case_stmt(16) case_stmt(15) - case_stmt(14) case_stmt(13) - case_stmt(12) case_stmt(11) - case_stmt(10) case_stmt( 9) - case_stmt( 8) case_stmt( 7) - case_stmt( 6) case_stmt( 5) + case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) + case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) + case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) + case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) + case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) + case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) #endif - case_stmt( 4) case_stmt( 3) - case_stmt( 2) case_stmt( 1) + case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) + case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) } - exprtk_disable_fallthrough_end #undef case_stmt @@ -14171,33 +16570,32 @@ namespace exprtk int i = 0; - exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : r[0] *= vec[i++]; \ + #define case_stmt(N,fall_through) \ + case N : r[0] *= vec[i++]; \ + fall_through \ #ifndef exprtk_disable_superscalar_unroll - case_stmt(15) case_stmt(14) - case_stmt(13) case_stmt(12) - case_stmt(11) case_stmt(10) - case_stmt( 9) case_stmt( 8) - case_stmt( 7) case_stmt( 6) - case_stmt( 5) case_stmt( 4) + case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) + case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) + case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) + case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) + case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) + case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) #endif - case_stmt( 3) case_stmt( 2) - case_stmt( 1) + case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) + case_stmt( 1, (void)0;) } - exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) #ifndef exprtk_disable_superscalar_unroll - + (r[ 4] * r[ 5] * r[ 6] * r[ 7]) - + (r[ 8] * r[ 9] * r[10] * r[11]) - + (r[12] * r[13] * r[14] * r[15]) + * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) + * (r[ 8] * r[ 9] * r[10] * r[11]) + * (r[12] * r[13] * r[14] * r[15]) #endif ; } @@ -14210,7 +16608,7 @@ namespace exprtk static inline T process(const ivector_ptr v) { - const T vec_size = T(v->vec()->vds().size()); + const T vec_size = T(v->vec()->size()); return vec_add_op::process(v) / vec_size; } }; @@ -14223,7 +16621,7 @@ namespace exprtk static inline T process(const ivector_ptr v) { const T* vec = v->vec()->vds().data(); - const std::size_t vec_size = v->vec()->vds().size(); + const std::size_t vec_size = v->vec()->size(); T result = vec[0]; @@ -14247,7 +16645,7 @@ namespace exprtk static inline T process(const ivector_ptr v) { const T* vec = v->vec()->vds().data(); - const std::size_t vec_size = v->vec()->vds().size(); + const std::size_t vec_size = v->vec()->size(); T result = vec[0]; @@ -14268,7 +16666,8 @@ namespace exprtk { public: - virtual ~vov_base_node() {} + virtual ~vov_base_node() + {} inline virtual operator_type operation() const { @@ -14285,7 +16684,8 @@ namespace exprtk { public: - virtual ~cov_base_node() {} + virtual ~cov_base_node() + {} inline virtual operator_type operation() const { @@ -14302,7 +16702,8 @@ namespace exprtk { public: - virtual ~voc_base_node() {} + virtual ~voc_base_node() + {} inline virtual operator_type operation() const { @@ -14319,7 +16720,8 @@ namespace exprtk { public: - virtual ~vob_base_node() {} + virtual ~vob_base_node() + {} virtual const T& v() const = 0; }; @@ -14329,7 +16731,8 @@ namespace exprtk { public: - virtual ~bov_base_node() {} + virtual ~bov_base_node() + {} virtual const T& v() const = 0; }; @@ -14339,7 +16742,8 @@ namespace exprtk { public: - virtual ~cob_base_node() {} + virtual ~cob_base_node() + {} inline virtual operator_type operation() const { @@ -14358,7 +16762,8 @@ namespace exprtk { public: - virtual ~boc_base_node() {} + virtual ~boc_base_node() + {} inline virtual operator_type operation() const { @@ -14377,7 +16782,8 @@ namespace exprtk { public: - virtual ~uv_base_node() {} + virtual ~uv_base_node() + {} inline virtual operator_type operation() const { @@ -14392,7 +16798,8 @@ namespace exprtk { public: - virtual ~sos_base_node() {} + virtual ~sos_base_node() + {} inline virtual operator_type operation() const { @@ -14405,7 +16812,8 @@ namespace exprtk { public: - virtual ~sosos_base_node() {} + virtual ~sosos_base_node() + {} inline virtual operator_type operation() const { @@ -14418,7 +16826,8 @@ namespace exprtk { public: - virtual ~T0oT1oT2_base_node() {} + virtual ~T0oT1oT2_base_node() + {} virtual std::string type_id() const = 0; }; @@ -14428,7 +16837,8 @@ namespace exprtk { public: - virtual ~T0oT1oT2oT3_base_node() {} + virtual ~T0oT1oT2oT3_base_node() + {} virtual std::string type_id() const = 0; }; @@ -14564,6 +16974,11 @@ namespace exprtk return Operation::type(); } + inline bool valid() const exprtk_override + { + return branch_.first && branch_.first->valid(); + } + inline operator_type operation() { return Operation::operation(); @@ -15186,7 +17601,8 @@ namespace exprtk { public: - virtual ~sf3ext_type_node() {} + virtual ~sf3ext_type_node() + {} virtual T0 t0() const = 0; @@ -15644,16 +18060,16 @@ namespace exprtk typedef std::pair branch_t; typedef Operation operation_t; - // variable op constant node + // variable op binary node explicit vob_node(const T& var, const expression_ptr branch) : v_(var) { construct_branch_pair(branch_, branch); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_.first); return Operation::process(v_,branch_.first->value()); } @@ -15662,6 +18078,11 @@ namespace exprtk return v_; } + inline bool valid() const exprtk_override + { + return branch_.first && branch_.first->valid(); + } + inline expression_node* branch(const std::size_t&) const exprtk_override { return branch_.first; @@ -15669,7 +18090,7 @@ namespace exprtk void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override @@ -15695,16 +18116,16 @@ namespace exprtk typedef std::pair branch_t; typedef Operation operation_t; - // variable op constant node + // binary node op variable node explicit bov_node(const expression_ptr branch, const T& var) : v_(var) { construct_branch_pair(branch_, branch); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_.first); return Operation::process(branch_.first->value(),v_); } @@ -15713,6 +18134,11 @@ namespace exprtk return v_; } + inline bool valid() const exprtk_override + { + return branch_.first && branch_.first->valid(); + } + inline expression_node* branch(const std::size_t&) const exprtk_override { return branch_.first; @@ -15720,7 +18146,7 @@ namespace exprtk void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override @@ -15746,16 +18172,16 @@ namespace exprtk typedef std::pair branch_t; typedef Operation operation_t; - // variable op constant node + // constant op variable node explicit cob_node(const T const_var, const expression_ptr branch) : c_(const_var) { construct_branch_pair(branch_, branch); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_.first); return Operation::process(c_,branch_.first->value()); } @@ -15774,6 +18200,11 @@ namespace exprtk (*const_cast(&c_)) = new_c; } + inline bool valid() const exprtk_override + { + return branch_.first && branch_.first->valid(); + } + inline expression_node* branch(const std::size_t&) const exprtk_override { return branch_.first; @@ -15787,7 +18218,7 @@ namespace exprtk void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override @@ -15813,16 +18244,16 @@ namespace exprtk typedef std::pair branch_t; typedef Operation operation_t; - // variable op constant node + // binary node op constant node explicit boc_node(const expression_ptr branch, const T const_var) : c_(const_var) { construct_branch_pair(branch_, branch); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_.first); return Operation::process(branch_.first->value(),c_); } @@ -15841,6 +18272,11 @@ namespace exprtk (*const_cast(&c_)) = new_c; } + inline bool valid() const exprtk_override + { + return branch_.first && branch_.first->valid(); + } + inline expression_node* branch(const std::size_t&) const exprtk_override { return branch_.first; @@ -15854,7 +18290,7 @@ namespace exprtk void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override @@ -16013,7 +18449,13 @@ namespace exprtk std::size_t r1 = 0; if (rp1_(r0, r1, s1_.size())) - return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1)); + { + return Operation::process + ( + s0_, + s1_.substr(r0, (r1 - r0) + 1) + ); + } else return T(0); } @@ -16085,10 +18527,11 @@ namespace exprtk rp1_(r0_1, r1_1, s1_.size()) ) { - return Operation::process( - s0_.substr(r0_0, (r1_0 - r0_0) + 1), - s1_.substr(r0_1, (r1_1 - r0_1) + 1) - ); + return Operation::process + ( + s0_.substr(r0_0, (r1_0 - r0_0) + 1), + s1_.substr(r0_1, (r1_1 - r0_1) + 1) + ); } else return T(0); @@ -16149,6 +18592,7 @@ namespace exprtk , str1_base_ptr_ (0) , str0_range_ptr_(0) , str1_range_ptr_(0) + , initialised_ (false) { if (is_generally_string_node(branch(0))) { @@ -16179,39 +18623,40 @@ namespace exprtk str1_range_ptr_ = &(range->range_ref()); } + + initialised_ = + str0_base_ptr_ && + str1_base_ptr_ && + str0_range_ptr_ && + str1_range_ptr_; + + assert(valid()); } inline T value() const exprtk_override { - if ( - str0_base_ptr_ && - str1_base_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ - ) - { - branch(0)->value(); - branch(1)->value(); + branch(0)->value(); + branch(1)->value(); - std::size_t str0_r0 = 0; - std::size_t str0_r1 = 0; + std::size_t str0_r0 = 0; + std::size_t str0_r1 = 0; - std::size_t str1_r0 = 0; - std::size_t str1_r1 = 0; + std::size_t str1_r0 = 0; + std::size_t str1_r1 = 0; - const range_t& range0 = (*str0_range_ptr_); - const range_t& range1 = (*str1_range_ptr_); + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); - if ( - range0(str0_r0, str0_r1, str0_base_ptr_->size()) && - range1(str1_r0, str1_r1, str1_base_ptr_->size()) - ) - { - return Operation::process( - str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1), - str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1) - ); - } + if ( + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) + ) + { + return Operation::process + ( + str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), + str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) + ); } return std::numeric_limits::quiet_NaN(); @@ -16222,6 +18667,11 @@ namespace exprtk return Operation::type(); } + inline bool valid() const exprtk_override + { + return initialised_; + } + private: str_sogens_node(const str_sogens_node&) exprtk_delete; @@ -16231,6 +18681,7 @@ namespace exprtk str_base_ptr str1_base_ptr_; range_ptr str0_range_ptr_; range_ptr str1_range_ptr_; + bool initialised_; }; template @@ -16242,7 +18693,7 @@ namespace exprtk typedef Operation operation_t; typedef sosos_node node_type; - // variable op variable node + // string op string op string node explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) : s0_(p0) , s1_(p1) @@ -16334,11 +18785,11 @@ namespace exprtk explicit bipow_node(expression_ptr branch) { construct_branch_pair(branch_, branch); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_.first); return PowOp::result(branch_.first->value()); } @@ -16347,6 +18798,11 @@ namespace exprtk return expression_node::e_ipow; } + inline bool valid() const exprtk_override + { + return branch_.first && branch_.first->valid(); + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(branch_, node_delete_list); @@ -16396,7 +18852,7 @@ namespace exprtk }; template - class bipowninv_node exprtk_final : public expression_node + class bipowinv_node exprtk_final : public expression_node { public: @@ -16404,14 +18860,14 @@ namespace exprtk typedef std::pair branch_t; typedef PowOp operation_t; - explicit bipowninv_node(expression_ptr branch) + explicit bipowinv_node(expression_ptr branch) { construct_branch_pair(branch_, branch); + assert(valid()); } inline T value() const exprtk_override { - assert(branch_.first); return (T(1) / PowOp::result(branch_.first->value())); } @@ -16420,9 +18876,14 @@ namespace exprtk return expression_node::e_ipowinv; } + inline bool valid() const exprtk_override + { + return branch_.first && branch_.first->valid(); + } + void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { - expression_node::ndb_t::template collect(branch_, node_delete_list); + expression_node::ndb_t::collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override @@ -16432,8 +18893,8 @@ namespace exprtk private: - bipowninv_node(const bipowninv_node&) exprtk_delete; - bipowninv_node& operator=(const bipowninv_node&) exprtk_delete; + bipowinv_node(const bipowinv_node&) exprtk_delete; + bipowinv_node& operator=(const bipowinv_node&) exprtk_delete; branch_t branch_; }; @@ -16577,6 +19038,46 @@ namespace exprtk return false; } + template + inline bool is_loop_node(const expression_node* node) + { + if (node) + { + switch (node->type()) + { + case expression_node::e_for : + case expression_node::e_repeat : + case expression_node::e_while : return true; + default : return false; + } + } + + return false; + } + + template + inline bool is_block_node(const expression_node* node) + { + if (node) + { + if (is_loop_node(node)) + { + return true; + } + + switch (node->type()) + { + case expression_node::e_conditional : + case expression_node::e_mswitch : + case expression_node::e_switch : + case expression_node::e_vararg : return true; + default : return false; + } + } + + return false; + } + class node_allocator { public: @@ -17117,7 +19618,8 @@ namespace exprtk : param_count(pc) {} - virtual ~ifunction() {} + virtual ~ifunction() + {} #define empty_method_body(N) \ { \ @@ -17208,7 +19710,8 @@ namespace exprtk { public: - virtual ~ivararg_function() {} + virtual ~ivararg_function() + {} inline virtual T operator() (const std::vector&) { @@ -17233,12 +19736,13 @@ namespace exprtk typedef type_store generic_type; typedef typename generic_type::parameter_list parameter_list_t; - igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) + explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) : parameter_sequence(param_seq) , rtrn_type(rtr_type) {} - virtual ~igeneric_function() {} + virtual ~igeneric_function() + {} #define igeneric_function_empty_body(N) \ { \ @@ -17262,6 +19766,8 @@ namespace exprtk inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) igeneric_function_empty_body(4) + #undef igeneric_function_empty_body + std::string parameter_sequence; return_type rtrn_type; }; @@ -17337,52 +19843,52 @@ namespace exprtk protected: - struct freefunc00 : public exprtk::ifunction + struct freefunc00 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc00(ff00_functor ff) : exprtk::ifunction(0), f(ff) {} - inline T operator() () + inline T operator() () exprtk_override { return f(); } ff00_functor f; }; - struct freefunc01 : public exprtk::ifunction + struct freefunc01 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc01(ff01_functor ff) : exprtk::ifunction(1), f(ff) {} - inline T operator() (const T& v0) + inline T operator() (const T& v0) exprtk_override { return f(v0); } ff01_functor f; }; - struct freefunc02 : public exprtk::ifunction + struct freefunc02 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc02(ff02_functor ff) : exprtk::ifunction(2), f(ff) {} - inline T operator() (const T& v0, const T& v1) + inline T operator() (const T& v0, const T& v1) exprtk_override { return f(v0, v1); } ff02_functor f; }; - struct freefunc03 : public exprtk::ifunction + struct freefunc03 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc03(ff03_functor ff) : exprtk::ifunction(3), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2) + inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override { return f(v0, v1, v2); } ff03_functor f; }; - struct freefunc04 : public exprtk::ifunction + struct freefunc04 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc04(ff04_functor ff) : exprtk::ifunction(4), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override { return f(v0, v1, v2, v3); } ff04_functor f; }; @@ -17392,120 +19898,120 @@ namespace exprtk using exprtk::ifunction::operator(); explicit freefunc05(ff05_functor ff) : exprtk::ifunction(5), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override { return f(v0, v1, v2, v3, v4); } ff05_functor f; }; - struct freefunc06 : public exprtk::ifunction + struct freefunc06 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc06(ff06_functor ff) : exprtk::ifunction(6), f(ff) {} - inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) + inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override { return f(v0, v1, v2, v3, v4, v5); } ff06_functor f; }; - struct freefunc07 : public exprtk::ifunction + struct freefunc07 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc07(ff07_functor ff) : exprtk::ifunction(7), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6) + const T& v5, const T& v6) exprtk_override { return f(v0, v1, v2, v3, v4, v5, v6); } ff07_functor f; }; - struct freefunc08 : public exprtk::ifunction + struct freefunc08 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc08(ff08_functor ff) : exprtk::ifunction(8), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6, const T& v7) + const T& v5, const T& v6, const T& v7) exprtk_override { return f(v0, v1, v2, v3, v4, v5, v6, v7); } ff08_functor f; }; - struct freefunc09 : public exprtk::ifunction + struct freefunc09 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc09(ff09_functor ff) : exprtk::ifunction(9), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6, const T& v7, const T& v8) + const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } ff09_functor f; }; - struct freefunc10 : public exprtk::ifunction + struct freefunc10 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc10(ff10_functor ff) : exprtk::ifunction(10), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) + const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } ff10_functor f; }; - struct freefunc11 : public exprtk::ifunction + struct freefunc11 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc11(ff11_functor ff) : exprtk::ifunction(11), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, - const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) + const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } ff11_functor f; }; - struct freefunc12 : public exprtk::ifunction + struct freefunc12 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc12(ff12_functor ff) : exprtk::ifunction(12), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, - const T& v10, const T& v11) + const T& v10, const T& v11) exprtk_override { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } ff12_functor f; }; - struct freefunc13 : public exprtk::ifunction + struct freefunc13 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc13(ff13_functor ff) : exprtk::ifunction(13), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, - const T& v10, const T& v11, const T& v12) + const T& v10, const T& v11, const T& v12) exprtk_override { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } ff13_functor f; }; - struct freefunc14 : public exprtk::ifunction + struct freefunc14 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc14(ff14_functor ff) : exprtk::ifunction(14), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, - const T& v10, const T& v11, const T& v12, const T& v13) + const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } ff14_functor f; }; - struct freefunc15 : public exprtk::ifunction + struct freefunc15 exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); explicit freefunc15(ff15_functor ff) : exprtk::ifunction(15), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, - const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) + const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } ff15_functor f; }; @@ -17765,7 +20271,7 @@ namespace exprtk { static inline bool test(const variable_node_t* p, const void* ptr) { - exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr)); + exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast(&(p->ref())), ptr)); return (&(p->ref()) == ptr); } }; @@ -18029,7 +20535,7 @@ namespace exprtk public: - symbol_table(const symtab_mutability_type mutability = e_mutable) + explicit symbol_table(const symtab_mutability_type mutability = e_mutable) : control_block_(control_block::create()) { control_block_->set_mutability(mutability); @@ -18508,6 +21014,34 @@ namespace exprtk return false; } + #define exprtk_define_reserved_function(NN) \ + inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ + { \ + if (!valid()) \ + { return false; } \ + if (!valid_symbol(function_name,false)) \ + { return false; } \ + if (symbol_exists(function_name,false)) \ + { return false; } \ + \ + exprtk::ifunction* ifunc = new freefunc##NN(function); \ + \ + local_data().free_function_list_.push_back(ifunc); \ + \ + return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ + } \ + + exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) + exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) + exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) + exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) + exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) + exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) + exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) + exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) + + #undef exprtk_define_reserved_function + template inline bool add_vector(const std::string& vector_name, T (&v)[N]) { @@ -18682,12 +21216,48 @@ namespace exprtk template class Sequence> - inline std::size_t get_vector_list(Sequence& vlist) const + inline std::size_t get_vector_list(Sequence& vec_list) const { if (!valid()) return 0; else - return local_data().vector_store.get_list(vlist); + return local_data().vector_store.get_list(vec_list); + } + + template class Sequence> + inline std::size_t get_function_list(Sequence& function_list) const + { + if (!valid()) + return 0; + + std::vector function_names; + std::size_t count = 0; + + count += local_data().function_store .get_list(function_names); + count += local_data().vararg_function_store .get_list(function_names); + count += local_data().generic_function_store .get_list(function_names); + count += local_data().string_function_store .get_list(function_names); + count += local_data().overload_function_store.get_list(function_names); + + std::set function_set; + + for (std::size_t i = 0; i < function_names.size(); ++i) + { + function_set.insert(function_names[i]); + } + + std::copy(function_set.begin(), function_set.end(), + std::back_inserter(function_list)); + + return count; + } + + inline std::vector get_function_list() const + { + std::vector result; + get_function_list(result); + return result; } inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const @@ -18878,6 +21448,38 @@ namespace exprtk } } + inline void load_variables_from(const symbol_table& st) + { + std::vector name_list; + + st.local_data().variable_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + T& variable = st.get_variable(name_list[i])->ref(); + add_variable(name_list[i], variable); + } + } + } + + inline void load_vectors_from(const symbol_table& st) + { + std::vector name_list; + + st.local_data().vector_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + vector_holder_t& vecholder = *st.get_vector(name_list[i]); + add_vector(name_list[i], vecholder.data(), vecholder.size()); + } + } + } + private: inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const @@ -18973,6 +21575,21 @@ namespace exprtk e_string }; + static std::string to_str(data_type dt) + { + switch(dt) + { + case e_unknown : return "e_unknown "; + case e_expr : return "e_expr" ; + case e_vecholder : return "e_vecholder"; + case e_data : return "e_data" ; + case e_vecdata : return "e_vecdata" ; + case e_string : return "e_string" ; + } + + return ""; + } + struct data_pack { data_pack() @@ -19178,17 +21795,18 @@ namespace exprtk return details::is_true(value()); } - inline void register_symbol_table(symbol_table& st) + inline bool register_symbol_table(symbol_table& st) { for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) { - if (&st == &symbol_table_list_[i]) + if (st == symbol_table_list_[i]) { - return; + return false; } } symbol_table_list_.push_back(st); + return true; } inline const symbol_table& get_symbol_table(const std::size_t& index = 0) const @@ -19201,6 +21819,11 @@ namespace exprtk return symbol_table_list_[index]; } + std::size_t num_symbol_tables() const + { + return symbol_table_list_.size(); + } + typedef results_context results_context_t; inline const results_context_t& results() const @@ -19330,6 +21953,8 @@ namespace exprtk friend class parser; friend class expression_helper; friend class function_compositor; + template + friend bool is_valid(const expression& expr); }; // class expression template @@ -19337,55 +21962,165 @@ namespace exprtk { public: - static inline bool is_constant(const expression& expr) + enum node_types + { + e_literal, + e_variable, + e_string, + e_unary, + e_binary, + e_function, + e_vararg, + e_null, + e_assert, + e_sf3ext, + e_sf4ext + }; + + static inline bool is_literal(const expression& expr) { - return details::is_constant_node(expr.control_block_->expr); + return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); } static inline bool is_variable(const expression& expr) { - return details::is_variable_node(expr.control_block_->expr); + return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); + } + + static inline bool is_string(const expression& expr) + { + return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); } static inline bool is_unary(const expression& expr) { - return details::is_unary_node(expr.control_block_->expr); + return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); } static inline bool is_binary(const expression& expr) { - return details::is_binary_node(expr.control_block_->expr); + return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); } static inline bool is_function(const expression& expr) { - return details::is_function(expr.control_block_->expr); + return expr.control_block_ && details::is_function(expr.control_block_->expr); + } + + static inline bool is_vararg(const expression& expr) + { + return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); } static inline bool is_null(const expression& expr) { - return details::is_null_node(expr.control_block_->expr); + return expr.control_block_ && details::is_null_node(expr.control_block_->expr); + } + + static inline bool is_assert(const expression& expr) + { + return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); + } + + static inline bool is_sf3ext(const expression& expr) + { + return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); + } + + static inline bool is_sf4ext(const expression& expr) + { + return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); + } + + static inline bool is_type(const expression& expr, const node_types node_type) + { + if (0 == expr.control_block_) + { + return false; + } + + switch (node_type) + { + case e_literal : return is_literal_node(expr); + case e_variable : return is_variable (expr); + case e_string : return is_string (expr); + case e_unary : return is_unary (expr); + case e_binary : return is_binary (expr); + case e_function : return is_function (expr); + case e_null : return is_null (expr); + case e_assert : return is_assert (expr); + case e_sf3ext : return is_sf3ext (expr); + case e_sf4ext : return is_sf4ext (expr); + }; + + return false; + } + + static inline bool match_type_sequence(const expression& expr, const std::vector& type_seq) + { + if ((0 == expr.control_block_) || !is_vararg(expr)) + { + return false; + } + + typedef details::vararg_node > mo_vararg_t; + + mo_vararg_t* vnode = dynamic_cast(expr.control_block_->expr); + + if ( + (0 == vnode) || + type_seq.empty() || + (vnode->size() < type_seq.size()) + ) + { + return false; + } + + for (std::size_t i = 0; i < type_seq.size(); ++i) + { + assert((*vnode)[i]); + + switch(type_seq[i]) + { + case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; + case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; + case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; + case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; + case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; + case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; + case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; + case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; + case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; + case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; + case e_vararg : break; + } + + return false; + } + + return true; } }; template inline bool is_valid(const expression& expr) { - return !expression_helper::is_null(expr); + return expr.control_block_ && !expression_helper::is_null(expr); } namespace parser_error { enum error_mode { - e_unknown = 0, - e_syntax = 1, - e_token = 2, - e_numeric = 4, - e_symtab = 5, - e_lexer = 6, - e_helper = 7, - e_parser = 8 + e_unknown = 0, + e_syntax = 1, + e_token = 2, + e_numeric = 4, + e_symtab = 5, + e_lexer = 6, + e_synthesis = 7, + e_helper = 8, + e_parser = 9 }; struct type @@ -19414,7 +22149,7 @@ namespace exprtk t.token.type = lexer::token::e_error; t.diagnostic = diagnostic; t.src_location = src_location; - exprtk_debug(("%s\n",diagnostic .c_str())); + exprtk_debug(("%s\n", diagnostic .c_str())); return t; } @@ -19428,7 +22163,7 @@ namespace exprtk t.token = tk; t.diagnostic = diagnostic; t.src_location = src_location; - exprtk_debug(("%s\n",diagnostic .c_str())); + exprtk_debug(("%s\n", diagnostic .c_str())); return t; } @@ -19520,70 +22255,79 @@ namespace exprtk e_level10, e_level11, e_level12, e_level13, e_level14 }; - typedef const T& cref_t; - typedef const T const_t; - typedef ifunction F; - typedef ivararg_function VAF; - typedef igeneric_function GF; - typedef ifunction ifunction_t; - typedef ivararg_function ivararg_function_t; - typedef igeneric_function igeneric_function_t; - typedef details::expression_node expression_node_t; - typedef details::literal_node literal_node_t; - typedef details::unary_node unary_node_t; - typedef details::binary_node binary_node_t; - typedef details::trinary_node trinary_node_t; - typedef details::quaternary_node quaternary_node_t; - typedef details::conditional_node conditional_node_t; - typedef details::cons_conditional_node cons_conditional_node_t; - typedef details::while_loop_node while_loop_node_t; - typedef details::repeat_until_loop_node repeat_until_loop_node_t; - typedef details::for_loop_node for_loop_node_t; - typedef details::while_loop_rtc_node while_loop_rtc_node_t; - typedef details::repeat_until_loop_rtc_node repeat_until_loop_rtc_node_t; - typedef details::for_loop_rtc_node for_loop_rtc_node_t; + typedef const T& cref_t; + typedef const T const_t; + typedef ifunction F; + typedef ivararg_function VAF; + typedef igeneric_function GF; + typedef ifunction ifunction_t; + typedef ivararg_function ivararg_function_t; + typedef igeneric_function igeneric_function_t; + typedef details::expression_node expression_node_t; + typedef details::literal_node literal_node_t; + typedef details::unary_node unary_node_t; + typedef details::binary_node binary_node_t; + typedef details::trinary_node trinary_node_t; + typedef details::quaternary_node quaternary_node_t; + typedef details::conditional_node conditional_node_t; + typedef details::cons_conditional_node cons_conditional_node_t; + typedef details::while_loop_node while_loop_node_t; + typedef details::repeat_until_loop_node repeat_until_loop_node_t; + typedef details::for_loop_node for_loop_node_t; + typedef details::while_loop_rtc_node while_loop_rtc_node_t; + typedef details::repeat_until_loop_rtc_node repeat_until_loop_rtc_node_t; + typedef details::for_loop_rtc_node for_loop_rtc_node_t; #ifndef exprtk_disable_break_continue - typedef details::while_loop_bc_node while_loop_bc_node_t; - typedef details::repeat_until_loop_bc_node repeat_until_loop_bc_node_t; - typedef details::for_loop_bc_node for_loop_bc_node_t; - typedef details::while_loop_bc_rtc_node while_loop_bc_rtc_node_t; - typedef details::repeat_until_loop_bc_rtc_node repeat_until_loop_bc_rtc_node_t; - typedef details::for_loop_bc_rtc_node for_loop_bc_rtc_node_t; + typedef details::while_loop_bc_node while_loop_bc_node_t; + typedef details::repeat_until_loop_bc_node repeat_until_loop_bc_node_t; + typedef details::for_loop_bc_node for_loop_bc_node_t; + typedef details::while_loop_bc_rtc_node while_loop_bc_rtc_node_t; + typedef details::repeat_until_loop_bc_rtc_node repeat_until_loop_bc_rtc_node_t; + typedef details::for_loop_bc_rtc_node for_loop_bc_rtc_node_t; #endif - typedef details::switch_node switch_node_t; - typedef details::variable_node variable_node_t; - typedef details::vector_elem_node vector_elem_node_t; - typedef details::rebasevector_elem_node rebasevector_elem_node_t; - typedef details::rebasevector_celem_node rebasevector_celem_node_t; - typedef details::vector_node vector_node_t; - typedef details::range_pack range_t; + typedef details::switch_node switch_node_t; + typedef details::variable_node variable_node_t; + typedef details::vector_elem_node vector_elem_node_t; + typedef details::vector_celem_node vector_celem_node_t; + typedef details::vector_elem_rtc_node vector_elem_rtc_node_t; + typedef details::vector_celem_rtc_node vector_celem_rtc_node_t; + typedef details::rebasevector_elem_node rebasevector_elem_node_t; + typedef details::rebasevector_celem_node rebasevector_celem_node_t; + typedef details::rebasevector_elem_rtc_node rebasevector_elem_rtc_node_t; + typedef details::rebasevector_celem_rtc_node rebasevector_celem_rtc_node_t; + typedef details::vector_node vector_node_t; + typedef details::vector_size_node vector_size_node_t; + typedef details::range_pack range_t; #ifndef exprtk_disable_string_capabilities - typedef details::stringvar_node stringvar_node_t; - typedef details::string_literal_node string_literal_node_t; - typedef details::string_range_node string_range_node_t; - typedef details::const_string_range_node const_string_range_node_t; - typedef details::generic_string_range_node generic_string_range_node_t; - typedef details::string_concat_node string_concat_node_t; - typedef details::assignment_string_node assignment_string_node_t; - typedef details::assignment_string_range_node assignment_string_range_node_t; - typedef details::conditional_string_node conditional_string_node_t; - typedef details::cons_conditional_str_node cons_conditional_str_node_t; + typedef details::stringvar_node stringvar_node_t; + typedef details::string_literal_node string_literal_node_t; + typedef details::string_range_node string_range_node_t; + typedef details::const_string_range_node const_string_range_node_t; + typedef details::generic_string_range_node generic_string_range_node_t; + typedef details::string_concat_node string_concat_node_t; + typedef details::assignment_string_node assignment_string_node_t; + typedef details::assignment_string_range_node assignment_string_range_node_t; + typedef details::conditional_string_node conditional_string_node_t; + typedef details::cons_conditional_str_node cons_conditional_str_node_t; #endif - typedef details::assignment_node assignment_node_t; - typedef details::assignment_vec_elem_node assignment_vec_elem_node_t; - typedef details::assignment_rebasevec_elem_node assignment_rebasevec_elem_node_t; - typedef details::assignment_rebasevec_celem_node assignment_rebasevec_celem_node_t; - typedef details::assignment_vec_node assignment_vec_node_t; - typedef details::assignment_vecvec_node assignment_vecvec_node_t; - typedef details::conditional_vector_node conditional_vector_node_t; - typedef details::scand_node scand_node_t; - typedef details::scor_node scor_node_t; - typedef lexer::token token_t; - typedef expression_node_t* expression_node_ptr; - typedef expression expression_t; - typedef symbol_table symbol_table_t; - typedef typename expression::symtab_list_t symbol_table_list_t; - typedef details::vector_holder* vector_holder_ptr; + typedef details::assignment_node assignment_node_t; + typedef details::assignment_vec_elem_node assignment_vec_elem_node_t; + typedef details::assignment_vec_elem_rtc_node assignment_vec_elem_rtc_node_t; + typedef details::assignment_rebasevec_elem_node assignment_rebasevec_elem_node_t; + typedef details::assignment_rebasevec_elem_rtc_node assignment_rebasevec_elem_rtc_node_t; + typedef details::assignment_rebasevec_celem_node assignment_rebasevec_celem_node_t; + typedef details::assignment_vec_node assignment_vec_node_t; + typedef details::assignment_vecvec_node assignment_vecvec_node_t; + typedef details::conditional_vector_node conditional_vector_node_t; + typedef details::scand_node scand_node_t; + typedef details::scor_node scor_node_t; + typedef lexer::token token_t; + typedef expression_node_t* expression_node_ptr; + typedef expression expression_t; + typedef symbol_table symbol_table_t; + typedef typename expression::symtab_list_t symbol_table_list_t; + typedef details::vector_holder vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; typedef typename details::functor_t functor_t; typedef typename functor_t::qfunc_t quaternary_functor_t; @@ -19636,6 +22380,7 @@ namespace exprtk enum element_type { e_none , + e_literal , e_variable, e_vector , e_vecelem , @@ -19643,6 +22388,7 @@ namespace exprtk }; typedef details::vector_holder vector_holder_t; + typedef literal_node_t* literal_node_ptr; typedef variable_node_t* variable_node_ptr; typedef vector_holder_t* vector_holder_ptr; typedef expression_node_t* expression_node_ptr; @@ -19657,8 +22403,8 @@ namespace exprtk , depth(std::numeric_limits::max()) , ref_count(0) , ip_index (0) - , type (e_none) - , active(false) + , type (e_none) + , active (false) , data (0) , var_node (0) , vec_node (0) @@ -19842,6 +22588,10 @@ namespace exprtk switch (se.type) { + case scope_element::e_literal : delete reinterpret_cast(se.data); + delete se.var_node; + break; + case scope_element::e_variable : delete reinterpret_cast(se.data); delete se.var_node; break; @@ -19906,6 +22656,25 @@ namespace exprtk return expression_node_ptr(0); } + inline std::string get_vector_name(const T* data) + { + for (std::size_t i = 0; i < element_.size(); ++i) + { + scope_element& se = element_[i]; + + if ( + se.active && + se.vec_node && + (se.vec_node->data() == data) + ) + { + return se.name; + } + } + + return "neo-vector"; + } + private: scope_element_manager(const scope_element_manager&) exprtk_delete; @@ -20092,16 +22861,17 @@ namespace exprtk if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) { limit_exceeded_ = true; - parser_.set_error( - make_error(parser_error::e_parser, - "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + - " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), - exprtk_error_location)); + parser_.set_error(make_error( + parser_error::e_parser, + "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + + " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), + exprtk_error_location)); } } ~stack_limit_handler() { + assert(parser_.state_.stack_depth > 0); parser_.state_.stack_depth--; } @@ -20211,22 +22981,23 @@ namespace exprtk inline variable_context get_variable_context(const std::string& variable_name) const { variable_context result; - if (!valid_symbol(variable_name)) - return result; - for (std::size_t i = 0; i < symtab_list_.size(); ++i) + if (valid_symbol(variable_name)) { - if (!symtab_list_[i].valid()) + for (std::size_t i = 0; i < symtab_list_.size(); ++i) { - continue; - } + if (!symtab_list_[i].valid()) + { + continue; + } - result.variable = local_data(i) - .variable_store.get(variable_name); - if (result.variable) - { - result.symbol_table = &symtab_list_[i]; - break; + result.variable = local_data(i) + .variable_store.get(variable_name); + if (result.variable) + { + result.symbol_table = &symtab_list_[i]; + break; + } } } @@ -20461,12 +23232,16 @@ namespace exprtk for (std::size_t i = 0; i < symtab_list_.size(); ++i) { if (!symtab_list_[i].valid()) + { continue; - else - result = - local_data(i).vector_store.get(vector_name); + } - if (result) break; + result = local_data(i).vector_store.get(vector_name); + + if (result) + { + break; + } } return result; @@ -20480,9 +23255,14 @@ namespace exprtk for (std::size_t i = 0; i < symtab_list_.size(); ++i) { if (!symtab_list_[i].valid()) + { continue; - else if (local_data(i).variable_store.is_constant(symbol_name)) + } + + if (local_data(i).variable_store.is_constant(symbol_name)) + { return true; + } } return false; @@ -20513,9 +23293,14 @@ namespace exprtk for (std::size_t i = 0; i < symtab_list_.size(); ++i) { if (!symtab_list_[i].valid()) + { continue; - else if (symtab_list_[i].symbol_exists(symbol)) + } + + if (symtab_list_[i].symbol_exists(symbol)) + { return true; + } } return false; @@ -20675,6 +23460,7 @@ namespace exprtk { parsing_return_stmt = false; parsing_break_stmt = false; + parsing_assert_stmt = false; return_stmt_present = false; side_effect_present = false; scope_depth = 0; @@ -20692,12 +23478,13 @@ namespace exprtk { side_effect_present = true; - exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str())); + exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); } } bool parsing_return_stmt; bool parsing_break_stmt; + bool parsing_assert_stmt; bool return_stmt_present; bool side_effect_present; bool type_check_enabled; @@ -20730,7 +23517,8 @@ namespace exprtk : mode(m) {} - virtual ~unknown_symbol_resolver() {} + virtual ~unknown_symbol_resolver() + {} virtual bool process(const std::string& /*unknown_symbol*/, usr_symbol_type& st, @@ -20806,11 +23594,14 @@ namespace exprtk details::case_normalise(symbol_name_list_[i].first); } - std::sort(symbol_name_list_.begin(),symbol_name_list_.end()); + std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); - std::unique_copy(symbol_name_list_.begin(), - symbol_name_list_.end (), - std::back_inserter(symbols_list)); + std::unique_copy + ( + symbol_name_list_.begin(), + symbol_name_list_.end (), + std::back_inserter(symbols_list) + ); return symbols_list.size(); } @@ -20831,9 +23622,12 @@ namespace exprtk std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); - std::unique_copy(assignment_name_list_.begin(), - assignment_name_list_.end (), - std::back_inserter(assignment_list)); + std::unique_copy + ( + assignment_name_list_.begin(), + assignment_name_list_.end (), + std::back_inserter(assignment_list) + ); return assignment_list.size(); } @@ -21020,7 +23814,7 @@ namespace exprtk e_ineq_gte , e_ineq_gt }; - static const std::size_t compile_all_opts = + static const std::size_t default_compile_all_opts = e_replacer + e_joiner + e_numeric_check + @@ -21029,9 +23823,10 @@ namespace exprtk e_commutative_check + e_strength_reduction; - settings_store(const std::size_t compile_options = compile_all_opts) + settings_store(const std::size_t compile_options = default_compile_all_opts) : max_stack_depth_(400) , max_node_depth_(10000) + , max_local_vector_size_(2000000000) { load_compile_options(compile_options); } @@ -21078,12 +23873,24 @@ namespace exprtk return (*this); } + settings_store& enable_commutative_check() + { + enable_commutative_check_ = true; + return (*this); + } + + settings_store& enable_strength_reduction() + { + enable_strength_reduction_ = true; + return (*this); + } + settings_store& disable_all_base_functions() { std::copy(details::base_function_list, details::base_function_list + details::base_function_list_size, std::insert_iterator - (disabled_func_set_, disabled_func_set_.begin())); + (disabled_func_set_, disabled_func_set_.begin())); return (*this); } @@ -21092,7 +23899,7 @@ namespace exprtk std::copy(details::cntrl_struct_list, details::cntrl_struct_list + details::cntrl_struct_list_size, std::insert_iterator - (disabled_ctrl_set_, disabled_ctrl_set_.begin())); + (disabled_ctrl_set_, disabled_ctrl_set_.begin())); return (*this); } @@ -21110,7 +23917,7 @@ namespace exprtk std::copy(details::arithmetic_ops_list, details::arithmetic_ops_list + details::arithmetic_ops_list_size, std::insert_iterator - (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); + (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); return (*this); } @@ -21119,7 +23926,7 @@ namespace exprtk std::copy(details::assignment_ops_list, details::assignment_ops_list + details::assignment_ops_list_size, std::insert_iterator - (disabled_assignment_set_, disabled_assignment_set_.begin())); + (disabled_assignment_set_, disabled_assignment_set_.begin())); return (*this); } @@ -21128,7 +23935,7 @@ namespace exprtk std::copy(details::inequality_ops_list, details::inequality_ops_list + details::inequality_ops_list_size, std::insert_iterator - (disabled_inequality_set_, disabled_inequality_set_.begin())); + (disabled_inequality_set_, disabled_inequality_set_.begin())); return (*this); } @@ -21138,6 +23945,18 @@ namespace exprtk return (*this); } + settings_store& disable_commutative_check() + { + enable_commutative_check_ = false; + return (*this); + } + + settings_store& disable_strength_reduction() + { + enable_strength_reduction_ = false; + return (*this); + } + bool replacer_enabled () const { return enable_replacer_; } bool commutative_check_enabled () const { return enable_commutative_check_; } bool joiner_enabled () const { return enable_joiner_; } @@ -21263,7 +24082,7 @@ namespace exprtk .find(inequality_opr_to_string(inequality)); } - settings_store& disable_base_function(settings_base_funcs bf) + settings_store& disable_base_function(const settings_base_funcs bf) { if ( (e_bf_unknown != bf) && @@ -21276,7 +24095,7 @@ namespace exprtk return (*this); } - settings_store& disable_control_structure(settings_control_structs ctrl_struct) + settings_store& disable_control_structure(const settings_control_structs ctrl_struct) { if ( (e_ctrl_unknown != ctrl_struct) && @@ -21289,7 +24108,7 @@ namespace exprtk return (*this); } - settings_store& disable_logic_operation(settings_logic_opr logic) + settings_store& disable_logic_operation(const settings_logic_opr logic) { if ( (e_logic_unknown != logic) && @@ -21302,7 +24121,7 @@ namespace exprtk return (*this); } - settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic) + settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) { if ( (e_arith_unknown != arithmetic) && @@ -21315,7 +24134,7 @@ namespace exprtk return (*this); } - settings_store& disable_assignment_operation(settings_assignment_opr assignment) + settings_store& disable_assignment_operation(const settings_assignment_opr assignment) { if ( (e_assign_unknown != assignment) && @@ -21328,7 +24147,7 @@ namespace exprtk return (*this); } - settings_store& disable_inequality_operation(settings_inequality_opr inequality) + settings_store& disable_inequality_operation(const settings_inequality_opr inequality) { if ( (e_ineq_unknown != inequality) && @@ -21341,7 +24160,7 @@ namespace exprtk return (*this); } - settings_store& enable_base_function(settings_base_funcs bf) + settings_store& enable_base_function(const settings_base_funcs bf) { if ( (e_bf_unknown != bf) && @@ -21359,7 +24178,7 @@ namespace exprtk return (*this); } - settings_store& enable_control_structure(settings_control_structs ctrl_struct) + settings_store& enable_control_structure(const settings_control_structs ctrl_struct) { if ( (e_ctrl_unknown != ctrl_struct) && @@ -21377,7 +24196,7 @@ namespace exprtk return (*this); } - settings_store& enable_logic_operation(settings_logic_opr logic) + settings_store& enable_logic_operation(const settings_logic_opr logic) { if ( (e_logic_unknown != logic) && @@ -21395,7 +24214,7 @@ namespace exprtk return (*this); } - settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic) + settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) { if ( (e_arith_unknown != arithmetic) && @@ -21413,7 +24232,7 @@ namespace exprtk return (*this); } - settings_store& enable_assignment_operation(settings_assignment_opr assignment) + settings_store& enable_assignment_operation(const settings_assignment_opr assignment) { if ( (e_assign_unknown != assignment) && @@ -21431,7 +24250,7 @@ namespace exprtk return (*this); } - settings_store& enable_inequality_operation(settings_inequality_opr inequality) + settings_store& enable_inequality_operation(const settings_inequality_opr inequality) { if ( (e_ineq_unknown != inequality) && @@ -21459,6 +24278,26 @@ namespace exprtk max_node_depth_ = max_node_depth; } + void set_max_local_vector_size(const std::size_t max_local_vector_size) + { + max_local_vector_size_ = max_local_vector_size; + } + + std::size_t max_stack_depth() const + { + return max_stack_depth_; + } + + std::size_t max_node_depth() const + { + return max_node_depth_; + } + + std::size_t max_local_vector_size() const + { + return max_local_vector_size_; + } + private: void load_compile_options(const std::size_t compile_options) @@ -21501,6 +24340,7 @@ namespace exprtk case details::e_mul : return "*"; case details::e_div : return "/"; case details::e_mod : return "%"; + case details::e_pow : return "^"; default : return "" ; } } @@ -21559,13 +24399,14 @@ namespace exprtk std::size_t max_stack_depth_; std::size_t max_node_depth_; + std::size_t max_local_vector_size_; friend class parser; }; typedef settings_store settings_t; - parser(const settings_t& settings = settings_t()) + explicit parser(const settings_t& settings = settings_t()) : settings_(settings) , resolve_unknown_symbol_(false) , results_context_(0) @@ -21581,6 +24422,9 @@ namespace exprtk , operator_joiner_2_(2) , operator_joiner_3_(3) , loop_runtime_check_(0) + , vector_access_runtime_check_(0) + , compilation_check_ptr_(0) + , assert_check_(0) { init_precompilation(); @@ -21593,15 +24437,16 @@ namespace exprtk expression_generator_.init_synthesize_map(); expression_generator_.set_parser(*this); - expression_generator_.set_uom(unary_op_map_); - expression_generator_.set_bom(binary_op_map_); + expression_generator_.set_uom (unary_op_map_ ); + expression_generator_.set_bom (binary_op_map_ ); expression_generator_.set_ibom(inv_binary_op_map_); - expression_generator_.set_sf3m(sf3_map_); - expression_generator_.set_sf4m(sf4_map_); + expression_generator_.set_sf3m(sf3_map_ ); + expression_generator_.set_sf4m(sf4_map_ ); expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); } - ~parser() {} + ~parser() + {} inline void init_precompilation() { @@ -21669,11 +24514,15 @@ namespace exprtk inline bool compile(const std::string& expression_string, expression& expr) { - state_ .reset(); - error_list_ .clear(); - brkcnt_list_ .clear(); - synthesis_error_.clear(); - sem_ .cleanup(); + state_ .reset(); + error_list_ .clear(); + brkcnt_list_ .clear(); + synthesis_error_ .clear(); + immutable_memory_map_.reset(); + immutable_symtok_map_.clear(); + current_state_stack_ .clear(); + assert_ids_ .clear(); + sem_ .cleanup(); return_cleanup(); @@ -21681,10 +24530,10 @@ namespace exprtk if (expression_string.empty()) { - set_error( - make_error(parser_error::e_syntax, - "ERR001 - Empty expression!", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + "ERR001 - Empty expression!", + exprtk_error_location)); return false; } @@ -21697,19 +24546,31 @@ namespace exprtk if (lexer().empty()) { - set_error( - make_error(parser_error::e_syntax, - "ERR002 - Empty expression!", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + "ERR002 - Empty expression!", + exprtk_error_location)); return false; } + if (halt_compilation_check()) + { + exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); + return false; + } + if (!run_assemblies()) { return false; } + if (halt_compilation_check()) + { + exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); + return false; + } + symtab_store_.symtab_list_ = expr.get_symbol_table_list(); dec_.clear(); @@ -21743,11 +24604,11 @@ namespace exprtk { if (error_list_.empty()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR003 - Invalid expression encountered", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR003 - Invalid expression encountered", + exprtk_error_location)); } if ((0 != e) && branch_deletable(e)) @@ -21799,11 +24660,11 @@ namespace exprtk default : diagnostic += "Unknown compiler error"; } - set_error( - make_error(parser_error::e_lexer, - lexer()[i], - diagnostic + ": " + lexer()[i].value, - exprtk_error_location)); + set_error(make_error( + parser_error::e_lexer, + lexer()[i], + diagnostic + ": " + lexer()[i].value, + exprtk_error_location)); } } } @@ -21842,11 +24703,11 @@ namespace exprtk if (0 != (bracket_checker_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) { - set_error( - make_error(parser_error::e_token, - bracket_checker_ptr->error_token(), - "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_token, + bracket_checker_ptr->error_token(), + "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", + exprtk_error_location)); } else if (0 != (numeric_checker_ptr = dynamic_cast*>(helper_assembly_.error_token_scanner))) { @@ -21854,11 +24715,11 @@ namespace exprtk { lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; - set_error( - make_error(parser_error::e_token, - error_token, - "ERR006 - Invalid numeric token: '" + error_token.value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_token, + error_token, + "ERR006 - Invalid numeric token: '" + error_token.value + "'", + exprtk_error_location)); } if (numeric_checker_ptr->error_count()) @@ -21872,13 +24733,13 @@ namespace exprtk { std::pair error_token = sequence_validator_ptr->error(i); - set_error( - make_error(parser_error::e_token, - error_token.first, - "ERR007 - Invalid token sequence: '" + - error_token.first.value + "' and '" + - error_token.second.value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_token, + error_token.first, + "ERR007 - Invalid token sequence: '" + + error_token.first.value + "' and '" + + error_token.second.value + "'", + exprtk_error_location)); } if (sequence_validator_ptr->error_count()) @@ -21892,13 +24753,13 @@ namespace exprtk { std::pair error_token = sequence_validator3_ptr->error(i); - set_error( - make_error(parser_error::e_token, - error_token.first, - "ERR008 - Invalid token sequence: '" + - error_token.first.value + "' and '" + - error_token.second.value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_token, + error_token.first, + "ERR008 - Invalid token sequence: '" + + error_token.first.value + "' and '" + + error_token.second.value + "'", + exprtk_error_location)); } if (sequence_validator3_ptr->error_count()) @@ -21923,9 +24784,11 @@ namespace exprtk inline parser_error::type get_error(const std::size_t& index) const { if (index < error_list_.size()) + { return error_list_[index]; - else - throw std::invalid_argument("parser::get_error() - Invalid error index specificed"); + } + + throw std::invalid_argument("parser::get_error() - Invalid error index specified"); } inline std::string error() const @@ -21994,11 +24857,41 @@ namespace exprtk loop_runtime_check_ = &lrtchk; } + inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) + { + vector_access_runtime_check_ = &vartchk; + } + + inline void register_compilation_timeout_check(compilation_check& compchk) + { + compilation_check_ptr_ = &compchk; + } + + inline void register_assert_check(assert_check& assrt_chck) + { + assert_check_ = &assrt_chck; + } + inline void clear_loop_runtime_check() { loop_runtime_check_ = loop_runtime_check_ptr(0); } + inline void clear_vector_access_runtime_check() + { + vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); + } + + inline void clear_compilation_timeout_check() + { + compilation_check_ptr_ = compilation_check_ptr(0); + } + + inline void clear_assert_check() + { + assert_check_ = assert_check_ptr(0); + } + private: inline bool valid_base_operation(const std::string& symbol) const @@ -22102,11 +24995,11 @@ namespace exprtk { if (error_list_.empty()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR009 - Invalid expression encountered", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR009 - Invalid expression encountered", + exprtk_error_location)); } return error_node(); @@ -22132,15 +25025,31 @@ namespace exprtk exprtk_debug(("-------------------------------------------------\n")); } - if (lexer().finished()) - break; - else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) + if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) { if (lexer().finished()) break; else next_token(); } + else if ( + !settings_.commutative_check_enabled() && + ( + current_token().type == token_t::e_symbol || + current_token().type == token_t::e_number || + current_token().type == token_t::e_string || + token_is_bracket(prsrhlpr_t::e_hold) + ) + ) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", + exprtk_error_location)); + + return error_node(); + } } if ( @@ -22158,13 +25067,17 @@ namespace exprtk return result; } - std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token) + std::string construct_subexpr(lexer::token& begin_token, + lexer::token& end_token, + const bool cleanup_whitespace = true) { std::string result = lexer().substr(begin_token.position,end_token.position); - - for (std::size_t i = 0; i < result.size(); ++i) + if (cleanup_whitespace) { - if (details::is_whitespace(result[i])) result[i] = ' '; + for (std::size_t i = 0; i < result.size(); ++i) + { + if (details::is_whitespace(result[i])) result[i] = ' '; + } } return result; @@ -22176,11 +25089,13 @@ namespace exprtk { inline void set(const precedence_level& l, const precedence_level& r, - const details::operator_type& o) + const details::operator_type& o, + const token_t tkn = token_t()) { - left = l; - right = r; + left = l; + right = r; operation = o; + token = tkn; } inline void reset() @@ -22193,10 +25108,58 @@ namespace exprtk precedence_level left; precedence_level right; details::operator_type operation; + token_t token; }; + inline void push_current_state(const state_t current_state) + { + current_state_stack_.push_back(current_state); + } + + inline void pop_current_state() + { + if (!current_state_stack_.empty()) + { + current_state_stack_.pop_back(); + } + } + + inline state_t current_state() const + { + return (!current_state_stack_.empty()) ? + current_state_stack_.back() : + state_t(); + } + + inline bool halt_compilation_check() + { + compilation_check::compilation_context context; + + if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) + { + const std::string error_message = + !context.error_message.empty() ? " Details: " + context.error_message : ""; + + set_error(make_error( + parser_error::e_parser, + token_t(), + "ERR011 - Internal compilation check failed." + error_message, + exprtk_error_location)); + + return true; + } + + return false; + } + inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) { + if (halt_compilation_check()) + { + exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); + return error_node(); + } + stack_limit_handler slh(*this); if (!slh) @@ -22211,6 +25174,11 @@ namespace exprtk return error_node(); } + if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) + { + return expression; + } + bool break_loop = false; state_t current_state; @@ -22221,110 +25189,111 @@ namespace exprtk switch (current_token().type) { - case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign); break; - case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass); break; - case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass); break; - case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass); break; - case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass); break; - case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass); break; - case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap ); break; - case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt ); break; - case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte ); break; - case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq ); break; - case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne ); break; - case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte ); break; - case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt ); break; - case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add ); break; - case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub ); break; - case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div ); break; - case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul ); break; - case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod ); break; - case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow ); break; - default : if (token_t::e_symbol == current_token().type) - { - static const std::string s_and = "and" ; - static const std::string s_nand = "nand" ; - static const std::string s_or = "or" ; - static const std::string s_nor = "nor" ; - static const std::string s_xor = "xor" ; - static const std::string s_xnor = "xnor" ; - static const std::string s_in = "in" ; - static const std::string s_like = "like" ; - static const std::string s_ilike = "ilike"; - static const std::string s_and1 = "&" ; - static const std::string s_or1 = "|" ; - static const std::string s_not = "not" ; - - if (details::imatch(current_token().value,s_and)) - { - current_state.set(e_level03, e_level04, details::e_and); - break; - } - else if (details::imatch(current_token().value,s_and1)) - { - #ifndef exprtk_disable_sc_andor - current_state.set(e_level03, e_level04, details::e_scand); - #else - current_state.set(e_level03, e_level04, details::e_and); - #endif - break; - } - else if (details::imatch(current_token().value,s_nand)) - { - current_state.set(e_level03, e_level04, details::e_nand); - break; - } - else if (details::imatch(current_token().value,s_or)) - { - current_state.set(e_level01, e_level02, details::e_or); - break; - } - else if (details::imatch(current_token().value,s_or1)) - { - #ifndef exprtk_disable_sc_andor - current_state.set(e_level01, e_level02, details::e_scor); - #else - current_state.set(e_level01, e_level02, details::e_or); - #endif - break; - } - else if (details::imatch(current_token().value,s_nor)) - { - current_state.set(e_level01, e_level02, details::e_nor); - break; - } - else if (details::imatch(current_token().value,s_xor)) - { - current_state.set(e_level01, e_level02, details::e_xor); - break; - } - else if (details::imatch(current_token().value,s_xnor)) - { - current_state.set(e_level01, e_level02, details::e_xnor); - break; - } - else if (details::imatch(current_token().value,s_in)) - { - current_state.set(e_level04, e_level04, details::e_in); - break; - } - else if (details::imatch(current_token().value,s_like)) - { - current_state.set(e_level04, e_level04, details::e_like); - break; - } - else if (details::imatch(current_token().value,s_ilike)) - { - current_state.set(e_level04, e_level04, details::e_ilike); - break; - } - else if (details::imatch(current_token().value,s_not)) - { - break; - } - } - - break_loop = true; + case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; + case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; + case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; + case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; + case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; + case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; + case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; + case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; + case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; + case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; + case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; + case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; + case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; + case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; + case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; + case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; + case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; + case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; + case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; + default : + if (token_t::e_symbol == current_token().type) + { + static const std::string s_and = "and" ; + static const std::string s_nand = "nand" ; + static const std::string s_or = "or" ; + static const std::string s_nor = "nor" ; + static const std::string s_xor = "xor" ; + static const std::string s_xnor = "xnor" ; + static const std::string s_in = "in" ; + static const std::string s_like = "like" ; + static const std::string s_ilike = "ilike"; + static const std::string s_and1 = "&" ; + static const std::string s_or1 = "|" ; + static const std::string s_not = "not" ; + + if (details::imatch(current_token().value,s_and)) + { + current_state.set(e_level03, e_level04, details::e_and, current_token()); + break; + } + else if (details::imatch(current_token().value,s_and1)) + { + #ifndef exprtk_disable_sc_andor + current_state.set(e_level03, e_level04, details::e_scand, current_token()); + #else + current_state.set(e_level03, e_level04, details::e_and, current_token()); + #endif + break; + } + else if (details::imatch(current_token().value,s_nand)) + { + current_state.set(e_level03, e_level04, details::e_nand, current_token()); + break; + } + else if (details::imatch(current_token().value,s_or)) + { + current_state.set(e_level01, e_level02, details::e_or, current_token()); + break; + } + else if (details::imatch(current_token().value,s_or1)) + { + #ifndef exprtk_disable_sc_andor + current_state.set(e_level01, e_level02, details::e_scor, current_token()); + #else + current_state.set(e_level01, e_level02, details::e_or, current_token()); + #endif + break; + } + else if (details::imatch(current_token().value,s_nor)) + { + current_state.set(e_level01, e_level02, details::e_nor, current_token()); + break; + } + else if (details::imatch(current_token().value,s_xor)) + { + current_state.set(e_level01, e_level02, details::e_xor, current_token()); + break; + } + else if (details::imatch(current_token().value,s_xnor)) + { + current_state.set(e_level01, e_level02, details::e_xnor, current_token()); + break; + } + else if (details::imatch(current_token().value,s_in)) + { + current_state.set(e_level04, e_level04, details::e_in, current_token()); + break; + } + else if (details::imatch(current_token().value,s_like)) + { + current_state.set(e_level04, e_level04, details::e_like, current_token()); + break; + } + else if (details::imatch(current_token().value,s_ilike)) + { + current_state.set(e_level04, e_level04, details::e_ilike, current_token()); + break; + } + else if (details::imatch(current_token().value,s_not)) + { + break; + } + } + + break_loop = true; } if (break_loop) @@ -22344,49 +25313,49 @@ namespace exprtk if (is_invalid_logic_operation(current_state.operation)) { - free_node(node_allocator_,expression); + free_node(node_allocator_, expression); - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR010 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + prev_token, + "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); return error_node(); } else if (is_invalid_arithmetic_operation(current_state.operation)) { - free_node(node_allocator_,expression); + free_node(node_allocator_, expression); - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR011 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + prev_token, + "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); return error_node(); } else if (is_invalid_inequality_operation(current_state.operation)) { - free_node(node_allocator_,expression); + free_node(node_allocator_, expression); - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR012 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + prev_token, + "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); return error_node(); } else if (is_invalid_assignment_operation(current_state.operation)) { - free_node(node_allocator_,expression); + free_node(node_allocator_, expression); - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR013 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + prev_token, + "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); return error_node(); } @@ -22401,34 +25370,38 @@ namespace exprtk free_node(node_allocator_, expression ); free_node(node_allocator_, right_branch); - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR014 - Return statements cannot be part of sub-expressions", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + prev_token, + "ERR016 - Return statements cannot be part of sub-expressions", + exprtk_error_location)); return error_node(); } + push_current_state(current_state); + new_expression = expression_generator_ ( current_state.operation, expression, right_branch ); + + pop_current_state(); } if (0 == new_expression) { if (error_list_.empty()) { - set_error( - make_error(parser_error::e_syntax, - prev_token, - !synthesis_error_.empty() ? - synthesis_error_ : - "ERR015 - General parsing error at token: '" + prev_token.value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + prev_token, + !synthesis_error_.empty() ? + synthesis_error_ : + "ERR017 - General parsing error at token: '" + prev_token.value + "'", + exprtk_error_location)); } free_node(node_allocator_, expression ); @@ -22454,14 +25427,35 @@ namespace exprtk if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR016 - Expression depth of " + details::to_str(static_cast(expression->node_depth())) + - " exceeds maximum allowed expression depth of " + details::to_str(static_cast(settings_.max_node_depth_)), - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR018 - Expression depth of " + details::to_str(static_cast(expression->node_depth())) + + " exceeds maximum allowed expression depth of " + details::to_str(static_cast(settings_.max_node_depth_)), + exprtk_error_location)); - free_node(node_allocator_,expression); + free_node(node_allocator_, expression); + + return error_node(); + } + else if ( + !settings_.commutative_check_enabled() && + !details::is_logic_opr(current_token().value) && + (current_state.operation == details::e_default) && + ( + current_token().type == token_t::e_symbol || + current_token().type == token_t::e_number || + current_token().type == token_t::e_string + ) + ) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", + exprtk_error_location)); + + free_node(node_allocator_, expression); return error_node(); } @@ -22479,7 +25473,7 @@ namespace exprtk { expression_node_ptr un_r = n->branch(0); n->release(); - free_node(node_allocator_,node); + free_node(node_allocator_, node); node = un_r; return true; @@ -22501,20 +25495,20 @@ namespace exprtk (0 != (return_node = sem_ .get_variable(v))) ) { - free_node(node_allocator_,node); + free_node(node_allocator_, node); node = return_node; return true; } else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR017 - Failed to find variable node in symbol table", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR020 - Failed to find variable node in symbol table", + exprtk_error_location)); - free_node(node_allocator_,node); + free_node(node_allocator_, node); return false; } @@ -22610,6 +25604,7 @@ namespace exprtk { for (std::size_t i = 0; i < deq_.size(); ++i) { + exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast(deq_[i]))); free_node(parser_.node_allocator_,deq_[i]); } @@ -22644,6 +25639,7 @@ namespace exprtk { for (std::size_t i = 0; i < vec_.size(); ++i) { + exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast(vec_[i]))); free_node(parser_.node_allocator_,vec_[i]); } @@ -22651,6 +25647,11 @@ namespace exprtk } } + ptr_t operator[](const std::size_t index) + { + return vec_[index]; + } + bool delete_ptr; parser& parser_; std::vector& vec_; @@ -22732,11 +25733,11 @@ namespace exprtk case 19 : func_node = parse_function_call<19>(function,function_name); break; case 20 : func_node = parse_function_call<20>(function,function_name); break; default : { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR018 - Invalid number of parameters for function: '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR021 - Invalid number of parameters for function: '" + function_name + "'", + exprtk_error_location)); return error_node(); } @@ -22746,11 +25747,11 @@ namespace exprtk return func_node; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR019 - Failed to generate call to function: '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR022 - Failed to generate call to function: '" + function_name + "'", + exprtk_error_location)); return error_node(); } @@ -22765,11 +25766,11 @@ namespace exprtk #endif if (0 == NumberofParameters) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR020 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", + exprtk_error_location)); return error_node(); } @@ -22788,11 +25789,11 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR021 - Expecting argument list for function: '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR024 - Expecting argument list for function: '" + function_name + "'", + exprtk_error_location)); return error_node(); } @@ -22803,11 +25804,11 @@ namespace exprtk if (0 == branch[i]) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR022 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", + exprtk_error_location)); return error_node(); } @@ -22815,11 +25816,11 @@ namespace exprtk { if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR023 - Invalid number of arguments for function: '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR026 - Invalid number of arguments for function: '" + function_name + "'", + exprtk_error_location)); return error_node(); } @@ -22828,11 +25829,11 @@ namespace exprtk if (!token_is(token_t::e_rbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR024 - Invalid number of arguments for function: '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR027 - Invalid number of arguments for function: '" + function_name + "'", + exprtk_error_location)); return error_node(); } @@ -22857,13 +25858,13 @@ namespace exprtk !token_is(token_t::e_rbracket) ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR025 - Expecting '()' to proceed call to function: '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", + exprtk_error_location)); - free_node(node_allocator_,result); + free_node(node_allocator_, result); return error_node(); } @@ -22882,23 +25883,23 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR026 - Expected a '(' at start of function call to '" + function_name + - "', instead got: '" + current_token().value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR029 - Expected a '(' at start of function call to '" + function_name + + "', instead got: '" + current_token().value + "'", + exprtk_error_location)); return 0; } if (token_is(token_t::e_rbracket, e_hold)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR027 - Expected at least one input parameter for function call '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", + exprtk_error_location)); return 0; } @@ -22920,11 +25921,11 @@ namespace exprtk continue; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR028 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", + exprtk_error_location)); return 0; } @@ -22932,11 +25933,11 @@ namespace exprtk if (sd.delete_ptr) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR029 - Invalid number of input parameters passed to function '" + function_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", + exprtk_error_location)); return 0; } @@ -22955,11 +25956,11 @@ namespace exprtk if (0 == std::distance(itr_range.first,itr_range.second)) { - set_error( - make_error(parser_error::e_syntax, - diagnostic_token, - "ERR030 - No entry found for base operation: " + operation_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + diagnostic_token, + "ERR033 - No entry found for base operation: " + operation_name, + exprtk_error_location)); return error_node(); } @@ -23002,11 +26003,11 @@ namespace exprtk free_node(node_allocator_, param_list[i]); } - set_error( - make_error(parser_error::e_syntax, - diagnostic_token, - "ERR031 - Invalid number of input parameters for call to function: '" + operation_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + diagnostic_token, + "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", + exprtk_error_location)); return error_node(); } @@ -23022,47 +26023,52 @@ namespace exprtk if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR032 - Expected ',' between if-statement condition and consequent", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR035 - Expected ',' between if-statement condition and consequent", + exprtk_error_location)); + result = false; } else if (0 == (consequent = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR033 - Failed to parse consequent for if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR036 - Failed to parse consequent for if-statement", + exprtk_error_location)); + result = false; } else if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR034 - Expected ',' between if-statement consequent and alternative", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR037 - Expected ',' between if-statement consequent and alternative", + exprtk_error_location)); + result = false; } else if (0 == (alternative = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR035 - Failed to parse alternative for if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR038 - Failed to parse alternative for if-statement", + exprtk_error_location)); + result = false; } else if (!token_is(token_t::e_rbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR036 - Expected ')' at the end of if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR039 - Expected ')' at the end of if-statement", + exprtk_error_location)); + result = false; } @@ -23076,15 +26082,30 @@ namespace exprtk { if (consq_is_str && alter_is_str) { - return expression_generator_ - .conditional_string(condition, consequent, alternative); + expression_node_ptr result_node = + expression_generator_ + .conditional_string(condition, consequent, alternative); + + if (result_node && result_node->valid()) + { + return result_node; + } + + set_error(make_error( + parser_error::e_synthesis, + current_token(), + "ERR040 - Failed to synthesize node: conditional_string", + exprtk_error_location)); + + free_node(node_allocator_, result_node); + return error_node(); } - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR037 - Return types of if-statement differ: string/non-string", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR041 - Return types of if-statement differ: string/non-string", + exprtk_error_location)); result = false; } @@ -23104,11 +26125,11 @@ namespace exprtk .conditional_vector(condition, consequent, alternative); } - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR038 - Return types of if-statement differ: vector/non-vector", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR042 - Return types of if-statement differ: vector/non-vector", + exprtk_error_location)); result = false; } @@ -23138,11 +26159,31 @@ namespace exprtk { if (0 == (consequent = parse_multi_sequence("if-statement-01"))) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR039 - Failed to parse body of consequent for if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR043 - Failed to parse body of consequent for if-statement", + exprtk_error_location)); + + result = false; + } + else if + ( + !settings_.commutative_check_enabled() && + !token_is("else",prsrhlpr_t::e_hold) && + !token_is_loop(prsrhlpr_t::e_hold) && + !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && + !token_is_right_bracket (prsrhlpr_t::e_hold) && + !token_is_ineq_opr (prsrhlpr_t::e_hold) && + !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && + !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) + ) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", + exprtk_error_location)); result = false; } @@ -23159,24 +26200,24 @@ namespace exprtk if (0 != (consequent = parse_expression())) { - if (!token_is(token_t::e_eof)) + if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR040 - Expected ';' at the end of the consequent for if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", + exprtk_error_location)); result = false; } } else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR041 - Failed to parse body of consequent for if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR046 - Failed to parse body of consequent for if-statement", + exprtk_error_location)); result = false; } @@ -23184,19 +26225,27 @@ namespace exprtk if (result) { - if (details::imatch(current_token().value,"else")) + if ( + details::imatch(current_token().value,"else") || + (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) + ) { next_token(); + if (details::imatch(current_token().value,"else")) + { + next_token(); + } + if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) { if (0 == (alternative = parse_multi_sequence("else-statement-01"))) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR042 - Failed to parse body of the 'else' for if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR047 - Failed to parse body of the 'else' for if-statement", + exprtk_error_location)); result = false; } @@ -23205,35 +26254,39 @@ namespace exprtk { if (0 == (alternative = parse_conditional_statement())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR043 - Failed to parse body of if-else statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR048 - Failed to parse body of if-else statement", + exprtk_error_location)); result = false; } } else if (0 != (alternative = parse_expression())) { - if (!token_is(token_t::e_eof)) + if ( + !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && + !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && + !token_is(token_t::e_eof) + ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR044 - Expected ';' at the end of the 'else-if' for the if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", + exprtk_error_location)); result = false; } } else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR045 - Failed to parse body of the 'else' for if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR050 - Failed to parse body of the 'else' for if-statement", + exprtk_error_location)); result = false; } @@ -23254,11 +26307,11 @@ namespace exprtk .conditional_string(condition, consequent, alternative); } - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR046 - Return types of if-statement differ: string/non-string", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR051 - Return types of if-statement differ: string/non-string", + exprtk_error_location)); result = false; } @@ -23278,11 +26331,11 @@ namespace exprtk .conditional_vector(condition, consequent, alternative); } - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR047 - Return types of if-statement differ: vector/non-vector", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR052 - Return types of if-statement differ: vector/non-vector", + exprtk_error_location)); result = false; } @@ -23309,21 +26362,21 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR048 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", + exprtk_error_location)); return error_node(); } else if (0 == (condition = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR049 - Failed to parse condition for if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR054 - Failed to parse condition for if-statement", + exprtk_error_location)); return error_node(); } @@ -23353,13 +26406,13 @@ namespace exprtk return parse_conditional_statement_02(condition); } - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR050 - Invalid if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR055 - Invalid if-statement", + exprtk_error_location)); - free_node(node_allocator_,condition); + free_node(node_allocator_, condition); return error_node(); } @@ -23374,51 +26427,51 @@ namespace exprtk if (0 == condition) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR051 - Encountered invalid condition branch for ternary if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR056 - Encountered invalid condition branch for ternary if-statement", + exprtk_error_location)); return error_node(); } else if (!token_is(token_t::e_ternary)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR052 - Expected '?' after condition of ternary if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR057 - Expected '?' after condition of ternary if-statement", + exprtk_error_location)); result = false; } else if (0 == (consequent = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR053 - Failed to parse consequent for ternary if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR058 - Failed to parse consequent for ternary if-statement", + exprtk_error_location)); result = false; } else if (!token_is(token_t::e_colon)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR054 - Expected ':' between ternary if-statement consequent and alternative", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR059 - Expected ':' between ternary if-statement consequent and alternative", + exprtk_error_location)); result = false; } else if (0 == (alternative = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR055 - Failed to parse alternative for ternary if-statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR060 - Failed to parse alternative for ternary if-statement", + exprtk_error_location)); result = false; } @@ -23437,11 +26490,11 @@ namespace exprtk .conditional_string(condition, consequent, alternative); } - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR056 - Return types of ternary differ: string/non-string", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR061 - Return types of ternary differ: string/non-string", + exprtk_error_location)); result = false; } @@ -23461,11 +26514,11 @@ namespace exprtk .conditional_vector(condition, consequent, alternative); } - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR057 - Return types of ternary differ: vector/non-vector", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR062 - Return types of ternary differ: vector/non-vector", + exprtk_error_location)); result = false; } @@ -23488,11 +26541,11 @@ namespace exprtk { if (settings_.logic_disabled("not")) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR058 - Invalid or disabled logic operation 'not'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR063 - Invalid or disabled logic operation 'not'", + exprtk_error_location)); return error_node(); } @@ -23519,31 +26572,31 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR059 - Expected '(' at start of while-loop condition statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR064 - Expected '(' at start of while-loop condition statement", + exprtk_error_location)); return error_node(); } else if (0 == (condition = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR060 - Failed to parse condition for while-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR065 - Failed to parse condition for while-loop", + exprtk_error_location)); return error_node(); } else if (!token_is(token_t::e_rbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR061 - Expected ')' at end of while-loop condition statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR066 - Expected ')' at end of while-loop condition statement", + exprtk_error_location)); result = false; } @@ -23556,21 +26609,21 @@ namespace exprtk if (0 == (branch = parse_multi_sequence("while-loop", true))) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR062 - Failed to parse body of while-loop")); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR067 - Failed to parse body of while-loop")); result = false; } else if (0 == (result_node = expression_generator_.while_loop(condition, branch, brkcnt_list_.front()))) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR063 - Failed to synthesize while-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR068 - Failed to synthesize while-loop", + exprtk_error_location)); result = false; } @@ -23587,7 +26640,20 @@ namespace exprtk return error_node(); } - return result_node; + if (result_node && result_node->valid()) + { + return result_node; + } + + set_error(make_error( + parser_error::e_synthesis, + current_token(), + "ERR069 - Failed to synthesize 'valid' while-loop", + exprtk_error_location)); + + free_node(node_allocator_, result_node); + + return error_node(); } inline expression_node_ptr parse_repeat_until_loop() @@ -23611,7 +26677,7 @@ namespace exprtk } else { - const token_t::token_type seperator = token_t::e_eof; + const token_t::token_type separator = token_t::e_eof; scope_handler sh(*this); @@ -23642,13 +26708,13 @@ namespace exprtk const bool is_next_until = peek_token_is(token_t::e_symbol) && peek_token_is("until"); - if (!token_is(seperator) && is_next_until) + if (!token_is(separator) && is_next_until) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR064 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", + exprtk_error_location)); return error_node(); } @@ -23666,11 +26732,11 @@ namespace exprtk if (sdd.delete_ptr) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR065 - Failed to parse body of repeat until loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR071 - Failed to parse body of repeat until loop", + exprtk_error_location)); return error_node(); } @@ -23678,33 +26744,33 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR066 - Expected '(' before condition statement of repeat until loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR072 - Expected '(' before condition statement of repeat until loop", + exprtk_error_location)); - free_node(node_allocator_,branch); + free_node(node_allocator_, branch); return error_node(); } else if (0 == (condition = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR067 - Failed to parse condition for repeat until loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR073 - Failed to parse condition for repeat until loop", + exprtk_error_location)); - free_node(node_allocator_,branch); + free_node(node_allocator_, branch); return error_node(); } else if (!token_is(token_t::e_rbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR068 - Expected ')' after condition of repeat until loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR074 - Expected ')' after condition of repeat until loop", + exprtk_error_location)); free_node(node_allocator_, branch ); free_node(node_allocator_, condition); @@ -23712,27 +26778,42 @@ namespace exprtk return error_node(); } - expression_node_ptr result; - - result = expression_generator_ - .repeat_until_loop(condition, branch, brkcnt_list_.front()); + expression_node_ptr result_node = + expression_generator_ + .repeat_until_loop( + condition, + branch, + brkcnt_list_.front()); - if (0 == result) + if (0 == result_node) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR069 - Failed to synthesize repeat until loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR075 - Failed to synthesize repeat until loop", + exprtk_error_location)); - free_node(node_allocator_,condition); + free_node(node_allocator_, condition); return error_node(); } handle_brkcnt_scope_exit(); - return result; + if (result_node && result_node->valid()) + { + return result_node; + } + + set_error(make_error( + parser_error::e_synthesis, + current_token(), + "ERR076 - Failed to synthesize 'valid' repeat until loop", + exprtk_error_location)); + + free_node(node_allocator_, result_node); + + return error_node(); } inline expression_node_ptr parse_for_loop() @@ -23751,11 +26832,11 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR070 - Expected '(' at start of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR077 - Expected '(' at start of for-loop", + exprtk_error_location)); return error_node(); } @@ -23771,21 +26852,21 @@ namespace exprtk if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR071 - Expected a variable at the start of initialiser section of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR078 - Expected a variable at the start of initialiser section of for-loop", + exprtk_error_location)); return error_node(); } else if (!peek_token_is(token_t::e_assign)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR072 - Expected variable assignment of initialiser section of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR079 - Expected variable assignment of initialiser section of for-loop", + exprtk_error_location)); return error_node(); } @@ -23796,11 +26877,11 @@ namespace exprtk if ((se->name == loop_counter_symbol) && se->active) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR073 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", + exprtk_error_location)); return error_node(); } @@ -23828,11 +26909,11 @@ namespace exprtk if (!sem_.add_element(nse)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR074 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", + exprtk_error_location)); sem_.free_element(nse); @@ -23840,7 +26921,7 @@ namespace exprtk } else { - exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str())); + exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); state_.activate_side_effect("parse_for_loop()"); } @@ -23850,21 +26931,21 @@ namespace exprtk if (0 == (initialiser = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR075 - Failed to parse initialiser of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR082 - Failed to parse initialiser of for-loop", + exprtk_error_location)); result = false; } else if (!token_is(token_t::e_eof)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR076 - Expected ';' after initialiser of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR083 - Expected ';' after initialiser of for-loop", + exprtk_error_location)); result = false; } @@ -23874,21 +26955,21 @@ namespace exprtk { if (0 == (condition = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR077 - Failed to parse condition of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR084 - Failed to parse condition of for-loop", + exprtk_error_location)); result = false; } else if (!token_is(token_t::e_eof)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR078 - Expected ';' after condition section of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR085 - Expected ';' after condition section of for-loop", + exprtk_error_location)); result = false; } @@ -23898,21 +26979,21 @@ namespace exprtk { if (0 == (incrementor = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR079 - Failed to parse incrementor of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR086 - Failed to parse incrementor of for-loop", + exprtk_error_location)); result = false; } else if (!token_is(token_t::e_rbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR080 - Expected ')' after incrementor section of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR087 - Expected ')' after incrementor section of for-loop", + exprtk_error_location)); result = false; } @@ -23926,11 +27007,11 @@ namespace exprtk if (0 == (loop_body = parse_multi_sequence("for-loop", true))) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR081 - Failed to parse body of for-loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR088 - Failed to parse body of for-loop", + exprtk_error_location)); result = false; } @@ -23958,7 +27039,20 @@ namespace exprtk brkcnt_list_.front()); handle_brkcnt_scope_exit(); - return result_node; + if (result_node && result_node->valid()) + { + return result_node; + } + + set_error(make_error( + parser_error::e_synthesis, + current_token(), + "ERR089 - Failed to synthesize 'valid' for-loop", + exprtk_error_location)); + + free_node(node_allocator_, result_node); + + return error_node(); } inline expression_node_ptr parse_switch_statement() @@ -23968,11 +27062,11 @@ namespace exprtk if (!details::imatch(current_token().value,"switch")) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR082 - Expected keyword 'switch'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR090 - Expected keyword 'switch'", + exprtk_error_location)); return error_node(); } @@ -23983,11 +27077,11 @@ namespace exprtk if (!token_is(token_t::e_lcrlbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR083 - Expected '{' for call to switch statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR091 - Expected '{' for call to switch statement", + exprtk_error_location)); return error_node(); } @@ -24008,18 +27102,21 @@ namespace exprtk return error_node(); else if (!token_is(token_t::e_colon)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR084 - Expected ':' for case of switch statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR092 - Expected ':' for case of switch statement", + exprtk_error_location)); free_node(node_allocator_, condition); return error_node(); } - expression_node_ptr consequent = parse_expression(); + expression_node_ptr consequent = + (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? + parse_multi_sequence("switch-consequent") : + parse_expression(); if (0 == consequent) { @@ -24029,11 +27126,11 @@ namespace exprtk } else if (!token_is(token_t::e_eof)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR085 - Expected ';' at end of case for switch statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR093 - Expected ';' at end of case for switch statement", + exprtk_error_location)); free_node(node_allocator_, condition ); free_node(node_allocator_, consequent); @@ -24058,11 +27155,11 @@ namespace exprtk { if (0 != default_statement) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR086 - Multiple default cases for switch statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR094 - Multiple default cases for switch statement", + exprtk_error_location)); return error_node(); } @@ -24071,29 +27168,29 @@ namespace exprtk if (!token_is(token_t::e_colon)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR087 - Expected ':' for default of switch statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR095 - Expected ':' for default of switch statement", + exprtk_error_location)); return error_node(); } - if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) - default_statement = parse_multi_sequence("switch-default"); - else - default_statement = parse_expression(); + default_statement = + (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? + parse_multi_sequence("switch-default"): + parse_expression(); if (0 == default_statement) return error_node(); else if (!token_is(token_t::e_eof)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR088 - Expected ';' at end of default for switch statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR096 - Expected ';' at end of default for switch statement", + exprtk_error_location)); return error_node(); } @@ -24102,11 +27199,11 @@ namespace exprtk break; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR089 - Expected '}' at end of switch statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR097 - Expected '}' at end of switch statement", + exprtk_error_location)); return error_node(); } @@ -24118,6 +27215,10 @@ namespace exprtk { arg_list.push_back(default_statement); } + else + { + arg_list.push_back(node_allocator_.allocate_c(std::numeric_limits::quiet_NaN())); + } result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); @@ -24133,11 +27234,11 @@ namespace exprtk if (!details::imatch(current_token().value,"[*]")) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR090 - Expected token '[*]'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR098 - Expected token '[*]'", + exprtk_error_location)); return error_node(); } @@ -24148,11 +27249,11 @@ namespace exprtk if (!token_is(token_t::e_lcrlbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR091 - Expected '{' for call to [*] statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR099 - Expected '{' for call to [*] statement", + exprtk_error_location)); return error_node(); } @@ -24161,11 +27262,11 @@ namespace exprtk { if (!details::imatch("case",current_token().value)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR092 - Expected a 'case' statement for multi-switch", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR100 - Expected a 'case' statement for multi-switch", + exprtk_error_location)); return error_node(); } @@ -24179,27 +27280,30 @@ namespace exprtk if (!token_is(token_t::e_colon)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR093 - Expected ':' for case of [*] statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR101 - Expected ':' for case of [*] statement", + exprtk_error_location)); return error_node(); } - expression_node_ptr consequent = parse_expression(); + expression_node_ptr consequent = + (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? + parse_multi_sequence("multi-switch-consequent") : + parse_expression(); if (0 == consequent) return error_node(); if (!token_is(token_t::e_eof)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR094 - Expected ';' at end of case for [*] statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR102 - Expected ';' at end of case for [*] statement", + exprtk_error_location)); return error_node(); } @@ -24224,11 +27328,11 @@ namespace exprtk if (!token_is(token_t::e_rcrlbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR095 - Expected '}' at end of [*] statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR103 - Expected '}' at end of [*] statement", + exprtk_error_location)); return error_node(); } @@ -24250,11 +27354,11 @@ namespace exprtk if (details::imatch(symbol,"~")) { next_token(); - return parse_multi_sequence(); + return check_block_statement_closure(parse_multi_sequence()); } else if (details::imatch(symbol,"[*]")) { - return parse_multi_switch_statement(); + return check_block_statement_closure(parse_multi_switch_statement()); } else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; @@ -24265,11 +27369,11 @@ namespace exprtk else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR096 - Unsupported built-in vararg function: " + symbol, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR104 - Unsupported built-in vararg function: " + symbol, + exprtk_error_location)); return error_node(); } @@ -24282,23 +27386,23 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR097 - Expected '(' for call to vararg function: " + symbol, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR105 - Expected '(' for call to vararg function: " + symbol, + exprtk_error_location)); return error_node(); } if (token_is(token_t::e_rbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR098 - vararg function: " + symbol + - " requires at least one input parameter", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR106 - vararg function: " + symbol + + " requires at least one input parameter", + exprtk_error_location)); return error_node(); } @@ -24316,11 +27420,11 @@ namespace exprtk break; else if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR099 - Expected ',' for call to vararg function: " + symbol, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR107 - Expected ',' for call to vararg function: " + symbol, + exprtk_error_location)); return error_node(); } @@ -24337,13 +27441,13 @@ namespace exprtk { if (!token_is(token_t::e_lsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR100 - Expected '[' as start of string range definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR108 - Expected '[' as start of string range definition", + exprtk_error_location)); - free_node(node_allocator_,expression); + free_node(node_allocator_, expression); return error_node(); } @@ -24356,7 +27460,7 @@ namespace exprtk if (!parse_range(rp,true)) { - free_node(node_allocator_,expression); + free_node(node_allocator_, expression); return error_node(); } @@ -24365,19 +27469,32 @@ namespace exprtk if (0 == result) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR101 - Failed to generate string range node", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR109 - Failed to generate string range node", + exprtk_error_location)); - free_node(node_allocator_,expression); + free_node(node_allocator_, expression); rp.free(); } rp.clear(); - return result; + if (result && result->valid()) + { + return result; + } + + set_error(make_error( + parser_error::e_synthesis, + current_token(), + "ERR110 - Failed to synthesize node: string_range_node", + exprtk_error_location)); + + free_node(node_allocator_, result); + rp.free(); + return error_node(); } #else inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) @@ -24386,7 +27503,7 @@ namespace exprtk } #endif - inline void parse_pending_string_rangesize(expression_node_ptr& expression) + inline bool parse_pending_string_rangesize(expression_node_ptr& expression) { // Allow no more than 100 range calls, eg: s[][][]...[][] const std::size_t max_rangesize_parses = 100; @@ -24404,6 +27521,61 @@ namespace exprtk { expression = parse_string_range_statement(expression); } + + return (i > 1); + } + + inline void parse_pending_vector_index_operator(expression_node_ptr& expression) + { + if + ( + (0 != expression) && + error_list_.empty() && + is_ivector_node(expression) + ) + { + if ( + settings_.commutative_check_enabled() && + token_is(token_t::e_mul,prsrhlpr_t::e_hold) && + peek_token_is(token_t::e_lsqrbracket) + ) + { + token_is(token_t::e_mul); + token_is(token_t::e_lsqrbracket); + } + else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) + { + token_is(token_t::e_lsqrbracket); + } + else if ( + token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && + peek_token_is(token_t::e_lsqrbracket) + ) + { + token_is(token_t::e_rbracket ); + token_is(token_t::e_lsqrbracket); + } + else + return; + + details::vector_interface* vi = dynamic_cast*>(expression); + + if (vi) + { + details::vector_holder& vec = vi->vec()->vec_holder(); + const std::string vector_name = sem_.get_vector_name(vec.data()); + expression_node_ptr index = parse_vector_index(vector_name); + + if (index) + { + expression = synthesize_vector_element(vector_name, &vec, expression, index); + return; + } + } + + free_node(node_allocator_, expression); + expression = error_node(); + } } template tmp_expression_list; + exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", + static_cast(expression_list .size()), + static_cast(side_effect_list.size()))); + bool return_node_present = false; for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) @@ -24439,7 +27615,7 @@ namespace exprtk for (std::size_t j = i + 1; j < expression_list.size(); ++j) { - free_node(node_allocator_,expression_list[j]); + free_node(node_allocator_, expression_list[j]); } return_node_present = true; @@ -24452,7 +27628,7 @@ namespace exprtk !side_effect_list[i] ) { - free_node(node_allocator_,expression_list[i]); + free_node(node_allocator_, expression_list[i]); continue; } else @@ -24493,7 +27669,7 @@ namespace exprtk { token_t::token_type open_bracket = token_t::e_lcrlbracket; token_t::token_type close_bracket = token_t::e_rcrlbracket; - token_t::token_type seperator = token_t::e_eof; + token_t::token_type separator = token_t::e_eof; if (!token_is(open_bracket)) { @@ -24501,16 +27677,16 @@ namespace exprtk { open_bracket = token_t::e_lbracket; close_bracket = token_t::e_rbracket; - seperator = token_t::e_comma; + separator = token_t::e_comma; } else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR102 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + - ((!source.empty()) ? std::string(" section of " + source): ""), - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + + ((!source.empty()) ? std::string(" section of " + source): ""), + exprtk_error_location)); return error_node(); } @@ -24550,13 +27726,13 @@ namespace exprtk const bool is_next_close = peek_token_is(close_bracket); - if (!token_is(seperator) && is_next_close) + if (!token_is(separator) && is_next_close) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR103 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, + exprtk_error_location)); return error_node(); } @@ -24574,23 +27750,23 @@ namespace exprtk inline bool parse_range(range_t& rp, const bool skip_lsqr = false) { // Examples of valid ranges: - // 1. [1:5] -> 1..5 - // 2. [ :5] -> 0..5 - // 3. [1: ] -> 1..end - // 4. [x:y] -> x..y where x <= y - // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2 - // 6. [ :y] -> 0..y where 0 <= y - // 7. [x: ] -> x..end where x <= end + // 1. [1:5] -> [1,5) + // 2. [ :5] -> [0,5) + // 3. [1: ] -> [1,end) + // 4. [x:y] -> [x,y) where x <= y + // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 + // 6. [ :y] -> [0,y) where 0 <= y + // 7. [x: ] -> [x,end) where x <= end rp.clear(); if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR104 - Expected '[' for start of range", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR113 - Expected '[' for start of range", + exprtk_error_location)); return false; } @@ -24607,11 +27783,11 @@ namespace exprtk if (0 == r0) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR105 - Failed parse begin section of range", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR114 - Failed parse begin section of range", + exprtk_error_location)); return false; } @@ -24626,15 +27802,15 @@ namespace exprtk rp.cache.first = rp.n0_c.second; } - free_node(node_allocator_,r0); + free_node(node_allocator_, r0); if (r0_value < T(0)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR106 - Range lower bound less than zero! Constraint: r0 >= 0", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", + exprtk_error_location)); return false; } @@ -24647,11 +27823,11 @@ namespace exprtk if (!token_is(token_t::e_colon)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR107 - Expected ':' for break in range", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR116 - Expected ':' for break in range", + exprtk_error_location)); rp.free(); @@ -24670,11 +27846,11 @@ namespace exprtk if (0 == r1) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR108 - Failed parse end section of range", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR117 - Failed parse end section of range", + exprtk_error_location)); rp.free(); @@ -24691,15 +27867,15 @@ namespace exprtk rp.cache.second = rp.n1_c.second; } - free_node(node_allocator_,r1); + free_node(node_allocator_, r1); if (r1_value < T(0)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR109 - Range upper bound less than zero! Constraint: r1 >= 0", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", + exprtk_error_location)); rp.free(); @@ -24714,11 +27890,11 @@ namespace exprtk if (!token_is(token_t::e_rsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR110 - Expected ']' for start of range", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR119 - Expected ']' for start of range", + exprtk_error_location)); rp.free(); @@ -24742,11 +27918,11 @@ namespace exprtk if (!rp_result || (r0 > r1)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR111 - Invalid range, Constraint: r0 <= r1", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR120 - Invalid range, Constraint: r0 <= r1", + exprtk_error_location)); return false; } @@ -24786,11 +27962,11 @@ namespace exprtk if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR112 - Unknown string symbol", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR121 - Unknown string symbol", + exprtk_error_location)); return error_node(); } @@ -24826,7 +28002,7 @@ namespace exprtk if (const_str_node) { - free_node(node_allocator_,result); + free_node(node_allocator_, result); return expression_generator_(T(const_str_node->size())); } @@ -24839,13 +28015,13 @@ namespace exprtk if (!parse_range(rp)) { - free_node(node_allocator_,result); + free_node(node_allocator_, result); return error_node(); } else if (const_str_node) { - free_node(node_allocator_,result); + free_node(node_allocator_, result); result = expression_generator_(const_str_node->ref(),rp); } else @@ -24882,7 +28058,7 @@ namespace exprtk next_token(); next_token(); - free_node(node_allocator_,result); + free_node(node_allocator_, result); return expression_generator_(T(const_str.size())); } @@ -24891,13 +28067,13 @@ namespace exprtk if (!parse_range(rp)) { - free_node(node_allocator_,result); + free_node(node_allocator_, result); rp.free(); return error_node(); } - free_node(node_allocator_,result); + free_node(node_allocator_, result); if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits::max())) { @@ -24910,13 +28086,13 @@ namespace exprtk (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR113 - Overflow in range for string: '" + const_str + "'[" + - (rp.n0_c.first ? details::to_str(static_cast(rp.n0_c.second)) : "?") + ":" + - (rp.n1_c.first ? details::to_str(static_cast(rp.n1_c.second)) : "?") + "]", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR122 - Overflow in range for string: '" + const_str + "'[" + + (rp.n0_c.first ? details::to_str(static_cast(rp.n0_c.second)) : "?") + ":" + + (rp.n1_c.first ? details::to_str(static_cast(rp.n1_c.second)) : "?") + "]", + exprtk_error_location)); rp.free(); @@ -24940,30 +28116,60 @@ namespace exprtk } #endif + inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") + { + expression_node_ptr index_expr = error_node(); + + if (0 == (index_expr = parse_expression())) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR123 - Failed to parse index for vector: '" + vector_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_rsqrbracket)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", + exprtk_error_location)); + + free_node(node_allocator_, index_expr); + + return error_node(); + } + + return index_expr; + } + inline expression_node_ptr parse_vector() { - const std::string symbol = current_token().value; + const std::string vector_name = current_token().value; vector_holder_ptr vec = vector_holder_ptr(0); - const scope_element& se = sem_.get_active_element(symbol); + const scope_element& se = sem_.get_active_element(vector_name); if ( - !details::imatch(se.name, symbol) || + !details::imatch(se.name, vector_name) || (se.depth > state_.scope_depth) || (scope_element::e_vector != se.type) ) { typedef typename symtab_store::vector_context vec_ctxt_t; - vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(symbol); + vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); if (0 == vec_ctx.vector_holder) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR114 - Symbol '" + symbol+ " not a vector", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR125 - Symbol '" + vector_name + " not a vector", + exprtk_error_location)); return error_node(); } @@ -24981,12 +28187,12 @@ namespace exprtk } } else + { vec = se.vec_node; + } assert(0 != vec); - expression_node_ptr index_expr = error_node(); - next_token(); if (!token_is(token_t::e_lsqrbracket)) @@ -24995,31 +28201,28 @@ namespace exprtk } else if (token_is(token_t::e_rsqrbracket)) { - return expression_generator_(T(vec->size())); + return (vec->rebaseable()) ? + node_allocator_.allocate(vec) : + expression_generator_(T(vec->size())); } - else if (0 == (index_expr = parse_expression())) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR115 - Failed to parse index for vector: '" + symbol + "'", - exprtk_error_location)); - return error_node(); - } - else if (!token_is(token_t::e_rsqrbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR116 - Expected ']' for index of vector: '" + symbol + "'", - exprtk_error_location)); + expression_node_ptr index_expr = parse_vector_index(vector_name); - free_node(node_allocator_,index_expr); + if (index_expr) + { + expression_node_ptr vec_node = node_allocator_.allocate(vec); - return error_node(); + return synthesize_vector_element(vector_name, vec, vec_node, index_expr); } + return error_node(); + } + + inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, + vector_holder_ptr vec, + expression_node_ptr vec_node, + expression_node_ptr index_expr) + { // Perform compile-time range check if (details::is_constant_node(index_expr)) { @@ -25028,20 +28231,21 @@ namespace exprtk if (index >= vec_size) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR117 - Index of " + details::to_str(index) + " out of range for " - "vector '" + symbol + "' of size " + details::to_str(vec_size), - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR126 - Index of " + details::to_str(index) + " out of range for " + "vector '" + vector_name + "' of size " + details::to_str(vec_size), + exprtk_error_location)); - free_node(node_allocator_,index_expr); + free_node(node_allocator_, vec_node ); + free_node(node_allocator_, index_expr); return error_node(); } } - return expression_generator_.vector_element(symbol, vec, index_expr); + return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); } inline expression_node_ptr parse_vararg_function_call(ivararg_function* vararg_function, const std::string& vararg_function_name) @@ -25060,12 +28264,12 @@ namespace exprtk { if (!vararg_function->allow_zero_parameters()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR118 - Zero parameter call to vararg function: " - + vararg_function_name + " not allowed", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR127 - Zero parameter call to vararg function: " + + vararg_function_name + " not allowed", + exprtk_error_location)); return error_node(); } @@ -25085,12 +28289,12 @@ namespace exprtk break; else if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR119 - Expected ',' for call to vararg function: " - + vararg_function_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR128 - Expected ',' for call to vararg function: " + + vararg_function_name, + exprtk_error_location)); return error_node(); } @@ -25099,37 +28303,37 @@ namespace exprtk } else if (!vararg_function->allow_zero_parameters()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR120 - Zero parameter call to vararg function: " - + vararg_function_name + " not allowed", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR129 - Zero parameter call to vararg function: " + + vararg_function_name + " not allowed", + exprtk_error_location)); return error_node(); } if (arg_list.size() < vararg_function->min_num_args()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR121 - Invalid number of parameters to call to vararg function: " - + vararg_function_name + ", require at least " - + details::to_str(static_cast(vararg_function->min_num_args())) + " parameters", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR130 - Invalid number of parameters to call to vararg function: " + + vararg_function_name + ", require at least " + + details::to_str(static_cast(vararg_function->min_num_args())) + " parameters", + exprtk_error_location)); return error_node(); } else if (arg_list.size() > vararg_function->max_num_args()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR122 - Invalid number of parameters to call to vararg function: " - + vararg_function_name + ", require no more than " - + details::to_str(static_cast(vararg_function->max_num_args())) + " parameters", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR131 - Invalid number of parameters to call to vararg function: " + + vararg_function_name + ", require no more than " + + details::to_str(static_cast(vararg_function->max_num_args())) + " parameters", + exprtk_error_location)); return error_node(); } @@ -25200,14 +28404,13 @@ namespace exprtk if (1 == error_list.size()) { - parser_. - set_error( - make_error(parser_error::e_syntax, - parser_.current_token(), - "ERR123 - Failed parameter type check for function '" + function_name_ + "', " - "Expected '" + function_definition_list_[0].param_seq + - "' call set: '" + param_seq + "'", - exprtk_error_location)); + parser_.set_error(make_error( + parser_error::e_syntax, + parser_.current_token(), + "ERR132 - Failed parameter type check for function '" + function_name_ + "', " + "Expected '" + function_definition_list_[0].param_seq + + "' call set: '" + param_seq + "'", + exprtk_error_location)); } else { @@ -25222,14 +28425,13 @@ namespace exprtk } } - parser_. - set_error( - make_error(parser_error::e_syntax, - parser_.current_token(), - "ERR124 - Failed parameter type check for function '" + function_name_ + "', " - "Best match: '" + function_definition_list_[max_diff_index].param_seq + - "' call set: '" + param_seq + "'", - exprtk_error_location)); + parser_.set_error(make_error( + parser_error::e_syntax, + parser_.current_token(), + "ERR133 - Failed parameter type check for function '" + function_name_ + "', " + "Best match: '" + function_definition_list_[max_diff_index].param_seq + + "' call set: '" + param_seq + "'", + exprtk_error_location)); } return false; @@ -25364,13 +28566,12 @@ namespace exprtk { invalid_state_ = false; - parser_. - set_error( - make_error(parser_error::e_syntax, - parser_.current_token(), - "ERR125 - Invalid parameter sequence of '" + param_seq_list[i] + - "' for function: " + function_name_, - exprtk_error_location)); + parser_.set_error(make_error( + parser_error::e_syntax, + parser_.current_token(), + "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + + "' for function: " + function_name_, + exprtk_error_location)); return; } @@ -25380,15 +28581,14 @@ namespace exprtk { invalid_state_ = false; - parser_. - set_error( - make_error(parser_error::e_syntax, - parser_.current_token(), - "ERR126 - Function '" + function_name_ + "' has a parameter sequence conflict between " + - "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + - "pseq_idx[" + details::to_str(i) + "] " + - "param seq: " + param_seq_list[i], - exprtk_error_location)); + parser_.set_error(make_error( + parser_error::e_syntax, + parser_.current_token(), + "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + + "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + + "pseq_idx[" + details::to_str(i) + "] " + + "param seq: " + param_seq_list[i], + exprtk_error_location)); return; } @@ -25424,11 +28624,11 @@ namespace exprtk if (tc.invalid()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR127 - Type checker instantiation failure for generic function: " + function_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR136 - Type checker instantiation failure for generic function: " + function_name, + exprtk_error_location)); return error_node(); } @@ -25442,12 +28642,12 @@ namespace exprtk !tc .allow_zero_parameters() ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR128 - Zero parameter call to generic function: " - + function_name + " not allowed", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR137 - Zero parameter call to generic function: " + + function_name + " not allowed", + exprtk_error_location)); return error_node(); } @@ -25474,11 +28674,11 @@ namespace exprtk break; else if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR129 - Expected ',' for call to generic function: " + function_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR138 - Expected ',' for call to generic function: " + function_name, + exprtk_error_location)); return error_node(); } @@ -25491,12 +28691,12 @@ namespace exprtk !tc .allow_zero_parameters () ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR130 - Zero parameter call to generic function: " - + function_name + " not allowed", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR139 - Zero parameter call to generic function: " + + function_name + " not allowed", + exprtk_error_location)); return error_node(); } @@ -25508,22 +28708,21 @@ namespace exprtk !tc.verify(param_type_list, param_seq_index) ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR131 - Invalid input parameter sequence for call to generic function: " + function_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, + exprtk_error_location)); return error_node(); } expression_node_ptr result = error_node(); - if (tc.paramseq_count() <= 1) - result = expression_generator_ - .generic_function_call(function, arg_list); - else - result = expression_generator_ + result = (tc.paramseq_count() <= 1) ? + expression_generator_ + .generic_function_call(function, arg_list) : + expression_generator_ .generic_function_call(function, arg_list, param_seq_index); sdd.delete_ptr = (0 == result); @@ -25546,12 +28745,12 @@ namespace exprtk !tc .allow_zero_parameters() ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR132 - Zero parameter call to generic function: " - + function_name + " not allowed", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR141 - Zero parameter call to generic function: " + + function_name + " not allowed", + exprtk_error_location)); return false; } @@ -25578,11 +28777,11 @@ namespace exprtk break; else if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR133 - Expected ',' for call to string function: " + function_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR142 - Expected ',' for call to string function: " + function_name, + exprtk_error_location)); return false; } @@ -25625,22 +28824,21 @@ namespace exprtk if (!tc.verify(param_type_list, param_seq_index)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR134 - Invalid input parameter sequence for call to string function: " + function_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, + exprtk_error_location)); return error_node(); } expression_node_ptr result = error_node(); - if (tc.paramseq_count() <= 1) - result = expression_generator_ - .string_function_call(function, arg_list); - else - result = expression_generator_ + result = (tc.paramseq_count() <= 1) ? + expression_generator_ + .string_function_call(function, arg_list) : + expression_generator_ .string_function_call(function, arg_list, param_seq_index); sdd.delete_ptr = (0 == result); @@ -25677,11 +28875,11 @@ namespace exprtk if (!tc.verify(param_type_list, param_seq_index)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR135 - Invalid input parameter sequence for call to overloaded function: " + function_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, + exprtk_error_location)); return error_node(); } @@ -25708,11 +28906,11 @@ namespace exprtk } else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR136 - Invalid return type for call to overloaded function: " + function_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR145 - Invalid return type for call to overloaded function: " + function_name, + exprtk_error_location)); } sdd.delete_ptr = (0 == result); @@ -25736,11 +28934,11 @@ namespace exprtk if (!p.token_is(token_t::e_lbracket)) { - p.set_error( - make_error(parser_error::e_syntax, - p.current_token(), - "ERR137 - Expected '(' for special function '" + sf_name + "'", - exprtk_error_location)); + p.set_error(make_error( + parser_error::e_syntax, + p.current_token(), + "ERR146 - Expected '(' for special function '" + sf_name + "'", + exprtk_error_location)); return error_node(); } @@ -25757,11 +28955,11 @@ namespace exprtk { if (!p.token_is(token_t::e_comma)) { - p.set_error( - make_error(parser_error::e_syntax, - p.current_token(), - "ERR138 - Expected ',' before next parameter of special function '" + sf_name + "'", - exprtk_error_location)); + p.set_error(make_error( + parser_error::e_syntax, + p.current_token(), + "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", + exprtk_error_location)); return p.error_node(); } @@ -25770,11 +28968,11 @@ namespace exprtk if (!p.token_is(token_t::e_rbracket)) { - p.set_error( - make_error(parser_error::e_syntax, - p.current_token(), - "ERR139 - Invalid number of parameters for special function '" + sf_name + "'", - exprtk_error_location)); + p.set_error(make_error( + parser_error::e_syntax, + p.current_token(), + "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", + exprtk_error_location)); return p.error_node(); } @@ -25797,11 +28995,11 @@ namespace exprtk !details::is_digit(sf_name[3]) ) { - set_error( - make_error(parser_error::e_token, - current_token(), - "ERR140 - Invalid special function[1]: " + sf_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_token, + current_token(), + "ERR149 - Invalid special function[1]: " + sf_name, + exprtk_error_location)); return error_node(); } @@ -25811,11 +29009,11 @@ namespace exprtk if (id >= details::e_sffinal) { - set_error( - make_error(parser_error::e_token, - current_token(), - "ERR141 - Invalid special function[2]: " + sf_name, - exprtk_error_location)); + set_error(make_error( + parser_error::e_token, + current_token(), + "ERR150 - Invalid special function[2]: " + sf_name, + exprtk_error_location)); return error_node(); } @@ -25843,21 +29041,21 @@ namespace exprtk { if (state_.parsing_break_stmt) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR142 - Invoking 'break' within a break call is not allowed", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR151 - Invoking 'break' within a break call is not allowed", + exprtk_error_location)); return error_node(); } else if (0 == state_.parsing_loop_stmt_count) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR143 - Invalid use of 'break', allowed only in the scope of a loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", + exprtk_error_location)); return error_node(); } @@ -25876,23 +29074,23 @@ namespace exprtk { if (0 == (return_expr = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR144 - Failed to parse return expression for 'break' statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR153 - Failed to parse return expression for 'break' statement", + exprtk_error_location)); return error_node(); } else if (!token_is(token_t::e_rsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR145 - Expected ']' at the completion of break's return expression", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR154 - Expected ']' at the completion of break's return expression", + exprtk_error_location)); - free_node(node_allocator_,return_expr); + free_node(node_allocator_, return_expr); return error_node(); } @@ -25904,11 +29102,11 @@ namespace exprtk } else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR146 - Invalid use of 'break', allowed only in the scope of a loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", + exprtk_error_location)); } return error_node(); @@ -25918,11 +29116,11 @@ namespace exprtk { if (0 == state_.parsing_loop_stmt_count) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR147 - Invalid use of 'continue', allowed only in the scope of a loop", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", + exprtk_error_location)); return error_node(); } @@ -25940,123 +29138,222 @@ namespace exprtk inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) { - expression_node_ptr size_expr = error_node(); + expression_node_ptr size_expression_node = error_node(); if (!token_is(token_t::e_lsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR148 - Expected '[' as part of vector size definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR157 - Expected '[' as part of vector size definition", + exprtk_error_location)); return error_node(); } - else if (0 == (size_expr = parse_expression())) + else if (0 == (size_expression_node = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR149 - Failed to determine size of vector '" + vec_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR158 - Failed to determine size of vector '" + vec_name + "'", + exprtk_error_location)); return error_node(); } - else if (!is_constant_node(size_expr)) + else if (!is_constant_node(size_expression_node)) { - free_node(node_allocator_,size_expr); + const bool is_rebaseble_vector = + (size_expression_node->type() == details::expression_node::e_vecsize) && + static_cast*>(size_expression_node)->vec_holder()->rebaseable(); - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR150 - Expected a literal number as size of vector '" + vec_name + "'", - exprtk_error_location)); + free_node(node_allocator_, size_expression_node); + + const std::string error_msg = (is_rebaseble_vector) ? + std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : + std::string("Expected a constant literal number as size of vector"); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR159 - " + error_msg + " '" + vec_name + "'", + exprtk_error_location)); return error_node(); } - const T vector_size = size_expr->value(); + const T vector_size = size_expression_node->value(); - free_node(node_allocator_,size_expr); + free_node(node_allocator_, size_expression_node); - const T max_vector_size = T(2000000000.0); + const std::size_t max_vector_size = settings_.max_local_vector_size(); if ( (vector_size <= T(0)) || std::not_equal_to() (T(0),vector_size - details::numeric::trunc(vector_size)) || - (vector_size > max_vector_size) + (static_cast(vector_size) > max_vector_size) ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR151 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + - details::to_str(details::numeric::to_int32(vector_size)), - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR160 - Invalid vector size. Must be an integer in the " + "range [0," + details::to_str(static_cast(max_vector_size)) + "], size: " + + details::to_str(details::numeric::to_int32(vector_size)), + exprtk_error_location)); return error_node(); } + typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); + + const std::size_t vec_size = static_cast(details::numeric::to_int32(vector_size)); + + scope_element& se = sem_.get_element(vec_name); + + if (se.name == vec_name) + { + if (se.active) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR161 - Illegal redefinition of local vector: '" + vec_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if ( + (se.size == vec_size) && + (scope_element::e_vector == se.type) + ) + { + vec_holder = se.vec_node; + se.active = true; + se.depth = state_.scope_depth; + se.ref_count++; + } + } + + if (0 == vec_holder) + { + scope_element nse; + nse.name = vec_name; + nse.active = true; + nse.ref_count = 1; + nse.type = scope_element::e_vector; + nse.depth = state_.scope_depth; + nse.size = vec_size; + nse.data = new T[vec_size]; + nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast(nse.data),nse.size); + + details::set_zero_value(reinterpret_cast(nse.data),vec_size); + + if (!sem_.add_element(nse)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR162 - Failed to add new local vector '" + vec_name + "' to SEM", + exprtk_error_location)); + + sem_.free_element(nse); + + return error_node(); + } + + vec_holder = nse.vec_node; + + exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", + nse.name.c_str(), + static_cast(nse.size))); + } + + state_.activate_side_effect("parse_define_vector_statement()"); + + lodge_symbol(vec_name, e_st_local_vector); + std::vector vec_initilizer_list; scoped_vec_delete svd((*this),vec_initilizer_list); bool single_value_initialiser = false; + bool range_value_initialiser = false; bool vec_to_vec_initialiser = false; bool null_initialisation = false; if (!token_is(token_t::e_rsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR152 - Expected ']' as part of vector size definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR163 - Expected ']' as part of vector size definition", + exprtk_error_location)); return error_node(); } - else if (!token_is(token_t::e_eof)) + else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) { if (!token_is(token_t::e_assign)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR153 - Expected ':=' as part of vector definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR164 - Expected ':=' as part of vector definition", + exprtk_error_location)); return error_node(); } else if (token_is(token_t::e_lsqrbracket)) { - expression_node_ptr initialiser = parse_expression(); + expression_node_ptr initialiser_component = parse_expression(); - if (0 == initialiser) + if (0 == initialiser_component) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR154 - Failed to parse single vector initialiser", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR165 - Failed to parse first component of vector initialiser for vector: " + vec_name, + exprtk_error_location)); return error_node(); } - vec_initilizer_list.push_back(initialiser); + vec_initilizer_list.push_back(initialiser_component); + + if (token_is(token_t::e_colon)) + { + initialiser_component = parse_expression(); + + if (0 == initialiser_component) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR166 - Failed to parse second component of vector initialiser for vector: " + vec_name, + exprtk_error_location)); + + return error_node(); + } + + vec_initilizer_list.push_back(initialiser_component); + } if (!token_is(token_t::e_rsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR155 - Expected ']' to close single value vector initialiser", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR167 - Expected ']' to close single value vector initialiser", + exprtk_error_location)); return error_node(); } - single_value_initialiser = true; + switch (vec_initilizer_list.size()) + { + case 1 : single_value_initialiser = true; break; + case 2 : range_value_initialiser = true; break; + } } else if (!token_is(token_t::e_lcrlbracket)) { @@ -26066,9 +29363,9 @@ namespace exprtk if (token_t::e_symbol == current_token().type) { // Is it a locally defined vector? - const scope_element& se = sem_.get_active_element(current_token().value); + const scope_element& lcl_se = sem_.get_active_element(current_token().value); - if (scope_element::e_vector == se.type) + if (scope_element::e_vector == lcl_se.type) { if (0 != (initialiser = parse_expression())) vec_initilizer_list.push_back(initialiser); @@ -26094,11 +29391,11 @@ namespace exprtk { if (0 == initialiser) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR156 - Expected '{' as part of vector initialiser list", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR168 - Expected '{' as part of vector initialiser list", + exprtk_error_location)); return error_node(); } @@ -26114,11 +29411,11 @@ namespace exprtk if (0 == initialiser) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR157 - Expected '{' as part of vector initialiser list", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR169 - Expected '{' as part of vector initialiser list", + exprtk_error_location)); return error_node(); } @@ -26132,11 +29429,11 @@ namespace exprtk if (!token_is(token_t::e_comma) && is_next_close) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR158 - Expected ',' between vector initialisers", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR170 - Expected ',' between vector initialisers", + exprtk_error_location)); return error_node(); } @@ -26152,99 +29449,118 @@ namespace exprtk !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) ) { - if (!token_is(token_t::e_eof)) + if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR159 - Expected ';' at end of vector definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR171 - Expected ';' at end of vector definition", + exprtk_error_location)); return error_node(); } } - if (T(vec_initilizer_list.size()) > vector_size) + if ( + !single_value_initialiser && + !range_value_initialiser && + (T(vec_initilizer_list.size()) > vector_size) + ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR160 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR172 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", + exprtk_error_location)); return error_node(); } } - typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); - - const std::size_t vec_size = static_cast(details::numeric::to_int32(vector_size)); - - scope_element& se = sem_.get_element(vec_name); + expression_node_ptr result = error_node(); - if (se.name == vec_name) + if ( + (vec_initilizer_list.size() == 1) && + single_value_initialiser + ) { - if (se.active) + if (details::is_constant_node(vec_initilizer_list[0])) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR161 - Illegal redefinition of local vector: '" + vec_name + "'", - exprtk_error_location)); - - return error_node(); + // vector_init_zero_value_node var v[10] := [0] + if (T(0) == vec_initilizer_list[0]->value()) + { + result = node_allocator_ + .allocate >( + (*vec_holder)[0], + vec_size, + vec_initilizer_list); + } + else + { + // vector_init_single_constvalue_node var v[10] := [123] + result = node_allocator_ + .allocate >( + (*vec_holder)[0], + vec_size, + vec_initilizer_list); + } } - else if ( - (se.size == vec_size) && - (scope_element::e_vector == se.type) - ) + else { - vec_holder = se.vec_node; - se.active = true; - se.depth = state_.scope_depth; - se.ref_count++; + // vector_init_single_value_node var v[10] := [123 + (x / y)] + result = node_allocator_ + .allocate >( + (*vec_holder)[0], + vec_size, + vec_initilizer_list); } } - - if (0 == vec_holder) + else if ( + (vec_initilizer_list.size() == 2) && + range_value_initialiser + ) { - scope_element nse; - nse.name = vec_name; - nse.active = true; - nse.ref_count = 1; - nse.type = scope_element::e_vector; - nse.depth = state_.scope_depth; - nse.size = vec_size; - nse.data = new T[vec_size]; - nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast(nse.data),nse.size); + bool base_const = details::is_constant_node(vec_initilizer_list[0]); + bool inc_const = details::is_constant_node(vec_initilizer_list[1]); - if (!sem_.add_element(nse)) + if (base_const && inc_const) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR162 - Failed to add new local vector '" + vec_name + "' to SEM", - exprtk_error_location)); - - sem_.free_element(nse); - - return error_node(); + // vector_init_single_value_node var v[10] := [1 : 3.5] + result = node_allocator_ + .allocate >( + (*vec_holder)[0], + vec_size, + vec_initilizer_list); + } + else if (base_const && !inc_const) + { + // vector_init_single_value_node var v[10] := [1 : x + y] + result = node_allocator_ + .allocate >( + (*vec_holder)[0], + vec_size, + vec_initilizer_list); + } + else if (!base_const && inc_const) + { + // vector_init_single_value_node var v[10] := [x + y : 3] + result = node_allocator_ + .allocate >( + (*vec_holder)[0], + vec_size, + vec_initilizer_list); + } + else if (!base_const && !inc_const) + { + // vector_init_single_value_node var v[10] := [x + y : z / w] + result = node_allocator_ + .allocate >( + (*vec_holder)[0], + vec_size, + vec_initilizer_list); } - - vec_holder = nse.vec_node; - - exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", - nse.name.c_str(), - static_cast(nse.size))); } - - state_.activate_side_effect("parse_define_vector_statement()"); - - lodge_symbol(vec_name, e_st_local_vector); - - expression_node_ptr result = error_node(); - - if (null_initialisation) + else if (null_initialisation) result = expression_generator_(T(0.0)); else if (vec_to_vec_initialiser) { @@ -26256,16 +29572,31 @@ namespace exprtk vec_initilizer_list[0]); } else + { result = node_allocator_ - .allocate >( + .allocate >( (*vec_holder)[0], vec_size, vec_initilizer_list, single_value_initialiser); + } - svd.delete_ptr = (0 == result); + svd.delete_ptr = false; - return result; + if (result && result->valid()) + { + return result; + } + + details::free_node(node_allocator_, result); + + set_error(make_error( + parser_error::e_synthesis, + current_token(), + "ERR173 - Failed to generate initialisation node for vector: " + vec_name, + exprtk_error_location)); + + return error_node(); } #ifndef exprtk_disable_string_capabilities @@ -26279,13 +29610,13 @@ namespace exprtk { if (se.active) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR163 - Illegal redefinition of local variable: '" + str_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR174 - Illegal redefinition of local variable: '" + str_name + "'", + exprtk_error_location)); - free_node(node_allocator_,initialisation_expression); + free_node(node_allocator_, initialisation_expression); return error_node(); } @@ -26311,13 +29642,13 @@ namespace exprtk if (!sem_.add_element(nse)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR164 - Failed to add new local string variable '" + str_name + "' to SEM", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR175 - Failed to add new local string variable '" + str_name + "' to SEM", + exprtk_error_location)); - free_node(node_allocator_,initialisation_expression); + free_node(node_allocator_, initialisation_expression); sem_.free_element(nse); @@ -26326,7 +29657,7 @@ namespace exprtk str_node = nse.str_node; - exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str())); + exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); } lodge_symbol(str_name, e_st_local_string); @@ -26357,11 +29688,11 @@ namespace exprtk { if (settings_.vardef_disabled()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR165 - Illegal variable definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR176 - Illegal variable definition", + exprtk_error_location)); return error_node(); } @@ -26378,41 +29709,41 @@ namespace exprtk if (!token_is(token_t::e_symbol)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR166 - Expected a symbol for variable definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR177 - Expected a symbol for variable definition", + exprtk_error_location)); return error_node(); } else if (details::is_reserved_symbol(var_name)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR167 - Illegal redefinition of reserved keyword: '" + var_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR178 - Illegal redefinition of reserved keyword: '" + var_name + "'", + exprtk_error_location)); return error_node(); } else if (symtab_store_.symbol_exists(var_name)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR168 - Illegal redefinition of variable '" + var_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR179 - Illegal redefinition of variable '" + var_name + "'", + exprtk_error_location)); return error_node(); } else if (local_variable_is_shadowed(var_name)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR169 - Illegal redefinition of local variable: '" + var_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR180 - Illegal redefinition of local variable: '" + var_name + "'", + exprtk_error_location)); return error_node(); } @@ -26428,11 +29759,11 @@ namespace exprtk { if (0 == (initialisation_expression = parse_expression())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR170 - Failed to parse initialisation expression", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR181 - Failed to parse initialisation expression for variable '" + var_name + "'", + exprtk_error_location)); return error_node(); } @@ -26446,13 +29777,13 @@ namespace exprtk { if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR171 - Expected ';' after variable definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR182 - Expected ';' after variable '" + var_name + "' definition", + exprtk_error_location)); - free_node(node_allocator_,initialisation_expression); + free_node(node_allocator_, initialisation_expression); return error_node(); } @@ -26474,11 +29805,11 @@ namespace exprtk { if (se.active) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR172 - Illegal redefinition of local variable: '" + var_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR183 - Illegal redefinition of local variable: '" + var_name + "'", + exprtk_error_location)); free_node(node_allocator_, initialisation_expression); @@ -26506,11 +29837,11 @@ namespace exprtk if (!sem_.add_element(nse)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR173 - Failed to add new local variable '" + var_name + "' to SEM", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR184 - Failed to add new local variable '" + var_name + "' to SEM", + exprtk_error_location)); free_node(node_allocator_, initialisation_expression); @@ -26521,7 +29852,7 @@ namespace exprtk var_node = nse.var_node; - exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str())); + exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); } state_.activate_side_effect("parse_define_var_statement()"); @@ -26536,6 +29867,174 @@ namespace exprtk return expression_generator_(details::e_assign,branch); } + inline expression_node_ptr parse_define_constvar_statement() + { + if (settings_.vardef_disabled()) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR185 - Illegal const variable definition", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is("const")) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR186 - Expected 'const' keyword for const-variable definition", + exprtk_error_location)); + + return error_node(); + } + else if (!token_is("var")) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR187 - Expected 'var' keyword for const-variable definition", + exprtk_error_location)); + + return error_node(); + } + + const std::string var_name = current_token().value; + + expression_node_ptr initialisation_expression = error_node(); + + if (!token_is(token_t::e_symbol)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR188 - Expected a symbol for const-variable definition", + exprtk_error_location)); + + return error_node(); + } + else if (details::is_reserved_symbol(var_name)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR189 - Illegal redefinition of reserved keyword: '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (symtab_store_.symbol_exists(var_name)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR190 - Illegal redefinition of variable '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (local_variable_is_shadowed(var_name)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR191 - Illegal redefinition of local variable: '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (token_is(token_t::e_assign)) + { + if (0 == (initialisation_expression = parse_expression())) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR192 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (!details::is_literal_node(initialisation_expression)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR193 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", + exprtk_error_location)); + + free_node(node_allocator_, initialisation_expression); + + return error_node(); + } + } + + const T init_value = initialisation_expression->value(); + + free_node(node_allocator_, initialisation_expression); + + expression_node_ptr var_node = reinterpret_cast(0); + + scope_element& se = sem_.get_element(var_name); + + if (se.name == var_name) + { + if (se.active) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR194 - Illegal redefinition of local variable: '" + var_name + "'", + exprtk_error_location)); + + return error_node(); + } + else if (scope_element::e_literal == se.type) + { + var_node = se.var_node; + se.active = true; + se.depth = state_.scope_depth; + se.ref_count++; + } + } + + if (0 == var_node) + { + scope_element nse; + nse.name = var_name; + nse.active = true; + nse.ref_count = 1; + nse.type = scope_element::e_literal; + nse.depth = state_.scope_depth; + nse.data = 0; + nse.var_node = node_allocator_.allocate(init_value); + + if (!sem_.add_element(nse)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR195 - Failed to add new local const-variable '" + var_name + "' to SEM", + exprtk_error_location)); + + sem_.free_element(nse); + + return error_node(); + } + + var_node = nse.var_node; + + exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); + } + + state_.activate_side_effect("parse_define_constvar_statement()"); + + lodge_symbol(var_name, e_st_local_variable); + + return expression_generator_(var_node->value()); + } + inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) { if ( @@ -26543,21 +30042,21 @@ namespace exprtk !token_is(token_t::e_rcrlbracket) ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR174 - Expected a '{}' for uninitialised var definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR196 - Expected a '{}' for uninitialised var definition", + exprtk_error_location)); return error_node(); } else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR175 - Expected ';' after uninitialised variable definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR197 - Expected ';' after uninitialised variable definition", + exprtk_error_location)); return error_node(); } @@ -26570,11 +30069,11 @@ namespace exprtk { if (se.active) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR176 - Illegal redefinition of local variable: '" + var_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR198 - Illegal redefinition of local variable: '" + var_name + "'", + exprtk_error_location)); return error_node(); } @@ -26600,11 +30099,11 @@ namespace exprtk if (!sem_.add_element(nse)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR177 - Failed to add new local variable '" + var_name + "' to SEM", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR199 - Failed to add new local variable '" + var_name + "' to SEM", + exprtk_error_location)); sem_.free_element(nse); @@ -26633,11 +30132,11 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR178 - Expected '(' at start of swap statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR200 - Expected '(' at start of swap statement", + exprtk_error_location)); return error_node(); } @@ -26652,11 +30151,11 @@ namespace exprtk if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR179 - Expected a symbol for variable or vector element definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR201 - Expected a symbol for variable or vector element definition", + exprtk_error_location)); return error_node(); } @@ -26664,11 +30163,11 @@ namespace exprtk { if (0 == (variable0 = parse_vector())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR180 - First parameter to swap is an invalid vector element: '" + var0_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR202 - First parameter to swap is an invalid vector element: '" + var0_name + "'", + exprtk_error_location)); return error_node(); } @@ -26697,11 +30196,11 @@ namespace exprtk if (0 == variable0) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR181 - First parameter to swap is an invalid variable: '" + var0_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR203 - First parameter to swap is an invalid variable: '" + var0_name + "'", + exprtk_error_location)); return error_node(); } @@ -26711,15 +30210,15 @@ namespace exprtk if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR182 - Expected ',' between parameters to swap", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR204 - Expected ',' between parameters to swap", + exprtk_error_location)); if (variable0_generated) { - free_node(node_allocator_,variable0); + free_node(node_allocator_, variable0); } return error_node(); @@ -26729,15 +30228,15 @@ namespace exprtk if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR183 - Expected a symbol for variable or vector element definition", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR205 - Expected a symbol for variable or vector element definition", + exprtk_error_location)); if (variable0_generated) { - free_node(node_allocator_,variable0); + free_node(node_allocator_, variable0); } return error_node(); @@ -26746,15 +30245,15 @@ namespace exprtk { if (0 == (variable1 = parse_vector())) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR184 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR206 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", + exprtk_error_location)); if (variable0_generated) { - free_node(node_allocator_,variable0); + free_node(node_allocator_, variable0); } return error_node(); @@ -26784,15 +30283,15 @@ namespace exprtk if (0 == variable1) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR185 - Second parameter to swap is an invalid variable: '" + var1_name + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR207 - Second parameter to swap is an invalid variable: '" + var1_name + "'", + exprtk_error_location)); if (variable0_generated) { - free_node(node_allocator_,variable0); + free_node(node_allocator_, variable0); } return error_node(); @@ -26803,20 +30302,20 @@ namespace exprtk if (!token_is(token_t::e_rbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR186 - Expected ')' at end of swap statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR208 - Expected ')' at end of swap statement", + exprtk_error_location)); if (variable0_generated) { - free_node(node_allocator_,variable0); + free_node(node_allocator_, variable0); } if (variable1_generated) { - free_node(node_allocator_,variable1); + free_node(node_allocator_, variable1); } return error_node(); @@ -26838,12 +30337,12 @@ namespace exprtk if (variable0_generated) { - free_node(node_allocator_,variable0); + free_node(node_allocator_, variable0); } if (variable1_generated) { - free_node(node_allocator_,variable1); + free_node(node_allocator_, variable1); } } else @@ -26860,11 +30359,11 @@ namespace exprtk { if (state_.parsing_return_stmt) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR187 - Return call within a return call is not allowed", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR209 - Return call within a return call is not allowed", + exprtk_error_location)); return error_node(); } @@ -26884,11 +30383,11 @@ namespace exprtk if (!token_is(token_t::e_lsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR188 - Expected '[' at start of return statement", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR210 - Expected '[' at start of return statement", + exprtk_error_location)); return error_node(); } @@ -26907,11 +30406,11 @@ namespace exprtk break; else if (!token_is(token_t::e_comma)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR189 - Expected ',' between values during call to return", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR211 - Expected ',' between values during call to return", + exprtk_error_location)); return error_node(); } @@ -26919,11 +30418,11 @@ namespace exprtk } else if (settings_.zero_return_disabled()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR190 - Zero parameter return statement not allowed", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR212 - Zero parameter return statement not allowed", + exprtk_error_location)); return error_node(); } @@ -26934,11 +30433,11 @@ namespace exprtk { if (!arg_list.empty()) { - set_error( - make_error(parser_error::e_syntax, - prev_token, - "ERR191 - Invalid ']' found during return call", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + prev_token, + "ERR213 - Invalid ']' found during return call", + exprtk_error_location)); return error_node(); } @@ -26977,6 +30476,194 @@ namespace exprtk } #endif + inline expression_node_ptr parse_assert_statement() + { + assert(details::imatch(current_token().value, "assert")); + + if (state_.parsing_assert_stmt) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR214 - Assert statement within an assert statement is not allowed", + exprtk_error_location)); + + return error_node(); + } + + scoped_bool_negator sbn(state_.parsing_assert_stmt); + + next_token(); + + std::vector assert_arg_list(3, error_node()); + scoped_vec_delete sdd((*this), assert_arg_list); + + expression_node_ptr& assert_condition = assert_arg_list[0]; + expression_node_ptr& assert_message = assert_arg_list[1]; + expression_node_ptr& assert_id = assert_arg_list[2]; + + if (!token_is(token_t::e_lbracket)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR215 - Expected '(' at start of assert statement", + exprtk_error_location)); + + return error_node(); + } + + const token_t start_token = current_token(); + + // Parse the assert condition + if (0 == (assert_condition = parse_expression())) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR216 - Failed to parse condition for assert statement", + exprtk_error_location)); + + return error_node(); + } + + const token_t end_token = current_token(); + + if (!token_is(token_t::e_rbracket)) + { + if (!token_is(token_t::e_comma)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR217 - Expected ',' between condition and message for assert statement", + exprtk_error_location)); + + return error_node(); + } + // Parse the assert message + else if ( + (0 == (assert_message = parse_expression())) || + !details::is_generally_string_node(assert_message) + ) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR218 - " + + (assert_message ? + std::string("Expected string for assert message") : + std::string("Failed to parse message for assert statement")), + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_rbracket)) + { + if (!token_is(token_t::e_comma)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR219 - Expected ',' between message and ID for assert statement", + exprtk_error_location)); + + return error_node(); + } + // Parse assert ID + else if ( + (0 == (assert_id = parse_expression())) || + !details::is_const_string_node(assert_id) + ) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR220 - " + + (assert_id ? + std::string("Expected literal string for assert ID") : + std::string("Failed to parse string for assert ID")), + exprtk_error_location)); + + return error_node(); + } + else if (!token_is(token_t::e_rbracket)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR221 - Expected ')' at start of assert statement", + exprtk_error_location)); + + return error_node(); + } + } + } + + exprtk::assert_check::assert_context context; + context.condition = lexer().substr(start_token.position, end_token.position); + context.offet = start_token.position; + + if (0 == assert_check_) + { + exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", + context.condition.c_str())); + + return new details::null_node(); + } + + #ifndef exprtk_disable_string_capabilities + if (assert_message && details::is_const_string_node(assert_message)) + { + context.message = dynamic_cast*>(assert_message)->str(); + } + + if (assert_id && details::is_const_string_node(assert_id)) + { + context.id = dynamic_cast*>(assert_id)->str(); + + if (assert_ids_.end() != assert_ids_.find(context.id)) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR222 - Duplicate assert ID: " + context.id, + exprtk_error_location)); + + return error_node(); + } + + assert_ids_.insert(context.id); + free_node(node_allocator_, assert_id); + } + #endif + + expression_node_ptr result_node = + expression_generator_.assert_call( + assert_condition, + assert_message, + context); + + exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); + exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); + exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); + exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast(context.offet))); + + if (0 == result_node) + { + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR223 - Failed to synthesize assert", + exprtk_error_location)); + + return error_node(); + } + + sdd.delete_ptr = false; + return result_node; + } + inline bool post_variable_process(const std::string& symbol) { if ( @@ -26987,11 +30674,11 @@ namespace exprtk { if (!settings_.commutative_check_enabled()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR192 - Invalid sequence of variable '" + symbol + "' and bracket", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR224 - Invalid sequence of variable '" + symbol + "' and bracket", + exprtk_error_location)); return false; } @@ -27009,23 +30696,26 @@ namespace exprtk if (details::is_generally_string_node(branch)) return true; + if (details::is_ivector_node(branch)) + return true; + const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; switch (token) { - case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || - token_is(token_t::e_lcrlbracket,hold) || - token_is(token_t::e_lsqrbracket,hold) ; + case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || + token_is(token_t::e_lcrlbracket, hold) || + token_is(token_t::e_lsqrbracket, hold) ; break; - case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || - token_is(token_t::e_lcrlbracket,hold) || - token_is(token_t::e_lsqrbracket,hold) ; + case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || + token_is(token_t::e_lcrlbracket, hold) || + token_is(token_t::e_lsqrbracket, hold) ; break; - case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || - token_is(token_t::e_lcrlbracket,hold) || - token_is(token_t::e_lsqrbracket,hold) ; + case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || + token_is(token_t::e_lcrlbracket, hold) || + token_is(token_t::e_lsqrbracket, hold) ; break; default : return true; @@ -27035,11 +30725,11 @@ namespace exprtk { if (!settings_.commutative_check_enabled()) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR193 - Invalid sequence of brackets", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR225 - Invalid sequence of brackets", + exprtk_error_location)); return false; } @@ -27122,7 +30812,10 @@ namespace exprtk if (se.active && details::imatch(se.name, symbol)) { - if (scope_element::e_variable == se.type) + if ( + (scope_element::e_variable == se.type) || + (scope_element::e_literal == se.type) + ) { se.active = true; lodge_symbol(symbol, e_st_local_variable); @@ -27132,7 +30825,9 @@ namespace exprtk next_token(); - return se.var_node; + return (scope_element::e_variable == se.type) ? + se.var_node : + expression_generator_(se.var_node->value()); } else if (scope_element::e_vector == se.type) { @@ -27170,11 +30865,11 @@ namespace exprtk return func_node; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR194 - Failed to generate node for function: '" + symbol + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR226 - Failed to generate node for function: '" + symbol + "'", + exprtk_error_location)); return error_node(); } @@ -27196,11 +30891,11 @@ namespace exprtk return vararg_func_node; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR195 - Failed to generate node for vararg function: '" + symbol + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR227 - Failed to generate node for vararg function: '" + symbol + "'", + exprtk_error_location)); return error_node(); } @@ -27222,11 +30917,11 @@ namespace exprtk return genericfunc_node; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR196 - Failed to generate node for generic function: '" + symbol + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR228 - Failed to generate node for generic function: '" + symbol + "'", + exprtk_error_location)); return error_node(); } @@ -27249,11 +30944,11 @@ namespace exprtk return stringfunc_node; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR197 - Failed to generate node for string function: '" + symbol + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR229 - Failed to generate node for string function: '" + symbol + "'", + exprtk_error_location)); return error_node(); } @@ -27275,11 +30970,11 @@ namespace exprtk return overloadfunc_node; else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR198 - Failed to generate node for overload function: '" + symbol + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR230 - Failed to generate node for overload function: '" + symbol + "'", + exprtk_error_location)); return error_node(); } @@ -27301,11 +30996,11 @@ namespace exprtk !details::is_base_function(symbol) ) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR199 - Invalid use of reserved symbol '" + symbol + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR231 - Invalid use of reserved symbol '" + symbol + "'", + exprtk_error_location)); return error_node(); } @@ -27332,11 +31027,13 @@ namespace exprtk switch (usr_symbol_type) { - case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value); - break; + case unknown_symbol_resolver::e_usr_variable_type : + create_result = symtab.create_variable(symbol, default_value); + break; - case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value); - break; + case unknown_symbol_resolver::e_usr_constant_type : + create_result = symtab.add_constant(symbol, default_value); + break; default : create_result = false; } @@ -27364,12 +31061,12 @@ namespace exprtk } } - set_error( - make_error(parser_error::e_symtab, - current_token(), - "ERR200 - Failed to create variable: '" + symbol + "'" + - (error_message.empty() ? "" : " - " + error_message), - exprtk_error_location)); + set_error(make_error( + parser_error::e_symtab, + current_token(), + "ERR232 - Failed to create variable: '" + symbol + "'" + + (error_message.empty() ? "" : " - " + error_message), + exprtk_error_location)); } else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) @@ -27384,27 +31081,51 @@ namespace exprtk } } - set_error( - make_error(parser_error::e_symtab, - current_token(), - "ERR201 - Failed to resolve symbol: '" + symbol + "'" + - (error_message.empty() ? "" : " - " + error_message), - exprtk_error_location)); + set_error(make_error( + parser_error::e_symtab, + current_token(), + "ERR233 - Failed to resolve symbol: '" + symbol + "'" + + (error_message.empty() ? "" : " - " + error_message), + exprtk_error_location)); } return error_node(); } } - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR202 - Undefined symbol: '" + symbol + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR234 - Undefined symbol: '" + symbol + "'", + exprtk_error_location)); return error_node(); } + inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) + { + if ( + expression && + ( + (current_token().type == token_t::e_symbol) || + (current_token().type == token_t::e_number) + ) + ) + { + free_node(node_allocator_, expression); + + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR235 - Invalid syntax '" + current_token().value + "' possible missing operator or context", + exprtk_error_location)); + + return error_node(); + } + + return expression; + } + inline expression_node_ptr parse_symbol() { static const std::string symbol_if = "if" ; @@ -27416,9 +31137,11 @@ namespace exprtk static const std::string symbol_break = "break" ; static const std::string symbol_continue = "continue"; static const std::string symbol_var = "var" ; + static const std::string symbol_const = "const" ; static const std::string symbol_swap = "swap" ; static const std::string symbol_return = "return" ; static const std::string symbol_not = "not" ; + static const std::string symbol_assert = "assert" ; const std::string symbol = current_token().value; @@ -27446,28 +31169,28 @@ namespace exprtk settings_.control_struct_enabled(symbol) ) { - return parse_while_loop(); + return check_block_statement_closure(parse_while_loop()); } else if ( details::imatch(symbol, symbol_repeat) && settings_.control_struct_enabled(symbol) ) { - return parse_repeat_until_loop(); + return check_block_statement_closure(parse_repeat_until_loop()); } else if ( details::imatch(symbol, symbol_for) && settings_.control_struct_enabled(symbol) ) { - return parse_for_loop(); + return check_block_statement_closure(parse_for_loop()); } else if ( details::imatch(symbol, symbol_switch) && settings_.control_struct_enabled(symbol) ) { - return parse_switch_statement(); + return check_block_statement_closure(parse_switch_statement()); } else if (details::is_valid_sf_symbol(symbol)) { @@ -27491,6 +31214,10 @@ namespace exprtk { return parse_define_var_statement(); } + else if (details::imatch(symbol, symbol_const)) + { + return parse_define_constvar_statement(); + } else if (details::imatch(symbol, symbol_swap)) { return parse_swap_statement(); @@ -27501,20 +31228,25 @@ namespace exprtk settings_.control_struct_enabled(symbol) ) { - return parse_return_statement(); + return check_block_statement_closure(parse_return_statement()); } #endif + else if (details::imatch(symbol, symbol_assert)) + { + return parse_assert_statement(); + } else if (symtab_store_.valid() || !sem_.empty()) { return parse_symtab_symbol(); } else { - set_error( - make_error(parser_error::e_symtab, - current_token(), - "ERR203 - Variable or function detected, yet symbol-table is invalid, Symbol: " + symbol, - exprtk_error_location)); + set_error(make_error( + parser_error::e_symtab, + current_token(), + "ERR236 - Unknown variable or function encountered. Symbol table(s) " + "is either invalid or does not contain symbol: '" + symbol + "'", + exprtk_error_location)); return error_node(); } @@ -27541,11 +31273,11 @@ namespace exprtk if (0 == literal_exp) { - set_error( - make_error(parser_error::e_numeric, - current_token(), - "ERR204 - Failed generate node for scalar: '" + current_token().value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_numeric, + current_token(), + "ERR237 - Failed generate node for scalar: '" + current_token().value + "'", + exprtk_error_location)); return error_node(); } @@ -27555,11 +31287,11 @@ namespace exprtk } else { - set_error( - make_error(parser_error::e_numeric, - current_token(), - "ERR205 - Failed to convert '" + current_token().value + "' to a number", - exprtk_error_location)); + set_error(make_error( + parser_error::e_numeric, + current_token(), + "ERR238 - Failed to convert '" + current_token().value + "' to a number", + exprtk_error_location)); return error_node(); } @@ -27579,25 +31311,32 @@ namespace exprtk next_token(); if (0 == (branch = parse_expression())) + { return error_node(); - else if (!token_is(token_t::e_rbracket)) + } + + token_is(token_t::e_eof); + + if (!token_is(token_t::e_rbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR206 - Expected ')' instead of: '" + current_token().value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR239 - Expected ')' instead of: '" + current_token().value + "'", + exprtk_error_location)); - details::free_node(node_allocator_,branch); + details::free_node(node_allocator_, branch); return error_node(); } else if (!post_bracket_process(token_t::e_lbracket,branch)) { - details::free_node(node_allocator_,branch); + details::free_node(node_allocator_, branch); return error_node(); } + + parse_pending_vector_index_operator(branch); } else if (token_t::e_lsqrbracket == current_token().type) { @@ -27607,19 +31346,19 @@ namespace exprtk return error_node(); else if (!token_is(token_t::e_rsqrbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR207 - Expected ']' instead of: '" + current_token().value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR240 - Expected ']' instead of: '" + current_token().value + "'", + exprtk_error_location)); - details::free_node(node_allocator_,branch); + details::free_node(node_allocator_, branch); return error_node(); } else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) { - details::free_node(node_allocator_,branch); + details::free_node(node_allocator_, branch); return error_node(); } @@ -27632,19 +31371,19 @@ namespace exprtk return error_node(); else if (!token_is(token_t::e_rcrlbracket)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR208 - Expected '}' instead of: '" + current_token().value + "'", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR241 - Expected '}' instead of: '" + current_token().value + "'", + exprtk_error_location)); - details::free_node(node_allocator_,branch); + details::free_node(node_allocator_, branch); return error_node(); } else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) { - details::free_node(node_allocator_,branch); + details::free_node(node_allocator_, branch); return error_node(); } @@ -27666,7 +31405,7 @@ namespace exprtk if (0 == result) { - details::free_node(node_allocator_,branch); + details::free_node(node_allocator_, branch); return error_node(); } @@ -27681,21 +31420,21 @@ namespace exprtk } else if (token_t::e_eof == current_token().type) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR209 - Premature end of expression[1]", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR242 - Premature end of expression[1]", + exprtk_error_location)); return error_node(); } else { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR210 - Premature end of expression[2]", - exprtk_error_location)); + set_error(make_error( + parser_error::e_syntax, + current_token(), + "ERR243 - Premature end of expression[2]", + exprtk_error_location)); return error_node(); } @@ -27796,6 +31535,8 @@ namespace exprtk register_synthezier(synthesize_covocov_expression4) register_synthezier(synthesize_vocovoc_expression4) register_synthezier(synthesize_covovoc_expression4) + + #undef register_synthezier #endif } @@ -27848,7 +31589,7 @@ namespace exprtk { typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); - if ((*binary_op_map_).end() == bop_itr) + if (binary_op_map_->end() == bop_itr) return false; bop = bop_itr->second; @@ -28260,13 +32001,20 @@ namespace exprtk if (details::is_string_node(branch[0])) return !b1_is_genstring; + else if (details::is_literal_node(branch[0])) + return true; else return ( - !details::is_variable_node (branch[0]) && - !details::is_vector_elem_node (branch[0]) && - !details::is_rebasevector_elem_node (branch[0]) && - !details::is_rebasevector_celem_node(branch[0]) && - !details::is_vector_node (branch[0]) + !details::is_variable_node (branch[0]) && + !details::is_vector_elem_node (branch[0]) && + !details::is_vector_celem_node (branch[0]) && + !details::is_vector_elem_rtc_node (branch[0]) && + !details::is_vector_celem_rtc_node (branch[0]) && + !details::is_rebasevector_elem_node (branch[0]) && + !details::is_rebasevector_celem_node (branch[0]) && + !details::is_rebasevector_elem_rtc_node (branch[0]) && + !details::is_rebasevector_celem_rtc_node(branch[0]) && + !details::is_vector_node (branch[0]) ) || b1_is_genstring; } @@ -28421,18 +32169,42 @@ namespace exprtk { if ((0 == branch[0]) || (0 == branch[1])) { + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR244 - Invalid branches received for operator '" + details::to_str(operation) + "'", + exprtk_error_location)); + return error_node(); } else if (is_invalid_string_op(operation,branch)) { + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR245 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", + exprtk_error_location)); + return error_node(); } else if (is_invalid_assignment_op(operation,branch)) { + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR246 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", + exprtk_error_location)); + return error_node(); } else if (is_invalid_break_continue_op(branch)) { + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR247 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", + exprtk_error_location)); + return error_node(); } else if (details::e_assign == operation) @@ -28551,10 +32323,22 @@ namespace exprtk { details::free_all_nodes(*node_allocator_,branch); + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR248 - Invalid branches operator '" + details::to_str(operation) + "'", + exprtk_error_location)); + return error_node(); } else if (is_invalid_string_op(operation, branch)) { + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR249 - Invalid branches for string operator '" + details::to_str(operation) + "'", + exprtk_error_location)); + return error_node(); } else if (is_string_operation(operation, branch)) @@ -28601,6 +32385,16 @@ namespace exprtk details::free_node(*node_allocator_, consequent ); details::free_node(*node_allocator_, alternative); + const std::string invalid_branches = + ((0 == condition ) ? std::string("condition ") : "") + + ((0 == consequent) ? std::string("consequent") : "") ; + + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + parser_->current_state().token, + "ERR250 - Invalid " + invalid_branches + " for conditional statement", + exprtk_error_location)); + return error_node(); } // Can the condition be immediately evaluated? if so optimise. @@ -28626,14 +32420,34 @@ namespace exprtk return node_allocator_->allocate >(); } } - else if ((0 != consequent) && (0 != alternative)) + + expression_node_ptr result = error_node(); + std::string node_name = "Unknown!"; + + if ((0 != consequent) && (0 != alternative)) { - return node_allocator_-> - allocate(condition, consequent, alternative); + result = node_allocator_->allocate(condition, consequent, alternative); + node_name = "conditional_node_t"; } else - return node_allocator_-> - allocate(condition, consequent); + { + result = node_allocator_->allocate(condition, consequent); + node_name = "cons_conditional_node_t"; + } + + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + token_t(), + "ERR251 - Failed to synthesize node: " + node_name, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } #ifndef exprtk_disable_string_capabilities @@ -28647,6 +32461,16 @@ namespace exprtk details::free_node(*node_allocator_, consequent ); details::free_node(*node_allocator_, alternative); + const std::string invalid_branches = + ((0 == condition ) ? std::string("condition ") : "") + + ((0 == consequent) ? std::string("consequent") : "") ; + + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + parser_->current_state().token, + "ERR252 - Invalid " + invalid_branches + " for string conditional statement", + exprtk_error_location)); + return error_node(); } // Can the condition be immediately evaluated? if so optimise. @@ -28674,10 +32498,25 @@ namespace exprtk } } else if ((0 != consequent) && (0 != alternative)) - return node_allocator_-> - allocate(condition, consequent, alternative); - else - return error_node(); + { + expression_node_ptr result = + node_allocator_->allocate(condition, consequent, alternative); + + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + token_t(), + "ERR253 - Failed to synthesize node: conditional_string_node_t", + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + } + + return error_node(); } #else inline expression_node_ptr conditional_string(expression_node_ptr, @@ -28698,6 +32537,16 @@ namespace exprtk details::free_node(*node_allocator_, consequent ); details::free_node(*node_allocator_, alternative); + const std::string invalid_branches = + ((0 == condition ) ? std::string("condition ") : "") + + ((0 == consequent) ? std::string("consequent") : "") ; + + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + parser_->current_state().token, + "ERR254 - Invalid " + invalid_branches + " for vector conditional statement", + exprtk_error_location)); + return error_node(); } // Can the condition be immediately evaluated? if so optimise. @@ -28746,16 +32595,34 @@ namespace exprtk return loop_runtime_check_ptr(0); } + inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const + { + return parser_->vector_access_runtime_check_; + } + inline expression_node_ptr while_loop(expression_node_ptr& condition, expression_node_ptr& branch, const bool break_continue_present = false) const { - if (!break_continue_present && details::is_constant_node(condition)) + if ( + !break_continue_present && + !parser_->state_.return_stmt_present && + details::is_constant_node(condition) + ) { expression_node_ptr result = error_node(); if (details::is_true(condition)) + { // Infinite loops are not allowed. + + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + parser_->current_state().token, + "ERR255 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", + exprtk_error_location)); + result = error_node(); + } else result = node_allocator_->allocate >(); @@ -28857,13 +32724,26 @@ namespace exprtk expression_node_ptr& loop_body, bool break_continue_present = false) const { - if (!break_continue_present && details::is_constant_node(condition)) + if ( + !break_continue_present && + !parser_->state_.return_stmt_present && + details::is_constant_node(condition) + ) { expression_node_ptr result = error_node(); if (details::is_true(condition)) + { // Infinite loops are not allowed. + + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + parser_->current_state().token, + "ERR256 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", + exprtk_error_location)); + result = error_node(); + } else result = node_allocator_->allocate >(); @@ -28890,19 +32770,19 @@ namespace exprtk if (rtc) return node_allocator_->allocate ( - initialiser, - condition, - incrementor, - loop_body, - rtc + initialiser, + condition, + incrementor, + loop_body, + rtc ); else return node_allocator_->allocate ( - initialiser, - condition, - incrementor, - loop_body + initialiser, + condition, + incrementor, + loop_body ); } #ifndef exprtk_disable_break_continue @@ -28911,19 +32791,19 @@ namespace exprtk if (rtc) return node_allocator_->allocate ( - initialiser, - condition, - incrementor, - loop_body, - rtc + initialiser, + condition, + incrementor, + loop_body, + rtc ); else return node_allocator_->allocate ( - initialiser, - condition, - incrementor, - loop_body + initialiser, + condition, + incrementor, + loop_body ); } #else @@ -28986,8 +32866,8 @@ namespace exprtk if (0 == result) { - T zero = T(0); - result = node_allocator_->allocate(zero); + const T zero = T(0); + result = node_allocator_->allocate(zero); } for (std::size_t i = 0; i < arg_list.size(); ++i) @@ -29161,6 +33041,28 @@ namespace exprtk return node_allocator_->allocate >(arg_list); } + inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, + expression_node_ptr& assert_message, + const assert_check::assert_context& context) + { + typedef details::assert_node alloc_type; + + expression_node_ptr result = node_allocator_->allocate_rrrr + (assert_condition, assert_message, parser_->assert_check_, context); + + if (result && result->valid()) + { + parser_->state_.activate_side_effect("assert_call()"); + return result; + } + + details::free_node(*node_allocator_, result ); + details::free_node(*node_allocator_, assert_condition); + details::free_node(*node_allocator_, assert_message ); + + return error_node(); + } + #define unary_opr_switch_statements \ case_stmt(details::e_abs , details::abs_op ) \ case_stmt(details::e_acos , details::acos_op ) \ @@ -29280,6 +33182,8 @@ namespace exprtk default : return error_node(); } + assert(temp_node); + const T v = temp_node->value(); details::free_node(*node_allocator_,temp_node); @@ -29383,6 +33287,8 @@ namespace exprtk default : return error_node(); } + assert(temp_node); + const T v = temp_node->value(); details::free_node(*node_allocator_,temp_node); @@ -29503,7 +33409,8 @@ namespace exprtk template class Sequence> - inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence& arg_list) + inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, + Sequence& arg_list) { switch (operation) { @@ -29526,7 +33433,8 @@ namespace exprtk template class Sequence> - inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence& arg_list) + inline expression_node_ptr vectorize_func(const details::operator_type& operation, + Sequence& arg_list) { if (1 == arg_list.size()) { @@ -29551,7 +33459,8 @@ namespace exprtk template class Sequence> - inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence& arg_list) + inline expression_node_ptr vararg_function(const details::operator_type& operation, + Sequence& arg_list) { if (!all_nodes_valid(arg_list)) { @@ -29561,9 +33470,9 @@ namespace exprtk } else if (is_constant_foldable(arg_list)) return const_optimise_varargfunc(operation,arg_list); - else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0])) + else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) return vectorize_func(operation,arg_list); - else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation)) + else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) return arg_list[0]; else if (all_nodes_variables(arg_list)) return varnode_optimise_varargfunc(operation,arg_list); @@ -29571,17 +33480,32 @@ namespace exprtk #ifndef exprtk_disable_string_capabilities if (details::e_smulti == operation) { - return node_allocator_-> + expression_node_ptr result = node_allocator_-> allocate > >(arg_list); + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR257 - Failed to synthesize node: str_vararg_node", + exprtk_error_location)); + + details::free_node(*node_allocator_, result); } else #endif { + expression_node_ptr result = error_node(); + switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ allocate > >(arg_list); \ + break; \ case_stmt(details::e_sum , details::vararg_add_op ) case_stmt(details::e_prod , details::vararg_mul_op ) @@ -29594,7 +33518,22 @@ namespace exprtk #undef case_stmt default : return error_node(); } + + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR258 - Failed to synthesize node: vararg_node", + exprtk_error_location)); + + details::free_node(*node_allocator_, result); } + + return error_node(); } template @@ -29635,7 +33574,19 @@ namespace exprtk return error_node(); } - return result; + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR259 - Failed to synthesize node: function_N_node_t", + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } } @@ -29672,7 +33623,19 @@ namespace exprtk parser_->state_.activate_side_effect("vararg_function_call()"); - return result; + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR260 - Failed to synthesize node: vararg_function_node", + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } inline expression_node_ptr generic_function_call(igeneric_function_t* gf, @@ -29691,14 +33654,23 @@ namespace exprtk const std::size_t no_psi = std::numeric_limits::max(); expression_node_ptr result = error_node(); + std::string node_name = "Unknown"; if (no_psi == param_seq_index) + { result = node_allocator_->allocate(arg_list,gf); + node_name = "generic_function_node"; + } else + { result = node_allocator_->allocate(gf, param_seq_index, arg_list); + node_name = "multimode_genfunction_node"; + } alloc_type1* genfunc_node_ptr = static_cast(result); + assert(genfunc_node_ptr); + if ( !arg_list.empty() && !gf->has_side_effects() && @@ -29716,9 +33688,20 @@ namespace exprtk } else if (genfunc_node_ptr->init_branches()) { - parser_->state_.activate_side_effect("generic_function_call()"); + if (result && result->valid()) + { + parser_->state_.activate_side_effect("generic_function_call()"); + return result; + } - return result; + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR261 - Failed to synthesize node: " + node_name, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } else { @@ -29746,14 +33729,23 @@ namespace exprtk const std::size_t no_psi = std::numeric_limits::max(); expression_node_ptr result = error_node(); + std::string node_name = "Unknown"; if (no_psi == param_seq_index) + { result = node_allocator_->allocate(gf,arg_list); + node_name = "string_function_node"; + } else + { result = node_allocator_->allocate(gf, param_seq_index, arg_list); + node_name = "multimode_strfunction_node"; + } alloc_type1* strfunc_node_ptr = static_cast(result); + assert(strfunc_node_ptr); + if ( !arg_list.empty() && !gf->has_side_effects() && @@ -29770,9 +33762,20 @@ namespace exprtk } else if (strfunc_node_ptr->init_branches()) { - parser_->state_.activate_side_effect("string_function_call()"); + if (result && result->valid()) + { + parser_->state_.activate_side_effect("string_function_call()"); + return result; + } - return result; + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR262 - Failed to synthesize node: " + node_name, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } else { @@ -29800,11 +33803,24 @@ namespace exprtk alloc_type* return_node_ptr = static_cast(result); + assert(return_node_ptr); + if (return_node_ptr->init_branches()) { - parser_->state_.activate_side_effect("return_call()"); + if (result && result->valid()) + { + parser_->state_.activate_side_effect("return_call()"); + return result; + } - return result; + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR263 - Failed to synthesize node: return_node", + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } else { @@ -29842,28 +33858,93 @@ namespace exprtk } #endif - inline expression_node_ptr vector_element(const std::string& symbol, - vector_holder_ptr vector_base, + inline expression_node_ptr vector_element(const std::string& symbol, + vector_holder_ptr vector_base, + expression_node_ptr vec_node, expression_node_ptr index) { expression_node_ptr result = error_node(); + std::string node_name = "Unknown"; if (details::is_constant_node(index)) { - std::size_t i = static_cast(details::numeric::to_int64(index->value())); + const std::size_t vec_index = static_cast(details::numeric::to_int64(index->value())); details::free_node(*node_allocator_,index); + if (vec_index >= vector_base->size()) + { + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + token_t(), + "ERR264 - Index of " + details::to_str(vec_index) + " out of range for " + "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), + exprtk_error_location)); + + details::free_node(*node_allocator_,vec_node); + + return error_node(); + } + if (vector_base->rebaseable()) { - return node_allocator_->allocate(i,vector_base); + vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); + + result = (rtc) ? + node_allocator_->allocate(vec_node, vec_index, vector_base, rtc) : + node_allocator_->allocate(vec_node, vec_index, vector_base ) ; + + node_name = (rtc) ? + "rebasevector_elem_rtc_node_t" : + "rebasevector_elem_node_t" ; + + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR265 - Failed to synthesize node: " + node_name + " for vector: " + symbol, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); + } + else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) + { + vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); + + result = (rtc) ? + node_allocator_->allocate(vec_node, vec_index, vector_base, rtc) : + node_allocator_->allocate(vec_node, vec_index, vector_base ) ; + + node_name = (rtc) ? + "vector_elem_rtc_node_t" : + "vector_elem_node_t" ; + + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR266 - Failed to synthesize node: " + node_name + " for vector: " + symbol, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } - const scope_element& se = parser_->sem_.get_element(symbol,i); + const scope_element& se = parser_->sem_.get_element(symbol,vec_index); - if (se.index == i) + if (se.index == vec_index) { result = se.var_node; + details::free_node(*node_allocator_,vec_node); } else { @@ -29872,10 +33953,10 @@ namespace exprtk nse.active = true; nse.ref_count = 1; nse.type = scope_element::e_vecelem; - nse.index = i; + nse.index = vec_index; nse.depth = parser_->state_.scope_depth; nse.data = 0; - nse.var_node = node_allocator_->allocate((*(*vector_base)[i])); + nse.var_node = node_allocator_->allocate((*(*vector_base)[vec_index])); if (!parser_->sem_.add_element(nse)) { @@ -29886,19 +33967,55 @@ namespace exprtk result = error_node(); } - exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str())); + details::free_node(*node_allocator_,vec_node); + + exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); parser_->state_.activate_side_effect("vector_element()"); result = nse.var_node; + node_name = "variable_node_t"; } } - else if (vector_base->rebaseable()) - result = node_allocator_->allocate(index,vector_base); else - result = node_allocator_->allocate(index,vector_base); + { + vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); - return result; + if (vector_base->rebaseable()) + { + result = (rtc) ? + node_allocator_->allocate(vec_node, index, vector_base, rtc) : + node_allocator_->allocate(vec_node, index, vector_base ) ; + + node_name = (rtc) ? + "rebasevector_elem_rtc_node_t" : + "rebasevector_elem_node_t" ; + } + else + { + result = rtc ? + node_allocator_->allocate(vec_node, index, vector_base, rtc) : + node_allocator_->allocate(vec_node, index, vector_base ) ; + + node_name = (rtc) ? + "vector_elem_rtc_node_t" : + "vector_elem_node_t" ; + } + } + + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR267 - Failed to synthesize node: " + node_name, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } private: @@ -29995,12 +34112,27 @@ namespace exprtk case details::expression_node::e_vecelem: return reinterpret_cast(&static_cast(node)->ref()); + case details::expression_node::e_veccelem: + return reinterpret_cast(&static_cast(node)->ref()); + + case details::expression_node::e_vecelemrtc: + return reinterpret_cast(&static_cast(node)->ref()); + + case details::expression_node::e_veccelemrtc: + return reinterpret_cast(&static_cast(node)->ref()); + case details::expression_node::e_rbvecelem: return reinterpret_cast(&static_cast(node)->ref()); + case details::expression_node::e_rbvecelemrtc: + return reinterpret_cast(&static_cast(node)->ref()); + case details::expression_node::e_rbveccelem: return reinterpret_cast(&static_cast(node)->ref()); + case details::expression_node::e_rbveccelemrtc: + return reinterpret_cast(&static_cast(node)->ref()); + case details::expression_node::e_vector: return reinterpret_cast(static_cast(node)->vec_holder().data()); @@ -30032,11 +34164,11 @@ namespace exprtk if (parser_->immutable_symtok_map_.end() != itr) { token_t& token = itr->second; - parser_->set_error( - parser_error::make_error(parser_error::e_parser, - token, - "ERR211 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", - exprtk_error_location)); + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + token, + "ERR268 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", + exprtk_error_location)); } else parser_->set_synthesis_error("Unable to assign symbol is immutable."); @@ -30058,16 +34190,26 @@ namespace exprtk lodge_assignment(e_st_variable,branch[0]); return synthesize_expression(operation,branch); } - else if (details::is_vector_elem_node(branch[0])) + else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) { lodge_assignment(e_st_vecelem,branch[0]); return synthesize_expression(operation, branch); } + else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + return synthesize_expression(operation, branch); + } else if (details::is_rebasevector_elem_node(branch[0])) { lodge_assignment(e_st_vecelem,branch[0]); return synthesize_expression(operation, branch); } + else if (details::is_rebasevector_elem_rtc_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + return synthesize_expression(operation, branch); + } else if (details::is_rebasevector_celem_node(branch[0])) { lodge_assignment(e_st_vecelem,branch[0]); @@ -30094,9 +34236,23 @@ namespace exprtk else return synthesize_expression(operation, branch); } + else if (details::is_literal_node(branch[0])) + { + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR269 - Cannot assign value to const variable", + exprtk_error_location)); + + return error_node(); + } else { - parser_->set_synthesis_error("Invalid assignment operation.[1]"); + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR270 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", + exprtk_error_location)); return error_node(); } @@ -30110,6 +34266,9 @@ namespace exprtk return error_node(); } + expression_node_ptr result = error_node(); + std::string node_name = "Unknown"; + if (details::is_variable_node(branch[0])) { lodge_assignment(e_st_variable,branch[0]); @@ -30117,9 +34276,11 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "assignment_op_node"; \ + break; \ case_stmt(details::e_addass , details::add_op) case_stmt(details::e_subass , details::sub_op) @@ -30137,9 +34298,55 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "assignment_vec_elem_op_node"; \ + break; \ + + case_stmt(details::e_addass , details::add_op) + case_stmt(details::e_subass , details::sub_op) + case_stmt(details::e_mulass , details::mul_op) + case_stmt(details::e_divass , details::div_op) + case_stmt(details::e_modass , details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else if (details::is_vector_elem_rtc_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + switch (operation) + { + #define case_stmt(op0, op1) \ + case op0 : result = node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + node_name = "assignment_vec_elem_op_rtc_node"; \ + break; \ + + case_stmt(details::e_addass , details::add_op) + case_stmt(details::e_subass , details::sub_op) + case_stmt(details::e_mulass , details::mul_op) + case_stmt(details::e_divass , details::div_op) + case_stmt(details::e_modass , details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else if (details::is_vector_celem_rtc_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + switch (operation) + { + #define case_stmt(op0, op1) \ + case op0 : result = node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + node_name = "assignment_vec_celem_op_rtc_node"; \ + break; \ case_stmt(details::e_addass , details::add_op) case_stmt(details::e_subass , details::sub_op) @@ -30157,9 +34364,11 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "assignment_rebasevec_elem_op_node"; \ + break; \ case_stmt(details::e_addass , details::add_op) case_stmt(details::e_subass , details::sub_op) @@ -30177,9 +34386,55 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "assignment_rebasevec_celem_op_node"; \ + break; \ + + case_stmt(details::e_addass , details::add_op) + case_stmt(details::e_subass , details::sub_op) + case_stmt(details::e_mulass , details::mul_op) + case_stmt(details::e_divass , details::div_op) + case_stmt(details::e_modass , details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else if (details::is_rebasevector_elem_rtc_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + switch (operation) + { + #define case_stmt(op0, op1) \ + case op0 : result = node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + node_name = "assignment_rebasevec_elem_op_rtc_node"; \ + break; \ + + case_stmt(details::e_addass , details::add_op) + case_stmt(details::e_subass , details::sub_op) + case_stmt(details::e_mulass , details::mul_op) + case_stmt(details::e_divass , details::div_op) + case_stmt(details::e_modass , details::mod_op) + #undef case_stmt + default : return error_node(); + } + } + else if (details::is_rebasevector_celem_rtc_node(branch[0])) + { + lodge_assignment(e_st_vecelem,branch[0]); + + switch (operation) + { + #define case_stmt(op0, op1) \ + case op0 : result = node_allocator_-> \ + template allocate_rrr > > \ + (operation, branch[0], branch[1]); \ + node_name = "assignment_rebasevec_celem_op_rtc_node"; \ + break; \ case_stmt(details::e_addass , details::add_op) case_stmt(details::e_subass , details::sub_op) @@ -30199,9 +34454,11 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "assignment_rebasevec_celem_op_node"; \ + break; \ case_stmt(details::e_addass , details::add_op) case_stmt(details::e_subass , details::sub_op) @@ -30217,9 +34474,11 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "assignment_vec_op_node"; \ + break; \ case_stmt(details::e_addass , details::add_op) case_stmt(details::e_subass , details::sub_op) @@ -30241,15 +34500,34 @@ namespace exprtk lodge_assignment(e_st_string,branch[0]); - return synthesize_expression(operation,branch); + result = synthesize_expression(operation,branch); + node_name = "assignment_string_node"; } #endif else { - parser_->set_synthesis_error("Invalid assignment operation[2]"); + parser_->set_error(parser_error::make_error( + parser_error::e_syntax, + parser_->current_state().token, + "ERR271 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", + exprtk_error_location)); return error_node(); } + + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR272 - Failed to synthesize node: " + node_name, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, @@ -30273,14 +34551,19 @@ namespace exprtk case_stmt(details::e_xor , details::xor_op ) \ case_stmt(details::e_xnor , details::xnor_op ) \ + expression_node_ptr result = error_node(); + std::string node_name = "Unknown"; + if (is_b0_ivec && is_b1_ivec) { switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "vec_binop_vecvec_node"; \ + break; \ batch_eqineq_logic_case #undef case_stmt @@ -30292,9 +34575,11 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "vec_binop_vecval_node"; \ + break; \ batch_eqineq_logic_case #undef case_stmt @@ -30306,9 +34591,11 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "vec_binop_valvec_node"; \ + break; \ batch_eqineq_logic_case #undef case_stmt @@ -30318,6 +34605,20 @@ namespace exprtk else return error_node(); + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR273 - Failed to synthesize node: " + node_name, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); + #undef batch_eqineq_logic_case } @@ -30334,14 +34635,19 @@ namespace exprtk case_stmt(details::e_div , details::div_op) \ case_stmt(details::e_mod , details::mod_op) \ + expression_node_ptr result = error_node(); + std::string node_name = "Unknown"; + if (is_b0_ivec && is_b1_ivec) { switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "vec_binop_vecvec_node"; \ + break; \ vector_ops case_stmt(details::e_pow,details:: pow_op) @@ -30354,9 +34660,11 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)"; \ + break; \ vector_ops case_stmt(details::e_pow,details:: pow_op) @@ -30369,9 +34677,11 @@ namespace exprtk switch (operation) { #define case_stmt(op0, op1) \ - case op0 : return node_allocator_-> \ + case op0 : result = node_allocator_-> \ template allocate_rrr > > \ (operation, branch[0], branch[1]); \ + node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)"; \ + break; \ vector_ops #undef case_stmt @@ -30381,6 +34691,20 @@ namespace exprtk else return error_node(); + if (result && result->valid()) + { + return result; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR274 - Failed to synthesize node: " + node_name, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); + #undef vector_ops } @@ -30398,6 +34722,7 @@ namespace exprtk #endif expression_node_ptr result = error_node(); + std::string node_name = "Unknown"; if (v0_is_ivar && v1_is_ivar) { @@ -30411,36 +34736,57 @@ namespace exprtk (0 != (v1 = dynamic_cast(branch[1]))) ) { - result = node_allocator_->allocate >(v0,v1); + result = node_allocator_->allocate >(v0,v1); + node_name = "swap_node"; } else - result = node_allocator_->allocate >(branch[0],branch[1]); + { + result = node_allocator_->allocate >(branch[0],branch[1]); + node_name = "swap_generic_node"; + } } else if (v0_is_ivec && v1_is_ivec) { - result = node_allocator_->allocate >(branch[0],branch[1]); + result = node_allocator_->allocate >(branch[0],branch[1]); + node_name = "swap_vecvec_node"; } #ifndef exprtk_disable_string_capabilities else if (v0_is_str && v1_is_str) { if (is_string_node(branch[0]) && is_string_node(branch[1])) + { result = node_allocator_->allocate > (branch[0], branch[1]); + node_name = "swap_string_node"; + } else + { result = node_allocator_->allocate > (branch[0], branch[1]); + node_name = "swap_genstrings_node"; + } } #endif else { parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); - return error_node(); } - parser_->state_.activate_side_effect("synthesize_swap_expression()"); + if (result && result->valid()) + { + parser_->state_.activate_side_effect("synthesize_swap_expression()"); + return result; + } - return result; + parser_->set_error(parser_error::make_error( + parser_error::e_synthesis, + token_t(), + "ERR275 - Failed to synthesize node: " + node_name, + exprtk_error_location)); + + details::free_node(*node_allocator_, result); + return error_node(); } #ifndef exprtk_disable_sc_andor @@ -30596,7 +34942,7 @@ namespace exprtk else if (not_recipricol) return cardinal_pow_optimisation_impl(branch[0],p); else - return cardinal_pow_optimisation_impl(branch[0],p); + return cardinal_pow_optimisation_impl(branch[0],p); } #else inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) @@ -31969,9 +36315,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; } }; @@ -32034,9 +36380,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; } }; @@ -32100,9 +36446,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; } }; @@ -32165,9 +36511,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; } }; @@ -32230,9 +36576,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; } }; @@ -32295,9 +36641,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; } }; @@ -32360,9 +36706,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; } }; @@ -32426,9 +36772,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; } }; @@ -32545,9 +36891,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; } }; @@ -32664,9 +37010,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; } }; @@ -32795,9 +37141,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)"; } }; @@ -32922,9 +37268,9 @@ namespace exprtk const details::operator_type o1) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t"; } }; @@ -33057,10 +37403,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -33146,10 +37492,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -33235,10 +37581,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -33324,10 +37670,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -33413,10 +37759,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -33607,10 +37953,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -33851,10 +38197,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -34045,10 +38391,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -34238,10 +38584,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t)"; + << "(t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t)"; } }; @@ -34298,10 +38644,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34358,10 +38704,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34418,10 +38764,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34478,10 +38824,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34539,10 +38885,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34600,10 +38946,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34660,10 +39006,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34720,10 +39066,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34780,10 +39126,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "(t" << expr_gen.to_str(o2) - << "t))"; + << "t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "(t" << expr_gen.to_str(o2) + << "t))"; } }; @@ -34840,10 +39186,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; } }; @@ -34900,10 +39246,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; } }; @@ -34960,10 +39306,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; } }; @@ -35020,10 +39366,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; } }; @@ -35081,10 +39427,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; } }; @@ -35142,10 +39488,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; } }; @@ -35202,10 +39548,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; } }; @@ -35263,10 +39609,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "t" << expr_gen.to_str(o0) - << "((t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t)"; + << "t" << expr_gen.to_str(o0) + << "((t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t)"; } }; @@ -35344,10 +39690,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35405,10 +39751,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35465,10 +39811,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35525,10 +39871,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35585,10 +39931,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35645,10 +39991,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35706,10 +40052,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35767,10 +40113,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35827,10 +40173,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "((t" << expr_gen.to_str(o0) - << "t)" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "((t" << expr_gen.to_str(o0) + << "t)" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35887,10 +40233,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -35948,10 +40294,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -36008,10 +40354,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -36067,10 +40413,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -36127,10 +40473,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -36187,10 +40533,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -36248,10 +40594,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -36309,10 +40655,10 @@ namespace exprtk const details::operator_type o2) { return details::build_string() - << "(t" << expr_gen.to_str(o0) - << "(t" << expr_gen.to_str(o1) - << "t)" << expr_gen.to_str(o2) - << "t"; + << "(t" << expr_gen.to_str(o0) + << "(t" << expr_gen.to_str(o1) + << "t)" << expr_gen.to_str(o2) + << "t"; } }; @@ -36737,6 +41083,8 @@ namespace exprtk default : return error_node(); } } + + #undef string_opr_switch_statements #endif #ifndef exprtk_disable_string_capabilities @@ -37070,11 +41418,22 @@ namespace exprtk return node_allocator_->allocate(v); } - else + + if (expression_point && expression_point->valid()) + { return expression_point; + } + + parser_->set_error(parser_error::make_error( + parser_error::e_parser, + token_t(), + "ERR276 - Failed to synthesize node: NodeType", + exprtk_error_location)); + + details::free_node(*node_allocator_, expression_point); } - else - return error_node(); + + return error_node(); } template @@ -37154,8 +41513,11 @@ namespace exprtk { scope_element& se = sem_.get_element(i); + exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); + if ( (scope_element::e_variable == se.type) || + (scope_element::e_literal == se.type) || (scope_element::e_vecelem == se.type) ) { @@ -37428,6 +41790,7 @@ namespace exprtk sf4_map_t sf4_map_; std::string synthesis_error_; scope_element_manager sem_; + std::vector current_state_stack_; immutable_memory_map_t immutable_memory_map_; immutable_symtok_map_t immutable_symtok_map_; @@ -37443,7 +41806,11 @@ namespace exprtk lexer::helper::sequence_validator sequence_validator_; lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; - loop_runtime_check_ptr loop_runtime_check_; + loop_runtime_check_ptr loop_runtime_check_; + vector_access_runtime_check_ptr vector_access_runtime_check_; + compilation_check_ptr compilation_check_ptr_; + assert_check_ptr assert_check_; + std::set assert_ids_; template friend void details::disable_type_checking(ParserType& p); @@ -37460,17 +41827,19 @@ namespace exprtk typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; typedef typename parser_t::unknown_symbol_resolver usr_t; - struct resolve_as_vector : public parser_t::unknown_symbol_resolver + struct resolve_as_vector : public usr_t { typedef exprtk::parser parser_t; + using usr_t::process; + resolve_as_vector() : usr_t(usr_t::e_usrmode_extended) {} virtual bool process(const std::string& unknown_symbol, symbol_table_t& symbol_table, - std::string&) + std::string&) exprtk_override { static T v[1]; symbol_table.add_vector(unknown_symbol,v); @@ -37682,7 +42051,9 @@ namespace exprtk const symbol_table& sym_table = e.get_symbol_table(); if (!sym_table.valid()) + { return std::numeric_limits::quiet_NaN(); + } details::variable_node* var = sym_table.get_variable(variable_name); @@ -37695,8 +42066,8 @@ namespace exprtk return result; } - else - return std::numeric_limits::quiet_NaN(); + + return std::numeric_limits::quiet_NaN(); } template @@ -37786,8 +42157,8 @@ namespace exprtk return result; } - else - return std::numeric_limits::quiet_NaN(); + + return std::numeric_limits::quiet_NaN(); } template @@ -37813,8 +42184,8 @@ namespace exprtk return result; } - else - return std::numeric_limits::quiet_NaN(); + + return std::numeric_limits::quiet_NaN(); } template @@ -37840,8 +42211,8 @@ namespace exprtk return result; } - else - return std::numeric_limits::quiet_NaN(); + + return std::numeric_limits::quiet_NaN(); } /* @@ -38120,97 +42491,98 @@ namespace exprtk disable_has_side_effects(*this); } - virtual ~polynomial() {} + virtual ~polynomial() + {} #define poly_rtrn(NN) \ return (NN != N) ? std::numeric_limits::quiet_NaN() : - inline virtual T operator() (const T& x, const T& c1, const T& c0) + inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override { poly_rtrn(1) (poly_impl::evaluate(x, c1, c0)); } - inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) + inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override { poly_rtrn(2) (poly_impl::evaluate(x, c2, c1, c0)); } - inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) + inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override { poly_rtrn(3) (poly_impl::evaluate(x, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, - const T& c0) + const T& c0) exprtk_override { poly_rtrn(4) (poly_impl::evaluate(x, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, - const T& c1, const T& c0) + const T& c1, const T& c0) exprtk_override { poly_rtrn(5) (poly_impl::evaluate(x, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, - const T& c2, const T& c1, const T& c0) + const T& c2, const T& c1, const T& c0) exprtk_override { poly_rtrn(6) (poly_impl::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, - const T& c3, const T& c2, const T& c1, const T& c0) + const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override { poly_rtrn(7) (poly_impl::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, - const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override { poly_rtrn(8) (poly_impl::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, - const T& c0) + const T& c0) exprtk_override { poly_rtrn(9) (poly_impl::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, - const T& c1, const T& c0) + const T& c1, const T& c0) exprtk_override { poly_rtrn(10) (poly_impl::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, - const T& c2, const T& c1, const T& c0) + const T& c2, const T& c1, const T& c0) exprtk_override { poly_rtrn(11) (poly_impl::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, - const T& c3, const T& c2, const T& c1, const T& c0) + const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override { poly_rtrn(12) (poly_impl::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } #undef poly_rtrn - inline virtual T operator() () + inline virtual T operator() () exprtk_override { return std::numeric_limits::quiet_NaN(); } - inline virtual T operator() (const T&) + inline virtual T operator() (const T&) exprtk_override { return std::numeric_limits::quiet_NaN(); } - inline virtual T operator() (const T&, const T&) + inline virtual T operator() (const T&, const T&) exprtk_override { return std::numeric_limits::quiet_NaN(); } @@ -38312,6 +42684,50 @@ namespace exprtk return (*this); } + inline function& vars(const std::string& v0, + const std::string& v1) + { + v_.push_back(v0); + v_.push_back(v1); + return (*this); + } + + inline function& vars(const std::string& v0, + const std::string& v1, + const std::string& v2) + { + v_.push_back(v0); + v_.push_back(v1); + v_.push_back(v2); + return (*this); + } + + inline function& vars(const std::string& v0, + const std::string& v1, + const std::string& v2, + const std::string& v3) + { + v_.push_back(v0); + v_.push_back(v1); + v_.push_back(v2); + v_.push_back(v3); + return (*this); + } + + inline function& vars(const std::string& v0, + const std::string& v1, + const std::string& v2, + const std::string& v3, + const std::string& v4) + { + v_.push_back(v0); + v_.push_back(v1); + v_.push_back(v2); + v_.push_back(v3); + v_.push_back(v4); + return (*this); + } + std::string name_; std::string expression_; std::deque v_; @@ -38321,12 +42737,14 @@ namespace exprtk struct base_func : public exprtk::ifunction { - typedef const T& type; - typedef exprtk::ifunction function_t; - typedef std::vector varref_t; - typedef std::vector var_t; + typedef const T& type; + typedef exprtk::ifunction function_t; + typedef std::vector varref_t; + typedef std::vector var_t; + typedef std::vector str_t; typedef std::pair lvarref_t; typedef std::vector lvr_vec_t; + typedef std::vector lstr_vec_t; using exprtk::ifunction::operator(); @@ -38338,10 +42756,11 @@ namespace exprtk v.resize(pc); } - virtual ~base_func() {} + virtual ~base_func() + {} - #define exprtk_assign(Index) \ - (*v[Index]) = v##Index; \ + #define exprtk_assign(Index) \ + (*v[Index]) = v##Index; \ inline void update(const T& v0) { @@ -38387,17 +42806,33 @@ namespace exprtk { expression = expr; - typedef typename expression_t::control_block::local_data_list_t ldl_t; + typedef typename expression_t::control_block ctrlblk_t; + typedef typename ctrlblk_t::local_data_list_t ldl_t; + typedef typename ctrlblk_t::data_type data_t; + typedef typename ldl_t::value_type ldl_value_type; const ldl_t ldl = expr.local_data_list(); - std::vector index_list; + std::vector > index_list; for (std::size_t i = 0; i < ldl.size(); ++i) { + exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", + static_cast(i), + expression_t::control_block::to_str(ldl[i].type).c_str(), + static_cast(ldl[i].size))); + + switch (ldl[i].type) + { + case ctrlblk_t::e_unknown : continue; + case ctrlblk_t::e_expr : continue; + case ctrlblk_t::e_vecholder : continue; + default : break; + } + if (ldl[i].size) { - index_list.push_back(i); + index_list.push_back(std::make_pair(i,ldl[i].type)); } } @@ -38405,19 +42840,34 @@ namespace exprtk for (std::size_t i = 0; i < index_list.size(); ++i) { - const std::size_t index = index_list[i]; + const std::size_t index = index_list[i].first; + const ldl_value_type& local_var = ldl[index]; + + assert(local_var.pointer); if (i < (index_list.size() - v.size())) { - lv.push_back( - std::make_pair( - reinterpret_cast(ldl[index].pointer), - ldl[index].size)); + if (local_var.type == ctrlblk_t::e_string) + { + local_str_vars.push_back( + reinterpret_cast(local_var.pointer)); + } + else if ( + (local_var.type == ctrlblk_t::e_data ) || + (local_var.type == ctrlblk_t::e_vecdata) + ) + { + local_vars.push_back(std::make_pair( + reinterpret_cast(local_var.pointer), + local_var.size)); - local_var_stack_size += ldl[index].size; + local_var_stack_size += local_var.size; + } } else - v[input_param_count++] = reinterpret_cast(ldl[index].pointer); + { + v[input_param_count++] = reinterpret_cast(local_var.pointer); + } } clear_stack(); @@ -38433,14 +42883,21 @@ namespace exprtk { var_t var_stack(v.size(),T(0)); copy(v,var_stack); - param_stack.push_back(var_stack); + input_params_stack.push_back(var_stack); + } + + if (!local_vars.empty()) + { + var_t local_vec_frame(local_var_stack_size,T(0)); + copy(local_vars,local_vec_frame); + local_var_stack.push_back(local_vec_frame); } - if (!lv.empty()) + if (!local_str_vars.empty()) { - var_t local_var_stack(local_var_stack_size,T(0)); - copy(lv,local_var_stack); - local_stack.push_back(local_var_stack); + str_t local_str_frame(local_str_vars.size()); + copy(local_str_vars,local_str_frame); + local_str_stack.push_back(local_str_frame); } } } @@ -38451,14 +42908,20 @@ namespace exprtk { if (!v.empty()) { - copy(param_stack.back(),v); - param_stack.pop_back(); + copy(input_params_stack.back(), v); + input_params_stack.pop_back(); } - if (!lv.empty()) + if (!local_vars.empty()) { - copy(local_stack.back(),lv); - local_stack.pop_back(); + copy(local_var_stack.back(), local_vars); + local_var_stack.pop_back(); + } + + if (!local_str_vars.empty()) + { + copy(local_str_stack.back(), local_str_vars); + local_str_stack.pop_back(); } } } @@ -38471,6 +42934,14 @@ namespace exprtk } } + void copy(const lstr_vec_t& src_v, str_t& dest_v) + { + for (std::size_t i = 0; i < src_v.size(); ++i) + { + dest_v[i] = (*src_v[i]); + } + } + void copy(const var_t& src_v, varref_t& dest_v) { for (std::size_t i = 0; i < src_v.size(); ++i) @@ -38503,9 +42974,12 @@ namespace exprtk typename var_t::const_iterator itr = src_v.begin(); typedef typename std::iterator_traits::difference_type diff_t; - for (std::size_t i = 0; i < src_v.size(); ++i) + for (std::size_t i = 0; i < dest_v.size(); ++i) { - lvarref_t vr = dest_v[i]; + lvarref_t& vr = dest_v[i]; + + assert(vr.first != 0); + assert(vr.second > 0); if (1 == vr.second) (*vr.first) = *itr++; @@ -38517,6 +42991,16 @@ namespace exprtk } } + void copy(const str_t& src_str, lstr_vec_t& dest_str) + { + assert(src_str.size() == dest_str.size()); + + for (std::size_t i = 0; i < dest_str.size(); ++i) + { + *dest_str[i] = src_str[i]; + } + } + inline void clear_stack() { for (std::size_t i = 0; i < v.size(); ++i) @@ -38530,29 +43014,19 @@ namespace exprtk return e.value(); } - expression_t expression; - varref_t v; - lvr_vec_t lv; - std::size_t local_var_stack_size; - std::size_t stack_depth; - std::deque param_stack; - std::deque local_stack; + expression_t expression; + varref_t v; + lvr_vec_t local_vars; + lstr_vec_t local_str_vars; + std::size_t local_var_stack_size; + std::size_t stack_depth; + std::deque input_params_stack; + std::deque local_var_stack; + std::deque local_str_stack; }; typedef std::map funcparam_t; - struct func_0param : public base_func - { - using exprtk::ifunction::operator(); - - func_0param() : base_func(0) {} - - inline T operator() () - { - return this->value(base_func::expression); - } - }; - typedef const T& type; template @@ -38577,13 +43051,26 @@ namespace exprtk scoped_bft& operator=(const scoped_bft&) exprtk_delete; }; + struct func_0param : public base_func + { + using exprtk::ifunction::operator(); + + func_0param() : base_func(0) {} + + inline T operator() () exprtk_override + { + scoped_bft sb(*this); + return this->value(base_func::expression); + } + }; + struct func_1param : public base_func { using exprtk::ifunction::operator(); func_1param() : base_func(1) {} - inline T operator() (type v0) + inline T operator() (type v0) exprtk_override { scoped_bft sb(*this); base_func::update(v0); @@ -38597,7 +43084,7 @@ namespace exprtk func_2param() : base_func(2) {} - inline T operator() (type v0, type v1) + inline T operator() (type v0, type v1) exprtk_override { scoped_bft sb(*this); base_func::update(v0, v1); @@ -38611,7 +43098,7 @@ namespace exprtk func_3param() : base_func(3) {} - inline T operator() (type v0, type v1, type v2) + inline T operator() (type v0, type v1, type v2) exprtk_override { scoped_bft sb(*this); base_func::update(v0, v1, v2); @@ -38625,7 +43112,7 @@ namespace exprtk func_4param() : base_func(4) {} - inline T operator() (type v0, type v1, type v2, type v3) + inline T operator() (type v0, type v1, type v2, type v3) exprtk_override { scoped_bft sb(*this); base_func::update(v0, v1, v2, v3); @@ -38639,7 +43126,7 @@ namespace exprtk func_5param() : base_func(5) {} - inline T operator() (type v0, type v1, type v2, type v3, type v4) + inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override { scoped_bft sb(*this); base_func::update(v0, v1, v2, v3, v4); @@ -38653,7 +43140,7 @@ namespace exprtk func_6param() : base_func(6) {} - inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) + inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override { scoped_bft sb(*this); base_func::update(v0, v1, v2, v3, v4, v5); @@ -38680,14 +43167,14 @@ namespace exprtk return result; } - #define def_fp_retval(N) \ - struct func_##N##param_retval : public func_##N##param \ - { \ - inline T value(expression_t& e) \ - { \ - return return_value(e); \ - } \ - }; \ + #define def_fp_retval(N) \ + struct func_##N##param_retval exprtk_final : public func_##N##param \ + { \ + inline T value(expression_t& e) exprtk_override \ + { \ + return return_value(e); \ + } \ + }; \ def_fp_retval(0) def_fp_retval(1) @@ -38697,6 +43184,8 @@ namespace exprtk def_fp_retval(5) def_fp_retval(6) + #undef def_fp_retval + template class Sequence> inline bool add(const std::string& name, @@ -38739,16 +43228,20 @@ namespace exprtk public: function_compositor() - : parser_(settings_t::compile_all_opts + + : parser_(settings_t::default_compile_all_opts + settings_t::e_disable_zero_return) , fp_map_(7) + , load_variables_(false) + , load_vectors_(false) {} - function_compositor(const symbol_table_t& st) + explicit function_compositor(const symbol_table_t& st) : symbol_table_(st) - , parser_(settings_t::compile_all_opts + + , parser_(settings_t::default_compile_all_opts + settings_t::e_disable_zero_return) , fp_map_(7) + , load_variables_(false) + , load_vectors_(false) {} ~function_compositor() @@ -38771,6 +43264,46 @@ namespace exprtk auxiliary_symtab_list_.push_back(&symtab); } + void load_variables(const bool load = true) + { + load_variables_ = load; + } + + void load_vectors(const bool load = true) + { + load_vectors_ = load; + } + + inline void register_loop_runtime_check(loop_runtime_check& lrtchk) + { + parser_.register_loop_runtime_check(lrtchk); + } + + inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) + { + parser_.register_vector_access_runtime_check(vartchk); + } + + inline void register_compilation_timeout_check(compilation_check& compchk) + { + parser_.register_compilation_timeout_check(compchk); + } + + inline void clear_loop_runtime_check() + { + parser_.clear_loop_runtime_check(); + } + + inline void clear_vector_access_runtime_check() + { + parser_.clear_vector_access_runtime_check(); + } + + inline void clear_compilation_timeout_check() + { + parser_.clear_compilation_timeout_check(); + } + void clear() { symbol_table_.clear(); @@ -38789,6 +43322,10 @@ namespace exprtk fp_map_[i].clear(); } + + clear_loop_runtime_check (); + clear_vector_access_runtime_check(); + clear_compilation_timeout_check (); } inline bool add(const function& f, const bool override = false) @@ -38796,6 +43333,31 @@ namespace exprtk return add(f.name_, f.expression_, f.v_,override); } + inline std::string error() const + { + if (!error_list_.empty()) + { + return error_list_[0].diagnostic; + } + else + return std::string("No Error"); + } + + inline std::size_t error_count() const + { + return error_list_.size(); + } + + inline parser_error::type get_error(const std::size_t& index) const + { + if (index < error_list_.size()) + { + return error_list_[index]; + } + + throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); + } + private: template expr_map_; std::vector fp_map_; std::vector auxiliary_symtab_list_; + std::deque error_list_; + bool load_variables_; + bool load_vectors_; }; // class function_compositor } // namespace exprtk -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +#if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) # ifndef NOMINMAX # define NOMINMAX # endif @@ -39001,9 +43592,11 @@ namespace exprtk { public: - #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) timer() : in_use_(false) + , start_time_{ {0, 0} } + , stop_time_ { {0, 0} } { QueryPerformanceFrequency(&clock_frequency_); } @@ -39081,7 +43674,7 @@ namespace exprtk bool in_use_; - #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) LARGE_INTEGER start_time_; LARGE_INTEGER stop_time_; LARGE_INTEGER clock_frequency_; @@ -39114,7 +43707,23 @@ namespace exprtk const T v, exprtk::details::numeric::details::real_type_tag) { - printf(fmt.c_str(),v); + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wformat-nonliteral" + #elif defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wformat-nonliteral" + #elif defined(_MSC_VER) + #endif + + printf(fmt.c_str(), v); + + #if defined(__clang__) + #pragma clang diagnostic pop + #elif defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic pop + #elif defined(_MSC_VER) + #endif } template @@ -39174,19 +43783,19 @@ namespace exprtk } // namespace exprtk::rtl::io::details template - struct print : public exprtk::igeneric_function + struct print exprtk_final : public exprtk::igeneric_function { typedef typename igeneric_function::parameter_list_t parameter_list_t; using exprtk::igeneric_function::operator(); - print(const std::string& scalar_format = "%10.5f") + explicit print(const std::string& scalar_format = "%10.5f") : scalar_format_(scalar_format) { exprtk::enable_zero_parameters(*this); } - inline T operator() (parameter_list_t parameters) + inline T operator() (parameter_list_t parameters) exprtk_override { details::print_impl::process(scalar_format_,parameters); return T(0); @@ -39196,19 +43805,19 @@ namespace exprtk }; template - struct println : public exprtk::igeneric_function + struct println exprtk_final : public exprtk::igeneric_function { typedef typename igeneric_function::parameter_list_t parameter_list_t; using exprtk::igeneric_function::operator(); - println(const std::string& scalar_format = "%10.5f") + explicit println(const std::string& scalar_format = "%10.5f") : scalar_format_(scalar_format) { exprtk::enable_zero_parameters(*this); } - inline T operator() (parameter_list_t parameters) + inline T operator() (parameter_list_t parameters) exprtk_override { details::print_impl::process(scalar_format_,parameters); printf("\n"); @@ -39290,8 +43899,8 @@ namespace exprtk return false; } - else - stream_ptr = stream; + + stream_ptr = stream; return true; } @@ -39306,8 +43915,8 @@ namespace exprtk return false; } - else - stream_ptr = stream; + + stream_ptr = stream; return true; } @@ -39322,13 +43931,13 @@ namespace exprtk return false; } - else - stream_ptr = stream; + + stream_ptr = stream; return true; } - else - return false; + + return false; } template @@ -39475,12 +44084,13 @@ namespace exprtk #ifdef _MSC_VER #pragma warning(pop) #endif + assert(sizeof(T) <= sizeof(void*)); } } // namespace exprtk::rtl::io::file::details template - class open : public exprtk::igeneric_function + class open exprtk_final : public exprtk::igeneric_function { public: @@ -39489,18 +44099,20 @@ namespace exprtk typedef typename igfun_t::generic_type generic_type; typedef typename generic_type::string_view string_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); open() : exprtk::igeneric_function("S|SS") { details::perform_check(); } - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const std::string file_name = to_str(string_t(parameters[0])); if (file_name.empty()) + { return T(0); + } if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) { @@ -39532,7 +44144,7 @@ namespace exprtk }; template - struct close : public exprtk::ifunction + struct close exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); @@ -39540,7 +44152,7 @@ namespace exprtk : exprtk::ifunction(1) { details::perform_check(); } - inline T operator() (const T& v) + inline T operator() (const T& v) exprtk_override { details::file_descriptor* fd = details::make_handle(v); @@ -39554,7 +44166,7 @@ namespace exprtk }; template - class write : public exprtk::igeneric_function + class write exprtk_final : public exprtk::igeneric_function { public: @@ -39565,13 +44177,13 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); write() : igfun_t("TS|TST|TV|TVT") { details::perform_check(); } - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); @@ -39611,7 +44223,7 @@ namespace exprtk }; template - class read : public exprtk::igeneric_function + class read exprtk_final : public exprtk::igeneric_function { public: @@ -39622,13 +44234,13 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); read() : igfun_t("TS|TST|TV|TVT") { details::perform_check(); } - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); @@ -39668,7 +44280,7 @@ namespace exprtk }; template - class getline : public exprtk::igeneric_function + class getline exprtk_final : public exprtk::igeneric_function { public: @@ -39678,14 +44290,13 @@ namespace exprtk typedef typename generic_type::string_view string_t; typedef typename generic_type::scalar_view scalar_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); getline() : igfun_t("T",igfun_t::e_rtrn_string) { details::perform_check(); } - inline T operator() (std::string& result, - parameter_list_t parameters) + inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override { details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); return T(fd->getline(result) ? 1 : 0); @@ -39693,7 +44304,7 @@ namespace exprtk }; template - struct eof : public exprtk::ifunction + struct eof exprtk_final : public exprtk::ifunction { using exprtk::ifunction::operator(); @@ -39701,10 +44312,9 @@ namespace exprtk : exprtk::ifunction(1) { details::perform_check(); } - inline T operator() (const T& v) + inline T operator() (const T& v) exprtk_override { details::file_descriptor* fd = details::make_handle(v); - return (fd->eof() ? T(1) : T(0)); } }; @@ -39814,44 +44424,61 @@ namespace exprtk } // namespace exprtk::rtl::details template - class all_true : public exprtk::igeneric_function + class all_true exprtk_final : public exprtk::igeneric_function { public: typedef typename exprtk::igeneric_function igfun_t; typedef typename igfun_t::parameter_list_t parameter_list_t; typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); all_true() - : exprtk::igeneric_function("V|VTT") + : exprtk::igeneric_function("V|VTT|T*") /* Overloads: 0. V - vector 1. VTT - vector, r0, r1 + 2. T* - T....T */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { - const vector_t vec(parameters[0]); + if (2 == ps_index) + { + for (std::size_t i = 0; i < parameters.size(); ++i) + { + if (scalar_t(parameters[i])() == T(0)) + { + return T(0); + } + } + } + else + { + const vector_t vec(parameters[0]); - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + { + return std::numeric_limits::quiet_NaN(); + } - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] == T(0)) + for (std::size_t i = r0; i <= r1; ++i) { - return T(0); + if (vec[i] == T(0)) + { + return T(0); + } } } @@ -39860,44 +44487,61 @@ namespace exprtk }; template - class all_false : public exprtk::igeneric_function + class all_false exprtk_final : public exprtk::igeneric_function { public: typedef typename exprtk::igeneric_function igfun_t; typedef typename igfun_t::parameter_list_t parameter_list_t; typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); all_false() - : exprtk::igeneric_function("V|VTT") + : exprtk::igeneric_function("V|VTT|T*") /* Overloads: 0. V - vector 1. VTT - vector, r0, r1 + 2. T* - T....T */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { - const vector_t vec(parameters[0]); + if (2 == ps_index) + { + for (std::size_t i = 0; i < parameters.size(); ++i) + { + if (scalar_t(parameters[i])() != T(0)) + { + return T(0); + } + } + } + else + { + const vector_t vec(parameters[0]); - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + { + return std::numeric_limits::quiet_NaN(); + } - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] != T(0)) + for (std::size_t i = r0; i <= r1; ++i) { - return T(0); + if (vec[i] != T(0)) + { + return T(0); + } } } @@ -39906,44 +44550,61 @@ namespace exprtk }; template - class any_true : public exprtk::igeneric_function + class any_true exprtk_final : public exprtk::igeneric_function { public: typedef typename exprtk::igeneric_function igfun_t; typedef typename igfun_t::parameter_list_t parameter_list_t; typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); any_true() - : exprtk::igeneric_function("V|VTT") + : exprtk::igeneric_function("V|VTT|T*") /* Overloads: 0. V - vector 1. VTT - vector, r0, r1 + 2. T* - T....T */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { - const vector_t vec(parameters[0]); + if (2 == ps_index) + { + for (std::size_t i = 0; i < parameters.size(); ++i) + { + if (scalar_t(parameters[i])() != T(0)) + { + return T(1); + } + } + } + else + { + const vector_t vec(parameters[0]); - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + { + return std::numeric_limits::quiet_NaN(); + } - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] != T(0)) + for (std::size_t i = r0; i <= r1; ++i) { - return T(1); + if (vec[i] != T(0)) + { + return T(1); + } } } @@ -39952,44 +44613,61 @@ namespace exprtk }; template - class any_false : public exprtk::igeneric_function + class any_false exprtk_final : public exprtk::igeneric_function { public: typedef typename exprtk::igeneric_function igfun_t; typedef typename igfun_t::parameter_list_t parameter_list_t; typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); any_false() - : exprtk::igeneric_function("V|VTT") + : exprtk::igeneric_function("V|VTT|T*") /* Overloads: 0. V - vector 1. VTT - vector, r0, r1 + 2. T* - T....T */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { - const vector_t vec(parameters[0]); + if (2 == ps_index) + { + for (std::size_t i = 0; i < parameters.size(); ++i) + { + if (scalar_t(parameters[i])() == T(0)) + { + return T(1); + } + } + } + else + { + const vector_t vec(parameters[0]); - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + { + return std::numeric_limits::quiet_NaN(); + } - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] == T(0)) + for (std::size_t i = r0; i <= r1; ++i) { - return T(1); + if (vec[i] == T(0)) + { + return T(1); + } } } @@ -39998,44 +44676,58 @@ namespace exprtk }; template - class count : public exprtk::igeneric_function + class count exprtk_final : public exprtk::igeneric_function { public: typedef typename exprtk::igeneric_function igfun_t; typedef typename igfun_t::parameter_list_t parameter_list_t; typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); count() - : exprtk::igeneric_function("V|VTT") + : exprtk::igeneric_function("V|VTT|T*") /* Overloads: 0. V - vector 1. VTT - vector, r0, r1 + 2. T* - T....T */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { - const vector_t vec(parameters[0]); + std::size_t cnt = 0; - std::size_t r0 = 0; - std::size_t r1 = vec.size() - 1; + if (2 == ps_index) + { + for (std::size_t i = 0; i < parameters.size(); ++i) + { + if (scalar_t(parameters[i])() != T(0)) ++cnt; + } + } + else + { + const vector_t vec(parameters[0]); - if ( - (1 == ps_index) && - !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) - ) - return std::numeric_limits::quiet_NaN(); + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; - std::size_t cnt = 0; + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + { + return std::numeric_limits::quiet_NaN(); + } - for (std::size_t i = r0; i <= r1; ++i) - { - if (vec[i] != T(0)) ++cnt; + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] != T(0)) ++cnt; + } } return T(cnt); @@ -40043,7 +44735,7 @@ namespace exprtk }; template - class copy : public exprtk::igeneric_function + class copy exprtk_final : public exprtk::igeneric_function { public: @@ -40053,7 +44745,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); copy() : exprtk::igeneric_function("VV|VTTVTT") @@ -40064,7 +44756,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t x(parameters[0]); vector_t y(parameters[(0 == ps_index) ? 1 : 3]); @@ -40096,7 +44788,7 @@ namespace exprtk }; template - class rol : public exprtk::igeneric_function + class rol exprtk_final : public exprtk::igeneric_function { public: @@ -40106,7 +44798,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); rol() : exprtk::igeneric_function("VT|VTTT") @@ -40117,7 +44809,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { vector_t vec(parameters[0]); @@ -40147,7 +44839,7 @@ namespace exprtk }; template - class ror : public exprtk::igeneric_function + class ror exprtk_final : public exprtk::igeneric_function { public: @@ -40157,7 +44849,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); ror() : exprtk::igeneric_function("VT|VTTT") @@ -40168,7 +44860,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { vector_t vec(parameters[0]); @@ -40185,8 +44877,8 @@ namespace exprtk ) return T(0); - std::size_t dist = r1 - r0 + 1; - std::size_t shift = (dist - (n % dist)) % dist; + const std::size_t dist = r1 - r0 + 1; + const std::size_t shift = (dist - (n % dist)) % dist; std::rotate( vec.begin() + r0, @@ -40198,7 +44890,7 @@ namespace exprtk }; template - class shift_left : public exprtk::igeneric_function + class reverse exprtk_final : public exprtk::igeneric_function { public: @@ -40208,7 +44900,48 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); + + reverse() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override + { + vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + return T(0); + + std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); + + return T(1); + } + }; + + template + class shift_left exprtk_final : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using igfun_t::operator(); shift_left() : exprtk::igeneric_function("VT|VTTT") @@ -40219,7 +44952,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { vector_t vec(parameters[0]); @@ -40246,7 +44979,7 @@ namespace exprtk vec.begin() + r0 + n, vec.begin() + r1 + 1); - for (std::size_t i = r1 - n + 1; i <= r1; ++i) + for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) { vec[i] = T(0); } @@ -40256,7 +44989,7 @@ namespace exprtk }; template - class shift_right : public exprtk::igeneric_function + class shift_right exprtk_final : public exprtk::igeneric_function { public: @@ -40266,7 +44999,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); shift_right() : exprtk::igeneric_function("VT|VTTT") @@ -40277,7 +45010,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { vector_t vec(parameters[0]); @@ -40316,7 +45049,7 @@ namespace exprtk }; template - class sort : public exprtk::igeneric_function + class sort exprtk_final : public exprtk::igeneric_function { public: @@ -40326,7 +45059,7 @@ namespace exprtk typedef typename generic_type::string_view string_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); sort() : exprtk::igeneric_function("V|VTT|VS|VSTT") @@ -40339,7 +45072,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { vector_t vec(parameters[0]); @@ -40379,7 +45112,7 @@ namespace exprtk }; template - class nthelement : public exprtk::igeneric_function + class nthelement exprtk_final : public exprtk::igeneric_function { public: @@ -40389,7 +45122,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); nthelement() : exprtk::igeneric_function("VT|VTTT") @@ -40400,7 +45133,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { vector_t vec(parameters[0]); @@ -40412,7 +45145,9 @@ namespace exprtk return T(0); if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) + { return std::numeric_limits::quiet_NaN(); + } std::nth_element( vec.begin() + r0, @@ -40424,7 +45159,7 @@ namespace exprtk }; template - class iota : public exprtk::igeneric_function + class assign exprtk_final : public exprtk::igeneric_function { public: @@ -40434,41 +45169,101 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); + + assign() + : exprtk::igeneric_function("VT|VTTT|VTTTT") + /* + Overloads: + 0. VT - vector, V + 1. VTTT - vector, V, r0, r1 + 2. VTTTT - vector, V, r0, r1, SS + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override + { + vector_t vec(parameters[0]); + + const T assign_value = scalar_t(parameters[1]); + + const std::size_t step_size = (2 != ps_index) ? 1 : + static_cast(scalar_t(parameters.back())()); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + ((ps_index == 1) || (ps_index == 2)) && + !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0) + ) + { + return T(0); + } + + for (std::size_t i = r0; i <= r1; i += step_size) + { + vec[i] = assign_value; + } + + return T(1); + } + }; + + template + class iota exprtk_final : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using igfun_t::operator(); iota() - : exprtk::igeneric_function("VT|VTT|VTTT|VTTTT") + : exprtk::igeneric_function("VTT|VT|VTTTT|VTTT") /* Overloads: - 0. VT - vector, increment - 1. VTT - vector, increment, base - 2. VTTTT - vector, increment, r0, r1 - 3. VTTTT - vector, increment, base, r0, r1 + 0. VTT - vector, SV, SS + 1. VT - vector, SV, SS (+1) + 2. VTTT - vector, r0, r1, SV, SS + 3. VTT - vector, r0, r1, SV, SS (+1) + + Where: + 1. SV - Start value + 2. SS - Step size */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { vector_t vec(parameters[0]); - T increment = scalar_t(parameters[1])(); - T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0); + const T start_value = (ps_index <= 1) ? + scalar_t(parameters[1]) : + scalar_t(parameters[3]) ; + + const T step_size = ((0 == ps_index) || (2 == ps_index)) ? + scalar_t(parameters.back())() : + T(1) ; std::size_t r0 = 0; std::size_t r1 = vec.size() - 1; - if ((2 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 2, 3, 0)) - return std::numeric_limits::quiet_NaN(); - else if ((3 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 3, 4, 0)) - return std::numeric_limits::quiet_NaN(); - else + if ( + ((ps_index == 2) || (ps_index == 3)) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) { - long long j = 0; + return T(0); + } - for (std::size_t i = r0; i <= r1; ++i, ++j) - { - vec[i] = base + (increment * j); - } + for (std::size_t i = r0; i <= r1; ++i) + { + vec[i] = start_value + ((i - r0) * step_size); } return T(1); @@ -40476,40 +45271,50 @@ namespace exprtk }; template - class sumk : public exprtk::igeneric_function + class sumk exprtk_final : public exprtk::igeneric_function { public: typedef typename exprtk::igeneric_function igfun_t; typedef typename igfun_t::parameter_list_t parameter_list_t; typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); sumk() - : exprtk::igeneric_function("V|VTT") + : exprtk::igeneric_function("V|VTT|VTTT") /* Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 + 0. V - vector + 1. VTT - vector, r0, r1 + 2. VTTT - vector, r0, r1, stride */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t vec(parameters[0]); + const std::size_t stride = (2 != ps_index) ? 1 : + static_cast(scalar_t(parameters[3])()); + std::size_t r0 = 0; std::size_t r1 = vec.size() - 1; - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0)) + if ( + ((1 == ps_index) || (2 == ps_index)) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + { return std::numeric_limits::quiet_NaN(); + } T result = T(0); T error = T(0); - for (std::size_t i = r0; i <= r1; ++i) + for (std::size_t i = r0; i <= r1; i += stride) { details::kahan_sum(result, error, vec[i]); } @@ -40519,7 +45324,7 @@ namespace exprtk }; template - class axpy : public exprtk::igeneric_function + class axpy exprtk_final : public exprtk::igeneric_function { public: @@ -40529,7 +45334,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); axpy() : exprtk::igeneric_function("TVV|TVVTT") @@ -40541,7 +45346,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t x(parameters[1]); vector_t y(parameters[2]); @@ -40566,7 +45371,7 @@ namespace exprtk }; template - class axpby : public exprtk::igeneric_function + class axpby exprtk_final : public exprtk::igeneric_function { public: @@ -40576,7 +45381,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); axpby() : exprtk::igeneric_function("TVTV|TVTVTT") @@ -40588,7 +45393,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t x(parameters[1]); vector_t y(parameters[3]); @@ -40614,7 +45419,7 @@ namespace exprtk }; template - class axpyz : public exprtk::igeneric_function + class axpyz exprtk_final : public exprtk::igeneric_function { public: @@ -40624,7 +45429,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); axpyz() : exprtk::igeneric_function("TVVV|TVVVTT") @@ -40636,7 +45441,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t x(parameters[1]); const vector_t y(parameters[2]); @@ -40645,7 +45450,7 @@ namespace exprtk std::size_t r0 = 0; std::size_t r1 = std::min(x.size(),y.size()) - 1; - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 3, 4, 1)) + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 4, 5, 1)) return std::numeric_limits::quiet_NaN(); else if (helper::invalid_range(y, r0, r1)) return std::numeric_limits::quiet_NaN(); @@ -40664,7 +45469,7 @@ namespace exprtk }; template - class axpbyz : public exprtk::igeneric_function + class axpbyz exprtk_final : public exprtk::igeneric_function { public: @@ -40674,7 +45479,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); axpbyz() : exprtk::igeneric_function("TVTVV|TVTVVTT") @@ -40686,7 +45491,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t x(parameters[1]); const vector_t y(parameters[3]); @@ -40695,7 +45500,7 @@ namespace exprtk std::size_t r0 = 0; std::size_t r1 = std::min(x.size(),y.size()) - 1; - if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 4, 5, 1)) + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 5, 6, 1)) return std::numeric_limits::quiet_NaN(); else if (helper::invalid_range(y, r0, r1)) return std::numeric_limits::quiet_NaN(); @@ -40715,7 +45520,7 @@ namespace exprtk }; template - class axpbz : public exprtk::igeneric_function + class axpbsy exprtk_final : public exprtk::igeneric_function { public: @@ -40725,7 +45530,110 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); + + axpbsy() + : exprtk::igeneric_function("TVTTV|TVTTVTT") + /* + y <- ax + by + Overloads: + 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) + 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override + { + const vector_t x(parameters[1]); + vector_t y(parameters[4]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 5, 6, 1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(y, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + const T b = scalar_t(parameters[2])(); + + const std::size_t s = static_cast(scalar_t(parameters[3])()); + + for (std::size_t i = r0; i <= r1; ++i) + { + y[i] = (a * x[i]) + (b * y[i + s]); + } + + return T(1); + } + }; + + template + class axpbsyz exprtk_final : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using igfun_t::operator(); + + axpbsyz() + : exprtk::igeneric_function("TVTTVV|TVTTVVTT") + /* + z <- ax + by + Overloads: + 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) + 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override + { + const vector_t x(parameters[1]); + const vector_t y(parameters[4]); + vector_t z(parameters[5]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !helper::load_vector_range::process(parameters, r0, r1, 6, 7, 1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(y, r0, r1)) + return std::numeric_limits::quiet_NaN(); + else if (helper::invalid_range(z, r0, r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + const T b = scalar_t(parameters[2])(); + + const std::size_t s = static_cast(scalar_t(parameters[3])()); + + for (std::size_t i = r0; i <= r1; ++i) + { + z[i] = (a * x[i]) + (b * y[i + s]); + } + + return T(1); + } + }; + + template + class axpbz exprtk_final : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using igfun_t::operator(); axpbz() : exprtk::igeneric_function("TVTV|TVTVTT") @@ -40737,7 +45645,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t x(parameters[1]); vector_t z(parameters[3]); @@ -40763,7 +45671,7 @@ namespace exprtk }; template - class dot : public exprtk::igeneric_function + class diff exprtk_final : public exprtk::igeneric_function { public: @@ -40773,7 +45681,55 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); + + diff() + : exprtk::igeneric_function("VV|VVT") + /* + x_(i - stride) - x_i + Overloads: + 0. VV - x(vector), y(vector) + 1. VVT - x(vector), y(vector), stride + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override + { + const vector_t x(parameters[0]); + vector_t y(parameters[1]); + + const std::size_t r0 = 0; + const std::size_t r1 = std::min(x.size(),y.size()) - 1; + + const std::size_t stride = (1 != ps_index) ? 1 : + std::min(r1,static_cast(scalar_t(parameters[2])())); + + for (std::size_t i = 0; i < stride; ++i) + { + y[i] = std::numeric_limits::quiet_NaN(); + } + + for (std::size_t i = (r0 + stride); i <= r1; ++i) + { + y[i] = x[i] - x[i - stride]; + } + + return T(1); + } + }; + + template + class dot exprtk_final : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using igfun_t::operator(); dot() : exprtk::igeneric_function("VV|VVTT") @@ -40784,7 +45740,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t x(parameters[0]); const vector_t y(parameters[1]); @@ -40809,7 +45765,7 @@ namespace exprtk }; template - class dotk : public exprtk::igeneric_function + class dotk exprtk_final : public exprtk::igeneric_function { public: @@ -40819,7 +45775,7 @@ namespace exprtk typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; - using exprtk::igeneric_function::operator(); + using igfun_t::operator(); dotk() : exprtk::igeneric_function("VV|VVTT") @@ -40830,7 +45786,7 @@ namespace exprtk */ {} - inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override { const vector_t x(parameters[0]); const vector_t y(parameters[1]); @@ -40855,30 +45811,155 @@ namespace exprtk } }; + template + class threshold_below exprtk_final : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using igfun_t::operator(); + + threshold_below() + : exprtk::igeneric_function("VTT|VTTTT") + /* + Overloads: + 0. VTT - vector, TV, SV + 1. VTTTT - vector, r0, r1, TV, SV + + Where: + TV - Threshold value + SV - Snap-to value + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override + { + vector_t vec(parameters[0]); + + const T threshold_value = (0 == ps_index) ? + scalar_t(parameters[1]) : + scalar_t(parameters[3]) ; + + const T snap_value = scalar_t(parameters.back()); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + { + return T(0); + } + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] < threshold_value) + { + vec[i] = snap_value; + } + } + + return T(1); + } + }; + + template + class threshold_above exprtk_final : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using igfun_t::operator(); + + threshold_above() + : exprtk::igeneric_function("VTT|VTTTT") + /* + Overloads: + 0. VTT - vector, TV, SV + 1. VTTTT - vector, r0, r1, TV, SV + + Where: + TV - Threshold value + SV - Snap-to value + */ + {} + + inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override + { + vector_t vec(parameters[0]); + + const T threshold_value = (0 == ps_index) ? + scalar_t(parameters[1]) : + scalar_t(parameters[3]) ; + + const T snap_value = scalar_t(parameters.back()); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ( + (1 == ps_index) && + !helper::load_vector_range::process(parameters, r0, r1, 1, 2, 0) + ) + { + return T(0); + } + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] > threshold_value) + { + vec[i] = snap_value; + } + } + + return T(1); + } + }; + template struct package { - all_true at; - all_false af; - any_true nt; - any_false nf; - count c; - copy cp; - rol rl; - ror rr; - shift_left sl; - shift_right sr; - sort st; - nthelement ne; - iota ia; - sumk sk; - axpy b1_axpy; - axpby b1_axpby; - axpyz b1_axpyz; - axpbyz b1_axpbyz; - axpbz b1_axpbz; - dot dt; - dotk dtk; + all_true at; + all_false af; + any_true nt; + any_false nf; + count c; + copy cp; + rol rl; + ror rr; + reverse rev; + shift_left sl; + shift_right sr; + sort st; + nthelement ne; + assign an; + iota ia; + sumk sk; + axpy b1_axpy; + axpby b1_axpby; + axpyz b1_axpyz; + axpbyz b1_axpbyz; + axpbsy b1_axpbsy; + axpbsyz b1_axpbsyz; + axpbz b1_axpbz; + diff df; + dot dt; + dotk dtk; + threshold_above ta; + threshold_below tb; bool register_package(exprtk::symbol_table& symtab) { @@ -40891,29 +45972,36 @@ namespace exprtk return false; \ } \ - exprtk_register_function("all_true" , at ) - exprtk_register_function("all_false" , af ) - exprtk_register_function("any_true" , nt ) - exprtk_register_function("any_false" , nf ) - exprtk_register_function("count" , c ) - exprtk_register_function("copy" , cp ) - exprtk_register_function("rotate_left" , rl ) - exprtk_register_function("rol" , rl ) - exprtk_register_function("rotate_right" , rr ) - exprtk_register_function("ror" , rr ) - exprtk_register_function("shftl" , sl ) - exprtk_register_function("shftr" , sr ) - exprtk_register_function("sort" , st ) - exprtk_register_function("nth_element" , ne ) - exprtk_register_function("iota" , ia ) - exprtk_register_function("sumk" , sk ) - exprtk_register_function("axpy" , b1_axpy ) - exprtk_register_function("axpby" , b1_axpby ) - exprtk_register_function("axpyz" , b1_axpyz ) - exprtk_register_function("axpbyz" , b1_axpbyz) - exprtk_register_function("axpbz" , b1_axpbz ) - exprtk_register_function("dot" , dt ) - exprtk_register_function("dotk" , dtk ) + exprtk_register_function("all_true" , at ) + exprtk_register_function("all_false" , af ) + exprtk_register_function("any_true" , nt ) + exprtk_register_function("any_false" , nf ) + exprtk_register_function("count" , c ) + exprtk_register_function("copy" , cp ) + exprtk_register_function("rotate_left" , rl ) + exprtk_register_function("rol" , rl ) + exprtk_register_function("rotate_right" , rr ) + exprtk_register_function("ror" , rr ) + exprtk_register_function("reverse" , rev ) + exprtk_register_function("shftl" , sl ) + exprtk_register_function("shftr" , sr ) + exprtk_register_function("sort" , st ) + exprtk_register_function("nth_element" , ne ) + exprtk_register_function("assign" , an ) + exprtk_register_function("iota" , ia ) + exprtk_register_function("sumk" , sk ) + exprtk_register_function("axpy" , b1_axpy ) + exprtk_register_function("axpby" , b1_axpby ) + exprtk_register_function("axpyz" , b1_axpyz ) + exprtk_register_function("axpbyz" , b1_axpbyz ) + exprtk_register_function("axpbsy" , b1_axpbsy ) + exprtk_register_function("axpbsyz" , b1_axpbsyz) + exprtk_register_function("axpbz" , b1_axpbz ) + exprtk_register_function("diff" , df ) + exprtk_register_function("dot" , dt ) + exprtk_register_function("dotk" , dtk ) + exprtk_register_function("threshold_above" , ta ) + exprtk_register_function("threshold_below" , tb ) #undef exprtk_register_function return true; @@ -40932,11 +46020,11 @@ namespace exprtk using ::exprtk::details::char_cptr; static char_cptr library = "Mathematical Expression Toolkit"; - static char_cptr version = "2.71828182845904523536028747135266" - "2497757247093699959574966967627724" - "0766303535475945713821785251664274" - "2746639193200305992181741359662904"; - static char_cptr date = "20230101"; + static char_cptr version = "2.718281828459045235360287471352662497757" + "24709369995957496696762772407663035354759" + "45713821785251664274274663919320030599218" + "17413596629043572900334295260595630738132"; + static char_cptr date = "20240101"; static char_cptr min_cpp = "199711L"; static inline std::string data() @@ -40958,12 +46046,8 @@ namespace exprtk #undef exprtk_error_location #endif - #ifdef exprtk_disable_fallthrough_begin - #undef exprtk_disable_fallthrough_begin - #endif - - #ifdef exprtk_disable_fallthrough_end - #undef exprtk_disable_fallthrough_end + #ifdef exprtk_fallthrough + #undef exprtk_fallthrough #endif #ifdef exprtk_override diff --git a/src/third_party/exprtk/exprtk_benchmark.cpp b/src/third_party/exprtk/exprtk_benchmark.cpp index 54bbcc2..c989954 100644 --- a/src/third_party/exprtk/exprtk_benchmark.cpp +++ b/src/third_party/exprtk/exprtk_benchmark.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * ExprTk vs Native Benchmarks * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -18,7 +19,6 @@ #include #include -#include #include #include #include @@ -26,26 +26,26 @@ #include "exprtk.hpp" -const std::string global_expression_list[] - = { - "(y + x)", - "2 * (y + x)", - "(2 * y + 2 * x)", - "((1.23 * x^2) / y) - 123.123", - "(y + x / y) * (x - y / x)", - "x / ((x + y) + (x - y)) / y", - "1 - ((x * y) + (y / x)) - 3", - "(5.5 + x) + (2 * x - 2 / 3 * y) * (x / 3 + y / 4) + (y + 7.7)", - "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^15 - 5.5x^23 + 6.6y^55", - "sin(2 * x) + cos(pi / y)", - "1 - sin(2 * x) + cos(pi / y)", - "sqrt(111.111 - sin(2 * x) + cos(pi / y) / 333.333)", - "(x^2 / sin(2 * pi / y)) - x / 2", - "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", - "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", - "if((y + (x * 2.2)) <= (x + y + 1.1), x - y, x * y) + 2 * pi / x" - }; +const std::string global_expression_list[] = + { + "(y + x)", + "2 * (y + x)", + "(2 * y + 2 * x)", + "((1.23 * x^2) / y) - 123.123", + "(y + x / y) * (x - y / x)", + "x / ((x + y) + (x - y)) / y", + "1 - ((x * y) + (y / x)) - 3", + "(5.5 + x) + (2 * x - 2 / 3 * y) * (x / 3 + y / 4) + (y + 7.7)", + "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^15 - 5.5x^23 + 6.6y^55", + "sin(2 * x) + cos(pi / y)", + "1 - sin(2 * x) + cos(pi / y)", + "sqrt(111.111 - sin(2 * x) + cos(pi / y) / 333.333)", + "(x^2 / sin(2 * pi / y)) - x / 2", + "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", + "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", + "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", + "if((y + (x * 2.2)) <= (x + y + 1.1), x - y, x * y) + 2 * pi / x" + }; const std::size_t global_expression_list_size = sizeof(global_expression_list) / sizeof(std::string); @@ -323,7 +323,7 @@ int main(int argc, char* argv[]) } { - std::cout << "--- EXPRTK ---" << std::endl; + printf("--- EXPRTK ---\n"); for (std::size_t i = 0; i < compiled_expr_list.size(); ++i) { run_exprtk_benchmark(x,y,compiled_expr_list[i],global_expression_list[i]); @@ -331,28 +331,28 @@ int main(int argc, char* argv[]) } { - std::cout << "--- NATIVE ---" << std::endl; - run_native_benchmark(x,y,native::func00,global_expression_list[ 0]); - run_native_benchmark(x,y,native::func01,global_expression_list[ 1]); - run_native_benchmark(x,y,native::func02,global_expression_list[ 2]); - run_native_benchmark(x,y,native::func03,global_expression_list[ 3]); - run_native_benchmark(x,y,native::func04,global_expression_list[ 4]); - run_native_benchmark(x,y,native::func05,global_expression_list[ 5]); - run_native_benchmark(x,y,native::func06,global_expression_list[ 6]); - run_native_benchmark(x,y,native::func07,global_expression_list[ 7]); - run_native_benchmark(x,y,native::func08,global_expression_list[ 8]); - run_native_benchmark(x,y,native::func09,global_expression_list[ 9]); - run_native_benchmark(x,y,native::func10,global_expression_list[10]); - run_native_benchmark(x,y,native::func11,global_expression_list[11]); - run_native_benchmark(x,y,native::func12,global_expression_list[12]); - run_native_benchmark(x,y,native::func13,global_expression_list[13]); - run_native_benchmark(x,y,native::func14,global_expression_list[14]); - run_native_benchmark(x,y,native::func15,global_expression_list[15]); - run_native_benchmark(x,y,native::func16,global_expression_list[16]); + printf("--- NATIVE ---\n"); + run_native_benchmark(x, y, native::func00,global_expression_list[ 0]); + run_native_benchmark(x, y, native::func01,global_expression_list[ 1]); + run_native_benchmark(x, y, native::func02,global_expression_list[ 2]); + run_native_benchmark(x, y, native::func03,global_expression_list[ 3]); + run_native_benchmark(x, y, native::func04,global_expression_list[ 4]); + run_native_benchmark(x, y, native::func05,global_expression_list[ 5]); + run_native_benchmark(x, y, native::func06,global_expression_list[ 6]); + run_native_benchmark(x, y, native::func07,global_expression_list[ 7]); + run_native_benchmark(x, y, native::func08,global_expression_list[ 8]); + run_native_benchmark(x, y, native::func09,global_expression_list[ 9]); + run_native_benchmark(x, y, native::func10,global_expression_list[10]); + run_native_benchmark(x, y, native::func11,global_expression_list[11]); + run_native_benchmark(x, y, native::func12,global_expression_list[12]); + run_native_benchmark(x, y, native::func13,global_expression_list[13]); + run_native_benchmark(x, y, native::func14,global_expression_list[14]); + run_native_benchmark(x, y, native::func15,global_expression_list[15]); + run_native_benchmark(x, y, native::func16,global_expression_list[16]); } { - std::cout << "--- PARSE ----" << std::endl; + printf("--- PARSE ----\n"); run_parse_benchmark(symbol_table); } @@ -396,7 +396,7 @@ double pgo_primer() return total; } -std::size_t load_expression_file(const std::string& file_name, std::deque& expression_list) +inline std::size_t load_expression_file(const std::string& file_name, std::deque& expression_list) { std::ifstream stream(file_name.c_str()); @@ -426,7 +426,7 @@ void perform_file_based_benchmark(const std::string& file_name, const std::size_ if (0 == load_expression_file(file_name,expr_str_list)) { - std::cout << "Failed to load any expressions from: " << file_name << "\n"; + printf("Failed to load any expressions from: %s\n", file_name.c_str()); return; } @@ -446,6 +446,8 @@ void perform_file_based_benchmark(const std::string& file_name, const std::size_ double z = 4.123456; double w = 5.123456; + exprtk::rtl::vecops::package vector_package; + symbol_table.add_variable("a", a); symbol_table.add_variable("b", b); symbol_table.add_variable("c", c); @@ -481,6 +483,9 @@ void perform_file_based_benchmark(const std::string& file_name, const std::size_ symbol_table.add_function("poly11", poly11); symbol_table.add_function("poly12", poly12); + symbol_table.add_package(vector_package); + + static double e = exprtk::details::numeric::constant::e; symbol_table.add_variable("e", e, true); diff --git a/src/third_party/exprtk/exprtk_simple_example_01.cpp b/src/third_party/exprtk/exprtk_simple_example_01.cpp index d20e2ed..52c5565 100644 --- a/src/third_party/exprtk/exprtk_simple_example_01.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_01.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 1 * - * Author: Arash Partow (1999-2023) * + * Simple Example 01 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -30,7 +31,7 @@ void trig_function() typedef exprtk::parser parser_t; const std::string expression_string = - "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)"; + "clamp(-1.0, sin(2 * pi * x) + cos(x / 2 * pi), +1.0)"; T x; diff --git a/src/third_party/exprtk/exprtk_simple_example_02.cpp b/src/third_party/exprtk/exprtk_simple_example_02.cpp index 77c8c60..279046a 100644 --- a/src/third_party/exprtk/exprtk_simple_example_02.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_02.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 2 * - * Author: Arash Partow (1999-2023) * + * Simple Example 02 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -29,15 +30,15 @@ void square_wave() typedef exprtk::expression expression_t; typedef exprtk::parser parser_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))"; + const std::string expression_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); @@ -55,7 +56,7 @@ void square_wave() expression.register_symbol_table(symbol_table); parser_t parser; - parser.compile(expr_string,expression); + parser.compile(expression_string,expression); const T delta = (T(4) * pi) / T(1000); diff --git a/src/third_party/exprtk/exprtk_simple_example_03.cpp b/src/third_party/exprtk/exprtk_simple_example_03.cpp index e133df0..3b8ad07 100644 --- a/src/third_party/exprtk/exprtk_simple_example_03.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_03.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 3 * - * Author: Arash Partow (1999-2023) * + * Simple Example 03 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -30,7 +31,7 @@ void polynomial() typedef exprtk::parser parser_t; const std::string expression_string = - "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1"; + "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1"; const T r0 = T(0); const T r1 = T(1); diff --git a/src/third_party/exprtk/exprtk_simple_example_04.cpp b/src/third_party/exprtk/exprtk_simple_example_04.cpp index 69a663e..04a4b3f 100644 --- a/src/third_party/exprtk/exprtk_simple_example_04.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_04.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 4 * - * Author: Arash Partow (1999-2023) * + * Simple Example 04 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -31,31 +32,32 @@ void fibonacci() typedef exprtk::function_compositor compositor_t; typedef typename compositor_t::function function_t; - compositor_t compositor; + T x = T(0); - compositor - .add( - function_t( // define function: fibonacci(x) - "fibonacci", - " var w := 0; " - " var y := 0; " - " var z := 1; " - " switch " - " { " - " case x == 0 : 0; " - " case x == 1 : 1; " - " default : " - " while ((x -= 1) > 0) " - " { " - " w := z; " - " z := z + y; " - " y := w; " - " z " - " }; " - " } ", - "x")); + compositor_t compositor; - T x = T(0); + compositor.add( + function_t("fibonacci") + .var("x") + .expression + ( + " switch " + " { " + " case x == 0 : 0; " + " case x == 1 : 1; " + " default : " + " { " + " var prev := 0; " + " var curr := 1; " + " while ((x -= 1) > 0) " + " { " + " var temp := prev; " + " prev := curr; " + " curr += temp; " + " }; " + " }; " + " } " + )); symbol_table_t& symbol_table = compositor.symbol_table(); symbol_table.add_constants(); diff --git a/src/third_party/exprtk/exprtk_simple_example_05.cpp b/src/third_party/exprtk/exprtk_simple_example_05.cpp index fdbabc9..3eb4a4f 100644 --- a/src/third_party/exprtk/exprtk_simple_example_05.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_05.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 5 * - * Author: Arash Partow (1999-2023) * + * Simple Example 05 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -31,14 +32,14 @@ struct myfunc : public exprtk::ifunction : exprtk::ifunction(2) { exprtk::disable_has_side_effects(*this); } - inline T operator()(const T& v1, const T& v2) + T operator()(const T& v1, const T& v2) { return T(1) + (v1 * v2) / T(3); } }; template -inline T myotherfunc(T v0, T v1, T v2) +T myotherfunc(T v0, T v1, T v2) { return std::abs(v0 - v1) * v2; } @@ -51,7 +52,7 @@ void custom_function() typedef exprtk::parser parser_t; 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 y = T(2); diff --git a/src/third_party/exprtk/exprtk_simple_example_06.cpp b/src/third_party/exprtk/exprtk_simple_example_06.cpp index b50660b..dbb805d 100644 --- a/src/third_party/exprtk/exprtk_simple_example_06.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_06.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 6 * - * Author: Arash Partow (1999-2023) * + * Simple Example 06 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -30,10 +31,10 @@ void vector_function() typedef exprtk::parser parser_t; const std::string expression_string = - " for (var i := 0; i < min(x[],y[],z[]); i += 1) " - " { " - " z[i] := 3sin(x[i]) + 2log(y[i]); " - " } "; + " for (var i := 0; i < min(x[], y[], z[]); i += 1) " + " { " + " z[i] := 3sin(x[i]) + 2log(y[i]); " + " } "; T x[] = { T(1.1), T(2.2), T(3.3), T(4.4), T(5.5) }; T y[] = { T(1.1), T(2.2), T(3.3), T(4.4), T(5.5) }; diff --git a/src/third_party/exprtk/exprtk_simple_example_07.cpp b/src/third_party/exprtk/exprtk_simple_example_07.cpp index 845b158..85e94f1 100644 --- a/src/third_party/exprtk/exprtk_simple_example_07.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_07.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 7 * - * Author: Arash Partow (1999-2023) * + * Simple Example 07 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ diff --git a/src/third_party/exprtk/exprtk_simple_example_08.cpp b/src/third_party/exprtk/exprtk_simple_example_08.cpp index bfacb1e..f82b992 100644 --- a/src/third_party/exprtk/exprtk_simple_example_08.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_08.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 8 * - * Author: Arash Partow (1999-2023) * + * Simple Example 08 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -28,27 +29,29 @@ void composite() typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; - typedef exprtk::parser_error::type error_t; + typedef exprtk::parser_error::type err_t; typedef exprtk::function_compositor compositor_t; typedef typename compositor_t::function function_t; - compositor_t compositor; - T x = T(1); T y = T(2); + compositor_t compositor; + symbol_table_t& symbol_table = compositor.symbol_table(); symbol_table.add_constants(); symbol_table.add_variable("x",x); symbol_table.add_variable("y",y); - compositor - .add( - function_t("f","sin(x / pi)","x")); // f(x) = sin(x / pi) + compositor.add( + function_t("f") // f(x) = sin(x / pi) + .var("x") + .expression( "sin(x / pi)" )); - compositor - .add( - function_t("g","3*[f(x) + f(y)]","x","y")); // g(x,y) = 3[f(x) + f(y)] + compositor.add( + function_t("g") // g(x,y) = 3[f(x) + f(y)] + .vars("x", "y") + .expression( "3*[f(x) + f(y)]" )); std::string expression_string = "g(1 + f(x), f(y) / 2)"; @@ -65,7 +68,7 @@ void composite() for (std::size_t i = 0; i < parser.error_count(); ++i) { - const 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(i), diff --git a/src/third_party/exprtk/exprtk_simple_example_09.cpp b/src/third_party/exprtk/exprtk_simple_example_09.cpp index 8934523..f7cd0f2 100644 --- a/src/third_party/exprtk/exprtk_simple_example_09.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_09.cpp @@ -2,8 +2,8 @@ ************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Simple Example 9 * - * Author: Arash Partow (1999-2023) * + * Simple Example 09 * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -41,76 +42,98 @@ void primes() compositor_t compositor(symbol_table); //Mode 1 - if statement based - compositor - .add( - function_t( // define function: is_prime_impl1(x,y) - "is_prime_impl1", - " if (y == 1,true, " - " if (0 == (x % y),false, " - " is_prime_impl1(x,y - 1))) ", - "x","y")); - - compositor - .add( - function_t( // define function: is_prime1(x) - "is_prime1", - " if (frac(x) != 0, false, " - " if (x <= 0, false, " - " is_prime_impl1(x,min(x - 1,trunc(sqrt(x)) + 1)))) ", - "x")); + compositor.add( + function_t("is_prime_impl1") + .vars("x", "y") + .expression + ( + " if (y == 1,true, " + " if (0 == (x % y),false, " + " is_prime_impl1(x,y - 1))) " + )); + + compositor.add( + function_t("is_prime1") + .var("x") + .expression + ( + " if (frac(x) != 0) " + " return [false]; " + " else if (x <= 0) " + " return [false]; " + " else " + " is_prime_impl1(x,min(x - 1,trunc(sqrt(x)) + 1)); " + )); //Mode 2 - switch statement based - compositor - .add( - function_t( // define function: is_prime_impl2(x,y) - "is_prime_impl2", - " switch " - " { " - " case y == 1 : true; " - " case (x % y) == 0 : false; " - " default : is_prime_impl2(x,y - 1); " - " } ", - "x","y")); - - compositor - .add( - function_t( // define function: is_prime2(x) - "is_prime2", - " switch " - " { " - " case x <= 0 : false; " - " case frac(x) != 0 : false; " - " default : is_prime_impl2(x,min(x - 1,trunc(sqrt(x)) + 1)); " - " } ", - "x")); - - //Mode 3 - switch statement and while-loop based - compositor - .add( - function_t( // define function: is_prime_impl3(x,y) - "is_prime_impl3", - " while (y > 0) " - " { " - " switch " - " { " - " case y == 1 : ~(y := 0,true); " - " case (x % y) == 0 : ~(y := 0,false); " - " default : y := y - 1; " - " } " - " } ", - "x","y")); - - compositor - .add( - function_t( // define function: is_prime3(x) - "is_prime3", - " switch " - " { " - " case x <= 0 : false; " - " case frac(x) != 0 : false; " - " default : is_prime_impl3(x,min(x - 1,trunc(sqrt(x)) + 1)); " - " } ", - "x")); + compositor.add( + function_t("is_prime_impl2") + .vars("x", "y") + .expression + ( + " switch " + " { " + " case y == 1 : true; " + " case (x % y) == 0 : false; " + " default : is_prime_impl2(x,y - 1); " + " } " + )); + + compositor.add( + function_t("is_prime2") + .var("x") + .expression + ( + " switch " + " { " + " case x <= 0 : false; " + " case frac(x) != 0 : false; " + " default : is_prime_impl2(x,min(x - 1,trunc(sqrt(x)) + 1)); " + " } " + )); + + //Mode 3 - switch statement and for-loop based + compositor.add( + function_t("is_prime3") + .var("x") + .expression + ( + " switch " + " { " + " case x <= 1 : return [false]; " + " case frac(x) != 0 : return [false]; " + " case x == 2 : return [true ]; " + " }; " + " " + " var prime_lut[27] := " + " { " + " 2, 3, 5, 7, 11, 13, 17, 19, 23, " + " 29, 31, 37, 41, 43, 47, 53, 59, 61, " + " 67, 71, 73, 79, 83, 89, 97, 101, 103 " + " }; " + " " + " var upper_bound := min(x - 1, trunc(sqrt(x)) + 1); " + " " + " for (var i := 0; i < prime_lut[]; i += 1) " + " { " + " if (prime_lut[i] >= upper_bound) " + " return [true]; " + " else if ((x % prime_lut[i]) == 0) " + " return [false]; " + " }; " + " " + " var lower_bound := prime_lut[prime_lut[] - 1] + 2; " + " " + " for (var i := lower_bound; i < upper_bound; i += 2) " + " { " + " if ((x % i) == 0) " + " { " + " return [false]; " + " } " + " }; " + " " + " return [true]; " + )); std::string expression_str1 = "is_prime1(x)"; std::string expression_str2 = "is_prime2(x)"; @@ -125,11 +148,11 @@ void primes() parser_t parser; - parser.compile(expression_str1,expression1); - parser.compile(expression_str2,expression2); - parser.compile(expression_str3,expression3); + parser.compile(expression_str1, expression1); + parser.compile(expression_str2, expression2); + parser.compile(expression_str3, expression3); - for (std::size_t i = 0; i < 100; ++i) + for (std::size_t i = 0; i < 15000; ++i) { x = static_cast(i); @@ -137,11 +160,16 @@ void primes() const T result2 = expression2.value(); const T result3 = expression3.value(); - printf("%03d Result1: %c Result2: %c Result3: %c\n", + const bool results_concur = (result1 == result2) && + (result1 == result3) ; + + printf("%03d Result1: %c Result2: %c Result3: %c " + "Results Concur: %c\n", static_cast(i), (result1 == T(1)) ? 'T' : 'F', (result2 == T(1)) ? 'T' : 'F', - (result3 == T(1)) ? 'T' : 'F'); + (result3 == T(1)) ? 'T' : 'F', + (results_concur) ? 'T' : 'F'); } } diff --git a/src/third_party/exprtk/exprtk_simple_example_10.cpp b/src/third_party/exprtk/exprtk_simple_example_10.cpp index 0a0add4..87b4058 100644 --- a/src/third_party/exprtk/exprtk_simple_example_10.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_10.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 10 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -41,28 +42,29 @@ void newton_sqrt() compositor_t compositor(symbol_table); - compositor - .add( - function_t( // define function: newton_sqrt(x) - "newton_sqrt", - " 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")); + compositor.add( + function_t("newton_sqrt") + .var("x") + .expression + ( + " 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); " + " }; " + " } " + )); const std::string expression_str = "newton_sqrt(x)"; @@ -72,16 +74,19 @@ void newton_sqrt() parser_t parser; parser.compile(expression_str,expression); - for (std::size_t i = 0; i < 100; ++i) + for (std::size_t i = 0; i < 1000; ++i) { x = static_cast(i); const T result = expression.value(); + const T real = std::sqrt(x); + const T error = std::abs(result - real); - printf("sqrt(%03d) - Result: %15.13f\tReal: %15.13f\n", + printf("sqrt(%03d) - Result: %15.13f\tReal: %15.13f\tError: %18.16f\n", static_cast(i), result, - std::sqrt(x)); + real, + error); } } diff --git a/src/third_party/exprtk/exprtk_simple_example_11.cpp b/src/third_party/exprtk/exprtk_simple_example_11.cpp index fdf123c..8a26fb5 100644 --- a/src/third_party/exprtk/exprtk_simple_example_11.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_11.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 11 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -30,12 +31,14 @@ void square_wave2() typedef exprtk::parser parser_t; const std::string wave_program = - " var r := 0; " - " for (var i := 0; i < 1000; i += 1) " - " { " - " r += (1 / (2i + 1)) * sin((4i + 2) * pi * f * t); " - " }; " - " r *= a * (4 / pi); "; + " var r := 0; " + " " + " for (var i := 0; i < 1000; i += 1) " + " { " + " r += (1 / (2i + 1)) * sin((4i + 2) * pi * f * t); " + " }; " + " " + " r *= a * (4 / pi); "; static const T pi = T(3.141592653589793238462643383279502); diff --git a/src/third_party/exprtk/exprtk_simple_example_12.cpp b/src/third_party/exprtk/exprtk_simple_example_12.cpp index aafeebb..8045de4 100644 --- a/src/third_party/exprtk/exprtk_simple_example_12.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_12.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 12 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,12 +11,12 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ -#include #include #include "exprtk.hpp" @@ -30,25 +30,25 @@ void bubble_sort() typedef exprtk::parser parser_t; const std::string bubblesort_program = - " var upper_bound := v[]; " - " var swapped := false; " - " repeat " - " swapped := false; " - " for (var i := 0; i < upper_bound; i += 1) " - " { " - " for (var j := i + 1; j < upper_bound; j += 1) " - " { " - " if (v[i] > v[j]) " - " { " - " v[i] <=> v[j]; " - " swapped := true; " - " }; " - " }; " - " }; " - " upper_bound -= 1; " - " until (not(swapped) or (upper_bound == 0)); "; + " var upper_bound := v[]; " + " " + " repeat " + " var new_upper_bound := 0; " + " " + " for (var i := 1; i < upper_bound; i += 1) " + " { " + " if (v[i - 1] > v[i]) " + " { " + " v[i - 1] <=> v[i]; " + " new_upper_bound := i; " + " }; " + " }; " + " " + " upper_bound := new_upper_bound; " + " " + " until (upper_bound <= 1); "; - T v[] = { T(9.9), T(2.2), T(1.1), T(5.5), T(7.7), T(4.4), T(3.3) }; + T v[] = { T(9.1), T(2.2), T(1.3), T(5.4), T(7.5), T(4.6), T(3.7) }; symbol_table_t symbol_table; symbol_table.add_vector("v",v); diff --git a/src/third_party/exprtk/exprtk_simple_example_13.cpp b/src/third_party/exprtk/exprtk_simple_example_13.cpp index 29ac239..cebdf73 100644 --- a/src/third_party/exprtk/exprtk_simple_example_13.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_13.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 13 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -32,30 +33,30 @@ void savitzky_golay_filter() typedef exprtk::parser parser_t; const std::string sgfilter_program = - " var weight[9] := " - " { " - " -21, 14, 39, " - " 54, 59, 54, " - " 39, 14, -21 " - " }; " - " " - " if (v_in[] >= weight[]) " - " { " - " var lower_bound := trunc(weight[] / 2); " - " var upper_bound := v_in[] - lower_bound; " - " " - " v_out := 0; " - " " - " for (var i := lower_bound; i < upper_bound; i += 1) " - " { " - " for (var j := -lower_bound; j <= lower_bound; j += 1) " - " { " - " v_out[i] += weight[j + lower_bound] * v_in[i + j]; " - " }; " - " }; " - " " - " v_out /= sum(weight); " - " } "; + " var weight[9] := " + " { " + " -21, 14, 39, " + " 54, 59, 54, " + " 39, 14, -21 " + " }; " + " " + " if (v_in[] >= weight[]) " + " { " + " const var lower_bound := trunc(weight[] / 2); " + " const var upper_bound := v_in[] - lower_bound; " + " " + " v_out := 0; " + " " + " for (var i := lower_bound; i < upper_bound; i += 1) " + " { " + " for (var j := -lower_bound; j <= lower_bound; j += 1) " + " { " + " v_out[i] += weight[j + lower_bound] * v_in[i + j]; " + " }; " + " }; " + " " + " v_out /= sum(weight); " + " } "; const std::size_t n = 1024; diff --git a/src/third_party/exprtk/exprtk_simple_example_14.cpp b/src/third_party/exprtk/exprtk_simple_example_14.cpp index 259067b..56208e1 100644 --- a/src/third_party/exprtk/exprtk_simple_example_14.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_14.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 14 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -29,15 +30,15 @@ void stddev_example() typedef exprtk::parser parser_t; const std::string stddev_program = - " var x[25] := { " - " 1, 2, 3, 4, 5, " - " 6, 7, 8, 9, 10, " - " 11, 12, 13, 14, 15, " - " 16, 17, 18, 19, 20, " - " 21, 22, 23, 24, 25 " - " }; " - " " - " sqrt(sum([x - avg(x)]^2) / x[]) "; + " var x[25] := { " + " 1, 2, 3, 4, 5, " + " 6, 7, 8, 9, 10, " + " 11, 12, 13, 14, 15, " + " 16, 17, 18, 19, 20, " + " 21, 22, 23, 24, 25 " + " }; " + " " + " sqrt(sum([x - avg(x)]^2) / x[]) "; expression_t expression; diff --git a/src/third_party/exprtk/exprtk_simple_example_15.cpp b/src/third_party/exprtk/exprtk_simple_example_15.cpp index 7affeb7..3dc6d4d 100644 --- a/src/third_party/exprtk/exprtk_simple_example_15.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_15.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 15 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -30,20 +31,20 @@ void black_scholes_merton_model() typedef exprtk::parser parser_t; 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); " - " " - " if (callput_flag == 'call') " - " s * ncdf(d1) - x * e^(-r * t) * ncdf(d2); " - " else if (callput_flag == 'put') " - " x * e^(-r * t) * ncdf(-d2) - s * ncdf(-d1); " - " "; - - T s = T(60.00); // Stock price - T x = T(65.00); // Strike price + " var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); " + " var d2 := d1 - v * sqrt(t); " + " " + " if (callput_flag == 'call') " + " s * ncdf(d1) - k * e^(-r * t) * ncdf(d2); " + " else if (callput_flag == 'put') " + " k * e^(-r * t) * ncdf(-d2) - s * ncdf(-d1); " + " "; + + T s = T(60.00); // Spot / Stock / Underlying / Base price + T k = T(65.00); // Strike price + T v = T( 0.30); // Volatility T t = T( 0.25); // Years to maturity T r = T( 0.08); // Risk free rate - T v = T( 0.30); // Volatility std::string callput_flag; @@ -51,7 +52,7 @@ void black_scholes_merton_model() symbol_table_t symbol_table; symbol_table.add_variable("s",s); - symbol_table.add_variable("x",x); + symbol_table.add_variable("k",k); symbol_table.add_variable("t",t); symbol_table.add_variable("r",r); symbol_table.add_variable("v",v); @@ -64,27 +65,27 @@ void black_scholes_merton_model() parser_t parser; parser.compile(bsm_model_program,expression); - { - callput_flag = "call"; + callput_flag = "call"; + + const T bsm_call_option_price = expression.value(); + + callput_flag = "put"; - const T bsm = expression.value(); + const T bsm_put_option_price = expression.value(); - 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, - bsm); - } + printf("BSM(call, %5.3f, %5.3f, %5.3f, %5.3f, %5.3f) = %10.6f\n", + s, k, t, r, v, + bsm_call_option_price); - { - callput_flag = "put"; + printf("BSM(put , %5.3f, %5.3f, %5.3f, %5.3f, %5.3f) = %10.6f\n", + s, k, t, r, v, + bsm_put_option_price); - const T bsm = expression.value(); + const T put_call_parity_diff = + (bsm_call_option_price - bsm_put_option_price) - + (s - k * std::exp(-r * t)); - 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, - bsm); - } + printf("Put-Call parity difference: %20.17f\n", put_call_parity_diff); } int main() diff --git a/src/third_party/exprtk/exprtk_simple_example_16.cpp b/src/third_party/exprtk/exprtk_simple_example_16.cpp index 2480500..13593db 100644 --- a/src/third_party/exprtk/exprtk_simple_example_16.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_16.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 16 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -31,21 +32,21 @@ void linear_least_squares() typedef exprtk::parser parser_t; const std::string linear_least_squares_program = - " if (x[] == y[]) " - " { " - " beta := (sum(x * y) - sum(x) * sum(y) / x[]) / " - " (sum(x^2) - sum(x)^2 / x[]); " - " " - " alpha := avg(y) - beta * avg(x); " - " " - " rmse := sqrt(sum((beta * x + alpha - y)^2) / y[]); " - " } " - " else " - " { " - " alpha := null; " - " beta := null; " - " rmse := null; " - " } "; + " if (x[] == y[]) " + " { " + " beta := (sum(x * y) - sum(x) * sum(y) / x[]) / " + " (sum(x^2) - sum(x)^2 / x[]); " + " " + " alpha := avg(y) - beta * avg(x); " + " " + " rmse := sqrt(sum((beta * x + alpha - y)^2) / y[]); " + " } " + " else " + " { " + " alpha := null; " + " beta := null; " + " rmse := null; " + " } "; T x[] = {T( 1), T( 2), T(3), T( 4), T( 5), T(6), T( 7), T( 8), T( 9), T(10)}; T y[] = {T(8.7), T(6.8), T(6), T(5.6), T(3.8), T(3), T(2.4), T(1.7), T(0.4), T(-1)}; diff --git a/src/third_party/exprtk/exprtk_simple_example_17.cpp b/src/third_party/exprtk/exprtk_simple_example_17.cpp index 24ae15b..2c2221c 100644 --- a/src/third_party/exprtk/exprtk_simple_example_17.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_17.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 17 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -48,8 +49,8 @@ void monte_carlo_pi() typedef exprtk::parser parser_t; const std::string monte_carlo_pi_program = - " var experiments[5 * 10^7] := [(rnd_01^2 + rnd_01^2) <= 1]; " - " 4 * sum(experiments) / experiments[]; "; + " var samples[2 * 10^8] := [(rnd_01^2 + rnd_01^2) <= 1]; " + " 4 * sum(samples) / samples[]; "; rnd_01 rnd01; diff --git a/src/third_party/exprtk/exprtk_simple_example_18.cpp b/src/third_party/exprtk/exprtk_simple_example_18.cpp index ad4631e..f4c714b 100644 --- a/src/third_party/exprtk/exprtk_simple_example_18.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_18.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 18 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -30,31 +31,31 @@ void file_io() typedef exprtk::parser parser_t; const std::string fileio_program = - " var file_name := 'file.txt'; " - " var stream := null; " - " " - " if (stream := open(file_name,'w')) " - " println('Successfully opened file: ' + file_name); " - " else " - " { " - " println('Failed to open file: ' + file_name); " - " return [false]; " - " } " - " " - " var s := 'Hello world...\n'; " - " " - " for (var i := 0; i < 10; i += 1) " - " { " - " write(stream,s); " - " } " - " " - " if (close(stream)) " - " println('Sucessfully closed file: ' + file_name); " - " else " - " { " - " println('Failed to close file: ' + file_name); " - " return [false]; " - " } "; + " var file_name := 'file.txt'; " + " var stream := null; " + " " + " if (stream := open(file_name,'w')) " + " println('Successfully opened file: ' + file_name); " + " else " + " { " + " println('Failed to open file: ' + file_name); " + " return [false]; " + " }; " + " " + " var s := 'Hello world...\n'; " + " " + " for (var i := 0; i < 10; i += 1) " + " { " + " write(stream,s); " + " }; " + " " + " if (close(stream)) " + " println('Sucessfully closed file: ' + file_name); " + " else " + " { " + " println('Failed to close file: ' + file_name); " + " return [false]; " + " } "; exprtk::rtl::io::file::package fileio_package; exprtk::rtl::io::println println; diff --git a/src/third_party/exprtk/exprtk_simple_example_19.cpp b/src/third_party/exprtk/exprtk_simple_example_19.cpp index 7929b8b..0aac6fc 100644 --- a/src/third_party/exprtk/exprtk_simple_example_19.cpp +++ b/src/third_party/exprtk/exprtk_simple_example_19.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Simple Example 19 * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -38,11 +39,11 @@ class randu : public exprtk::igeneric_function randu() : exprtk::igeneric_function("V|VTT") - /* - Overloads: - 0. V - vector - 1. VTT - vector, r0, r1 - */ + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ { ::srand(static_cast(time(NULL))); } inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) @@ -52,10 +53,11 @@ class randu : public exprtk::igeneric_function std::size_t r0 = 0; std::size_t r1 = v.size() - 1; + using namespace exprtk::rtl::vecops::helper; + if ( (1 == ps_index) && - !exprtk::rtl::vecops::helper:: - load_vector_range::process(parameters, r0, r1, 1, 2, 0) + !load_vector_range::process(parameters, r0, r1, 1, 2, 0) ) return T(0); @@ -85,23 +87,23 @@ void vector_randu() typedef exprtk::parser parser_t; const std::string vecrandu_program = - " var noise[6] := [0]; " - " " - " if (randu(noise,0,5) == false) " - " { " - " println('Failed to generate noise'); " - " return [false]; " - " } " - " " - " var noisy[6] := signal + (noise - 1/2); " - " " - " for (var i := 0; i < noisy[]; i += 1) " - " { " - " println('noisy[',i,'] = ', noisy[i]); " - " } " - " " - " println('avg: ', avg(noisy)); " - " "; + " var noise[6] := [0]; " + " " + " if (randu(noise,0,5) == false) " + " { " + " println('Failed to generate noise'); " + " return [false]; " + " }; " + " " + " var noisy[noise[]] := signal + (noise - 1/2); " + " " + " for (var i := 0; i < noisy[]; i += 1) " + " { " + " println('noisy[',i,'] = ', noisy[i]); " + " }; " + " " + " println('avg: ', avg(noisy)); " + " "; T signal[] = { T(1.1), T(2.2), T(3.3), T(4.4), T(5.5), T(6.6), T(7.7) }; diff --git a/src/third_party/exprtk/exprtk_simple_example_20.cpp b/src/third_party/exprtk/exprtk_simple_example_20.cpp new file mode 100644 index 0000000..67e27e9 --- /dev/null +++ b/src/third_party/exprtk/exprtk_simple_example_20.cpp @@ -0,0 +1,109 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 20 * + * Author: Arash Partow (1999-2024) * + * URL: https://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the MIT License. * + * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * + * * + ************************************************************** +*/ + + +#include +#include +#include +#include + +#include "exprtk.hpp" + + +struct vector_access_rtc : public exprtk::vector_access_runtime_check +{ + typedef std::map map_t; + map_t vector_map; + + bool handle_runtime_violation(violation_context& context) + { + const map_t::iterator itr = vector_map.find(static_cast(context.base_ptr)); + std::string vector_name = (itr != vector_map.end()) ? + itr->second : "Unknown" ; + + printf("Runtime vector access violation\n" + "Vector: %s base: %p end: %p access: %p typesize: %d\n", + vector_name.c_str(), + context.base_ptr , + context.end_ptr , + context.access_ptr , + static_cast(context.type_size)); + + throw std::runtime_error + ("Runtime vector access violation. Vector: " + vector_name); + + return false; + } +}; + +template +void vector_overflow_example() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + const std::string expression_str = + " for (var i := 0; i < max(v0[],v1[]); i += 1) " + " { " + " v0[i] := (2 * v0[i]) + (v1[i] / 3); " + " } "; + + T v0[5 ] = { 0, 1, 2, 3, 4 }; + T v1[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + vector_access_rtc vec_rtc; + + vec_rtc.vector_map[v0] = "v0"; + vec_rtc.vector_map[v1] = "v1"; + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + symbol_table.add_vector("v0", v0); + symbol_table.add_vector("v1", v1); + + expression.register_symbol_table(symbol_table); + + parser.register_vector_access_runtime_check(vec_rtc); + + try + { + if (!parser.compile(expression_str, expression)) + { + printf("Error: %s\tExpression: %s\n", + parser.error().c_str(), + expression_str.c_str()); + + return; + } + + expression.value(); + } + catch(std::runtime_error& exception) + { + printf("Exception: %s\n",exception.what()); + } +} + +int main() +{ + vector_overflow_example(); + return 0; +} diff --git a/src/third_party/exprtk/exprtk_simple_example_21.cpp b/src/third_party/exprtk/exprtk_simple_example_21.cpp new file mode 100644 index 0000000..c631418 --- /dev/null +++ b/src/third_party/exprtk/exprtk_simple_example_21.cpp @@ -0,0 +1,117 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 21 * + * Author: Arash Partow (1999-2024) * + * URL: https://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the MIT License. * + * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * + * * + ************************************************************** +*/ + + +#include +#include + +#include "exprtk.hpp" + + +template +void binomial_option_pricing_model() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + const std::string european_option_binomial_model_program = + " var dt := t / n; " + " var z := exp(r * dt); " + " var z_inv := 1 / z; " + " var u := exp(v * sqrt(dt)); " + " var u_inv := 1 / u; " + " var p_up := (z - u_inv) / (u - u_inv); " + " var p_down := 1 - p_up; " + " " + " var option_price[n + 1] := [0]; " + " " + " for (var i := 0; i <= n; i += 1) " + " { " + " var base_price := s * u^(n - 2i); " + " option_price[i] := " + " switch " + " { " + " case callput_flag == 'call' : max(base_price - k, 0); " + " case callput_flag == 'put' : max(k - base_price, 0); " + " }; " + " }; " + " " + " for (var j := n - 1; j >= 0; j -= 1) " + " { " + " for (var i := 0; i <= j; i += 1) " + " { " + " option_price[i] := z_inv * " + " (p_up * option_price[i] + p_down * option_price[i + 1]); " + " } " + " }; " + " " + " option_price[0]; "; + + T s = T( 100.00); // Spot / Stock / Underlying / Base price + T k = T( 110.00); // Strike price + T v = T( 0.30); // Volatility + T t = T( 2.22); // Years to maturity + T r = T( 0.05); // Risk free rate + T n = T(1000.00); // Number of time steps + + std::string callput_flag; + + symbol_table_t symbol_table; + symbol_table.add_variable("s",s); + symbol_table.add_variable("k",k); + symbol_table.add_variable("t",t); + symbol_table.add_variable("r",r); + symbol_table.add_variable("v",v); + symbol_table.add_constant("n",n); + symbol_table.add_stringvar("callput_flag",callput_flag); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + parser.compile(european_option_binomial_model_program,expression); + + callput_flag = "call"; + + const T binomial_call_option_price = expression.value(); + + callput_flag = "put"; + + const T binomial_put_option_price = expression.value(); + + printf("BinomialPrice(call, %5.3f, %5.3f, %5.3f, %5.3f, %5.3f) = %10.6f\n", + s, k, t, r, v, + binomial_call_option_price); + + printf("BinomialPrice(put , %5.3f, %5.3f, %5.3f, %5.3f, %5.3f) = %10.6f\n", + s, k, t, r, v, + binomial_put_option_price); + + const T put_call_parity_diff = + (binomial_call_option_price - binomial_put_option_price) - + (s - k * std::exp(-r * t)); + + printf("Put-Call parity difference: %20.17f\n", put_call_parity_diff); +} + +int main() +{ + binomial_option_pricing_model(); + return 0; +} diff --git a/src/third_party/exprtk/exprtk_simple_example_22.cpp b/src/third_party/exprtk/exprtk_simple_example_22.cpp new file mode 100644 index 0000000..f40969d --- /dev/null +++ b/src/third_party/exprtk/exprtk_simple_example_22.cpp @@ -0,0 +1,144 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 22 * + * Author: Arash Partow (1999-2024) * + * URL: https://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the MIT License. * + * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * + * * + ************************************************************** +*/ + + +#include +#include + +#include "exprtk.hpp" + + +template +void compute_implied_volatility() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + typedef exprtk::function_compositor compositor_t; + typedef typename compositor_t::function function_t; + + const std::string implied_volatility_program = + " const var epsilon := 0.0000001; " + " const var max_iters := 1000; " + " " + " var v := 0.5; /* Initial volatility guess */ " + " var itr := 0; " + " " + " while ((itr += 1) <= max_iters) " + " { " + " var price := " + " switch " + " { " + " case callput_flag == 'call' : bsm_call(s, k, r, t, v); " + " case callput_flag == 'put' : bsm_put (s, k, r, t, v); " + " }; " + " " + " var price_diff := price - target_price; " + " " + " if (abs(price_diff) <= epsilon) " + " { " + " break; " + " }; " + " " + " v -= price_diff / vega(s, k, r, t, v); " + " }; " + " " + " itr <= max_iters ? v : null; "; + + T s = T( 100.00); // Spot / Stock / Underlying / Base price + T k = T( 110.00); // Strike price + T t = T( 2.22); // Years to maturity + T r = T( 0.05); // Risk free rate + T target_price = T( 0.00); + + std::string callput_flag; + + symbol_table_t symbol_table(symbol_table_t::e_immutable); + symbol_table.add_variable("s",s); + symbol_table.add_variable("k",k); + symbol_table.add_variable("t",t); + symbol_table.add_variable("r",r); + symbol_table.add_stringvar("callput_flag",callput_flag); + symbol_table.add_variable ("target_price",target_price); + symbol_table.add_pi(); + + compositor_t compositor(symbol_table); + + compositor.add( + function_t("bsm_call") + .vars("s", "k", "r", "t", "v") + .expression + ( + " var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); " + " var d2 := d1 - v * sqrt(t); " + " s * ncdf(d1) - k * exp(-r * t) * ncdf(d2); " + )); + + compositor.add( + function_t("bsm_put") + .vars("s", "k", "r", "t", "v") + .expression + ( + " var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); " + " var d2 := d1 - v * sqrt(t); " + " k * exp(-r * t) * ncdf(-d2) - s * ncdf(-d1); " + )); + + compositor.add( + function_t("vega") + .vars("s", "k", "r", "t", "v") + .expression + ( + " var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); " + " s * sqrt(t) * exp(-d1^2 / 2) / sqrt(2pi); " + )); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + parser.compile(implied_volatility_program,expression); + + { + callput_flag = "call"; + target_price = T(18.339502); + + const T implied_vol = expression.value(); + + printf("Call Option(s: %5.3f, k: %5.3f, t: %5.3f, r: %5.3f) " + "@ $%8.6f Implied volatility = %10.8f\n", + s, k, t, r, target_price, implied_vol); + } + + { + callput_flag = "put"; + target_price = T(16.782764); + + const T implied_vol = expression.value(); + + printf("Put Option(s: %5.3f, k: %5.3f, t: %5.3f, r: %5.3f) " + "@ $%8.6f Implied volatility = %10.8f\n", + s, k, t, r, target_price, implied_vol); + } +} + +int main() +{ + compute_implied_volatility(); + return 0; +} diff --git a/src/third_party/exprtk/exprtk_simple_example_23.cpp b/src/third_party/exprtk/exprtk_simple_example_23.cpp new file mode 100644 index 0000000..8828ece --- /dev/null +++ b/src/third_party/exprtk/exprtk_simple_example_23.cpp @@ -0,0 +1,136 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 23 * + * Author: Arash Partow (1999-2024) * + * URL: https://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the MIT License. * + * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * + * * + ************************************************************** +*/ + + +#include +#include + +#include "exprtk.hpp" + + +template +void real_1d_discrete_fourier_transform() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + typedef exprtk::function_compositor compositor_t; + typedef typename compositor_t::function function_t; + + const T sampling_rate = 1024.0; // ~1KHz + const T N = 8 * sampling_rate; // 8 seconds worth of samples + + std::vector input (static_cast(N),0.0); + std::vector output(static_cast(N),0.0); + + exprtk::rtl::io::println println; + + symbol_table_t symbol_table; + symbol_table.add_vector ("input" , input ); + symbol_table.add_vector ("output" , output ); + symbol_table.add_function ("println" , println ); + symbol_table.add_constant ("N" , N ); + symbol_table.add_constant ("sampling_rate", sampling_rate); + symbol_table.add_pi(); + + compositor_t compositor(symbol_table); + compositor.load_vectors(true); + + compositor.add( + function_t("dft_1d_real") + .var("N") + .expression + ( + " for (var k := 0; k < N; k += 1) " + " { " + " var k_real := 0.0; " + " var k_imag := 0.0; " + " " + " for (var i := 0; i < N; i += 1) " + " { " + " var theta := 2pi * k * i / N; " + " k_real += input[i] * cos(theta); " + " k_imag -= input[i] * sin(theta); " + " }; " + " " + " output[k] := hypot(k_real,k_imag); " + " } " + )); + + const std::string dft_program = + " " + " /* " + " Generate an aggregate waveform comprised of three " + " sine waves of varying frequencies and amplitudes. " + " */ " + " var frequencies[3] := { 100.0, 200.0, 300.0 }; /* Hz */ " + " var amplitudes [3] := { 10.0, 20.0, 30.0 }; /* Power */ " + " " + " for (var i := 0; i < N; i += 1) " + " { " + " var time := i / sampling_rate; " + " " + " for (var j := 0; j < frequencies[]; j += 1) " + " { " + " var frequency := frequencies[j]; " + " var amplitude := amplitudes [j]; " + " var theta := 2 * pi * frequency * time; " + " " + " input[i] += amplitude * sin(theta); " + " } " + " }; " + " " + " dft_1d_real(input[]); " + " " + " var freq_bin_size := sampling_rate / N; " + " var max_bin := ceil(N / 2); " + " var max_noise_level := 1e-5; " + " " + " /* Normalise amplitudes */ " + " output /= max_bin; " + " " + " println('1D Real DFT Frequencies'); " + " " + " for (var k := 0; k < max_bin; k += 1) " + " { " + " if (output[k] > max_noise_level) " + " { " + " var freq_begin := k * freq_bin_size; " + " var freq_end := freq_begin + freq_bin_size; " + " " + " println('Index: ', k,' ', " + " 'Freq. range: [', freq_begin, 'Hz, ', freq_end, 'Hz) ', " + " 'Amplitude: ', output[k]); " + " } " + " } " + " "; + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + parser.compile(dft_program,expression); + + expression.value(); +} + +int main() +{ + real_1d_discrete_fourier_transform(); + return 0; +} diff --git a/src/third_party/exprtk/exprtk_simple_example_24.cpp b/src/third_party/exprtk/exprtk_simple_example_24.cpp new file mode 100644 index 0000000..6b5c302 --- /dev/null +++ b/src/third_party/exprtk/exprtk_simple_example_24.cpp @@ -0,0 +1,143 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 24 * + * Author: Arash Partow (1999-2024) * + * URL: https://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the MIT License. * + * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * + * * + ************************************************************** +*/ + + +#include +#include + +#include "exprtk.hpp" + + +template +struct char_process : public exprtk::igeneric_function +{ + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::string_view string_t; + + using exprtk::igeneric_function::operator(); + + char_process() + : exprtk::igeneric_function("S") + {} + + inline T operator()(parameter_list_t parameters) + { + const unsigned char c = string_t(parameters[0])[0]; + return Process(c); + } +}; + +template +T is_digit_func(const unsigned char c) +{ + return (('0' <= c) && (c <= '9')) ? T(1) : T(0); +} + +template +T to_num_func(const unsigned char c) +{ + return static_cast(c - '0'); +} + +template +void rpn_example() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + const std::string rpn_program = + " var stack[1000] := [0]; " + " var stack_size := 0; " + " " + " for (var i := 0; i < rpn_expression[]; i += 1) " + " { " + " var c := rpn_expression[i : i + 1]; " + " " + " if (c == ' ') " + " { " + " continue; " + " } " + " else if (is_digit(c)) " + " { " + " stack[stack_size] := to_num(c); " + " stack_size += 1; " + " } " + " else " + " { " + " var operator := c; " + " var operand1 := stack[stack_size - 2]; " + " var operand2 := stack[stack_size - 1]; " + " stack_size -= 2; " + " " + " switch " + " { " + " case operator == '+' : stack[stack_size] := operand1 + operand2; " + " case operator == '-' : stack[stack_size] := operand1 - operand2; " + " case operator == '*' : stack[stack_size] := operand1 * operand2; " + " case operator == '/' : stack[stack_size] := operand1 / operand2; " + " case operator == '^' : stack[stack_size] := operand1 ^ operand2; " + " }; " + " " + " stack_size += 1; " + " } " + " }; " + " " + " println(stack[0], ' = ', rpn_expression); " + " "; + + std::string rpn_expression; + + char_process> isdigit; + char_process> tonum; + exprtk::rtl::io::println println; + + symbol_table_t symbol_table; + symbol_table.add_stringvar("rpn_expression", rpn_expression); + symbol_table.add_function ("println" , println ); + symbol_table.add_function ("is_digit" , isdigit ); + symbol_table.add_function ("to_num" , tonum ); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + parser.compile(rpn_program, expression); + + const std::string rpn_expressions[] = + { + "2 3 8 / ^ 4 6 * + 3 9 / -", // 2 ^ (3 / 8) + 4 * 6 - 3 / 9 + "1 2 / 6 5 2 - / * 7 +" , // (1 / 2) * (6 / (5 - 2)) + 7 + "1 2 * 3 / 4 * 5 / 6 *" , // ((((1 * 2) / 3) * 4) / 5) * 6 + "8 6 4 + * 2 /" // (8 * (6 + 4)) / 2 + }; + + for (std::size_t i = 0; i < sizeof(rpn_expressions) / sizeof(std::string); ++i) + { + rpn_expression = rpn_expressions[i]; + expression.value(); + } +} + +int main() +{ + rpn_example(); + return 0; +} diff --git a/src/third_party/exprtk/exprtk_test.cpp b/src/third_party/exprtk/exprtk_test.cpp index 65661d7..4327731 100644 --- a/src/third_party/exprtk/exprtk_test.cpp +++ b/src/third_party/exprtk/exprtk_test.cpp @@ -3,7 +3,7 @@ * C++ Mathematical Expression Toolkit Library * * * * Examples and Unit-Tests * - * Author: Arash Partow (1999-2023) * + * Author: Arash Partow (1999-2024) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -11,6 +11,7 @@ * permitted under the guidelines and in accordance with the * * most current version of the MIT License. * * https://www.opensource.org/licenses/MIT * + * SPDX-License-Identifier: MIT * * * ************************************************************** */ @@ -22,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -36,1085 +36,1095 @@ typedef float numeric_type; typedef double numeric_type; #endif +#if __cplusplus >= 201103L + #define exprtk_test_override override + #define exprtk_test_final final + #define exprtk_test_delete = delete +#else + #define exprtk_test_override + #define exprtk_test_final + #define exprtk_test_delete +#endif + typedef std::pair test_t; static const test_t global_test_list[] = - { - // Note: Each of following tests must compile down - // to a single literal node. - test_t("0",0.0), - test_t("1",1.0), - test_t("2",2.0), - test_t("3",3.0), - test_t("4",4.0), - test_t("5",5.0), - test_t("6",6.0), - test_t("7",7.0), - test_t("8",8.0), - test_t("9",9.0), - test_t("12.12",12.12), - test_t("123.123",123.123), - test_t("1234.1234",1234.1234), - test_t("12345.12345",12345.12345), - test_t("123456.123456",123456.123456), - test_t("0.0",0.0), - test_t("1.0",1.0), - test_t("2.0",2.0), - test_t("3.0",3.0), - test_t("4.0",4.0), - test_t("5.0",5.0), - test_t("6.0",6.0), - test_t("7.0",7.0), - test_t("8.0",8.0), - test_t("9.0",9.0), - test_t("0.0",0.0), - test_t("1.1",1.1), - test_t("2.2",2.2), - test_t("3.3",3.3), - test_t("4.4",4.4), - test_t("5.5",5.5), - test_t("6.6",6.6), - test_t("7.7",7.7), - test_t("8.8",8.8), - test_t("9.9",9.9), - test_t("+0",0.0), - test_t("+1",1.0), - test_t("+2",2.0), - test_t("+3",3.0), - test_t("+4",4.0), - test_t("+5",5.0), - test_t("+6",6.0), - test_t("+7",7.0), - test_t("+8",8.0), - test_t("+9",9.0), - test_t("+0.0",0.0), - test_t("+1.0",1.0), - test_t("+2.0",2.0), - test_t("+3.0",3.0), - test_t("+4.0",4.0), - test_t("+5.0",5.0), - test_t("+6.0",6.0), - test_t("+7.0",7.0), - test_t("+8.0",8.0), - test_t("+9.0",9.0), - test_t("+0.0",0.0), - test_t("+1.1",1.1), - test_t("+2.2",2.2), - test_t("+3.3",3.3), - test_t("+4.4",4.4), - test_t("+5.5",5.5), - test_t("+6.6",6.6), - test_t("+7.7",7.7), - test_t("+8.8",8.8), - test_t("+9.9",9.9), - test_t("-0",-0.0), - test_t("-1",-1.0), - test_t("-2",-2.0), - test_t("-3",-3.0), - test_t("-4",-4.0), - test_t("-5",-5.0), - test_t("-6",-6.0), - test_t("-7",-7.0), - test_t("-8",-8.0), - test_t("-9",-9.0), - test_t("-0.0",-0.0), - test_t("-1.0",-1.0), - test_t("-2.0",-2.0), - test_t("-3.0",-3.0), - test_t("-4.0",-4.0), - test_t("-5.0",-5.0), - test_t("-6.0",-6.0), - test_t("-7.0",-7.0), - test_t("-8.0",-8.0), - test_t("-9.0",-9.0), - test_t("-0.0",-0.0), - test_t("-1.1",-1.1), - test_t("-2.2",-2.2), - test_t("-3.3",-3.3), - test_t("-4.4",-4.4), - test_t("-5.5",-5.5), - test_t("-6.6",-6.6), - test_t("-7.7",-7.7), - test_t("-8.8",-8.8), - test_t("-9.9",-9.9), - test_t("0.0e+0" ,+0.0e+0), - test_t("1.1e+1" ,+1.1e+1), - test_t("2.2e+2" ,+2.2e+2), - test_t("3.3e+3" ,+3.3e+3), - test_t("4.4e+4" ,+4.4e+4), - test_t("5.5e+5" ,+5.5e+5), - test_t("6.6e+6" ,+6.6e+6), - test_t("7.7e+7" ,+7.7e+7), - test_t("8.8e+8" ,+8.8e+8), - test_t("9.9e+9" ,+9.9e+9), - test_t("-0.0e+0",-0.0e+0), - test_t("-1.1e+1",-1.1e+1), - test_t("-2.2e+2",-2.2e+2), - test_t("-3.3e+3",-3.3e+3), - test_t("-4.4e+4",-4.4e+4), - test_t("-5.5e+5",-5.5e+5), - test_t("-6.6e+6",-6.6e+6), - test_t("-7.7e+7",-7.7e+7), - test_t("-8.8e+8",-8.8e+8), - test_t("-9.9e+9",-9.9e+9), - test_t("0.0E+0" ,+0.0E+0), - test_t("1.1E+1" ,+1.1E+1), - test_t("2.2E+2" ,+2.2E+2), - test_t("3.3E+3" ,+3.3E+3), - test_t("4.4E+4" ,+4.4E+4), - test_t("5.5E+5" ,+5.5E+5), - test_t("6.6E+6" ,+6.6E+6), - test_t("7.7E+7" ,+7.7E+7), - test_t("8.8E+8" ,+8.8E+8), - test_t("9.9E+9" ,+9.9E+9), - test_t("-0.0E+0",-0.0E+0), - test_t("-1.1E+1",-1.1E+1), - test_t("-2.2E+2",-2.2E+2), - test_t("-3.3E+3",-3.3E+3), - test_t("-4.4E+4",-4.4E+4), - test_t("-5.5E+5",-5.5E+5), - test_t("-6.6E+6",-6.6E+6), - test_t("-7.7E+7",-7.7E+7), - test_t("-8.8E+8",-8.8E+8), - test_t("-9.9E+9",-9.9E+9), - test_t("(0)",0.0), - test_t("(1)",1.0), - test_t("(2)",2.0), - test_t("(3)",3.0), - test_t("(4)",4.0), - test_t("(5)",5.0), - test_t("(6)",6.0), - test_t("(7)",7.0), - test_t("(8)",8.0), - test_t("(9)",9.0), - test_t("(0.0)",0.0), - test_t("(1.0)",1.0), - test_t("(2.0)",2.0), - test_t("(3.0)",3.0), - test_t("(4.0)",4.0), - test_t("(5.0)",5.0), - test_t("(6.0)",6.0), - test_t("(7.0)",7.0), - test_t("(8.0)",8.0), - test_t("(9.0)",9.0), - test_t("(0.0)",0.0), - test_t("(1.1)",1.1), - test_t("(2.2)",2.2), - test_t("(3.3)",3.3), - test_t("(4.4)",4.4), - test_t("(5.5)",5.5), - test_t("(6.6)",6.6), - test_t("(7.7)",7.7), - test_t("(8.8)",8.8), - test_t("(9.9)",9.9), - test_t("(+0)" ,0.0), - test_t("(+1)" ,1.0), - test_t("(+2)" ,2.0), - test_t("(+3)" ,3.0), - test_t("(+4)" ,4.0), - test_t("(+5)" ,5.0), - test_t("(+6)" ,6.0), - test_t("(+7)" ,7.0), - test_t("(+8)" ,8.0), - test_t("(+9)" ,9.0), - test_t("(+0.0)",0.0), - test_t("(+1.0)",1.0), - test_t("(+2.0)",2.0), - test_t("(+3.0)",3.0), - test_t("(+4.0)",4.0), - test_t("(+5.0)",5.0), - test_t("(+6.0)",6.0), - test_t("(+7.0)",7.0), - test_t("(+8.0)",8.0), - test_t("(+9.0)",9.0), - test_t("(+0.0)",0.0), - test_t("(+1.1)",1.1), - test_t("(+2.2)",2.2), - test_t("(+3.3)",3.3), - test_t("(+4.4)",4.4), - test_t("(+5.5)",5.5), - test_t("(+6.6)",6.6), - test_t("(+7.7)",7.7), - test_t("(+8.8)",8.8), - test_t("(+9.9)",9.9), - test_t("(-0)" ,-0.0), - test_t("(-1)" ,-1.0), - test_t("(-2)" ,-2.0), - test_t("(-3)" ,-3.0), - test_t("(-4)" ,-4.0), - test_t("(-5)" ,-5.0), - test_t("(-6)" ,-6.0), - test_t("(-7)" ,-7.0), - test_t("(-8)" ,-8.0), - test_t("(-9)" ,-9.0), - test_t("(-0.0)",-0.0), - test_t("(-1.0)",-1.0), - test_t("(-2.0)",-2.0), - test_t("(-3.0)",-3.0), - test_t("(-4.0)",-4.0), - test_t("(-5.0)",-5.0), - test_t("(-6.0)",-6.0), - test_t("(-7.0)",-7.0), - test_t("(-8.0)",-8.0), - test_t("(-9.0)",-9.0), - test_t("(-0.0)",-0.0), - test_t("(-1.1)",-1.1), - test_t("(-2.2)",-2.2), - test_t("(-3.3)",-3.3), - test_t("(-4.4)",-4.4), - test_t("(-5.5)",-5.5), - test_t("(-6.6)",-6.6), - test_t("(-7.7)",-7.7), - test_t("(-8.8)",-8.8), - test_t("(-9.9)",-9.9), - test_t("-(1.1)",-1.1), - test_t("-(1.1+2.2)",-3.3), - test_t("1234567890",1234567890), - test_t("123456789.0",123456789.0), - test_t("+1234567890",1234567890), - test_t("+123456789.0",123456789.0), - test_t("-1234567890",-1234567890), - test_t("-123456789.0",-123456789.0), - test_t("1234.567890",1234.567890), - test_t("-1234.567890",-1234.567890), - test_t("0+9",9.0), - test_t("1+8",9.0), - test_t("2+7",9.0), - test_t("3+6",9.0), - test_t("4+5",9.0), - test_t("5+4",9.0), - test_t("6+3",9.0), - test_t("7+2",9.0), - test_t("8+1",9.0), - test_t("9+0",9.0), - test_t(" 0 + 9 ",9.0), - test_t(" 1 + 8 ",9.0), - test_t(" 2 + 7 ",9.0), - test_t(" 3 + 6 ",9.0), - test_t(" 4 + 5 ",9.0), - test_t(" 5 + 4 ",9.0), - test_t(" 6 + 3 ",9.0), - test_t(" 7 + 2 ",9.0), - test_t(" 8 + 1 ",9.0), - test_t(" 9 + 0 ",9.0), - test_t("( 0 + 9 )",9.0), - test_t("( 1 + 8 )",9.0), - test_t("( 2 + 7 )",9.0), - test_t("( 3 + 6 )",9.0), - test_t("( 4 + 5 )",9.0), - test_t("( 5 + 4 )",9.0), - test_t("( 6 + 3 )",9.0), - test_t("( 7 + 2 )",9.0), - test_t("( 8 + 1 )",9.0), - test_t("( 9 + 0 )",9.0), - test_t("1E1+1",11.0), - test_t("1e1+1",11.0), - test_t("1E1-1", 9.0), - test_t("1e1-1", 9.0), - test_t("1E01+1",11.0), - test_t("1e01+1",11.0), - test_t("1E01-1", 9.0), - test_t("1e01-1", 9.0), - test_t("1+2",+3.0), - test_t("1-2",-1.0), - test_t("1*2",+2.0), - test_t("1/2",+0.5), - test_t("1.1+2.2", +3.3), - test_t("1.1-2.2", -1.1), - test_t("1.1*2.2",+2.42), - test_t("1.1/2.2", +0.5), - test_t("0-9",-9.0), - test_t("1-8",-7.0), - test_t("2-7",-5.0), - test_t("3-6",-3.0), - test_t("4-5",-1.0), - test_t("5-4",+1.0), - test_t("6-3",+3.0), - test_t("7-2",+5.0), - test_t("8-1",+7.0), - test_t("9-0",+9.0), - test_t("2.*3",+6.0), - test_t("2.*3.",+6.0), - test_t("2.+3",+5.0), - test_t("2.+3.",+5.0), - test_t("123.*456.",+56088.0), - test_t(" 0 - 9 ",-9.0), - test_t(" 1 - 8 ",-7.0), - test_t(" 2 - 7 ",-5.0), - test_t(" 3 - 6 ",-3.0), - test_t(" 4 - 5 ",-1.0), - test_t(" 5 - 4 ",+1.0), - test_t(" 6 - 3 ",+3.0), - test_t(" 7 - 2 ",+5.0), - test_t(" 8 - 1 ",+7.0), - test_t(" 9 - 0 ",+9.0), - test_t("( 0 - 9 )",-9.0), - test_t("( 1 - 8 )",-7.0), - test_t("( 2 - 7 )",-5.0), - test_t("( 3 - 6 )",-3.0), - test_t("( 4 - 5 )",-1.0), - test_t("( 5 - 4 )",+1.0), - test_t("( 6 - 3 )",+3.0), - test_t("( 7 - 2 )",+5.0), - test_t("( 8 - 1 )",+7.0), - test_t("( 9 - 0 )",+9.0), - test_t("1 - -1" , 2.0), - test_t("1 --1" , 2.0), - test_t("1-- 1" , 2.0), - test_t("1--1" , 2.0), - test_t("1 -- -1", 0.0), - test_t("1 + -1" , 0.0), - test_t("1 +-1" , 0.0), - test_t("1+- 1" , 0.0), - test_t("1+-1" , 0.0), - test_t("1 +- -1", 2.0), - test_t("1 + +1" , 2.0), - test_t("1 ++1" , 2.0), - test_t("1 - -1 + 1" , 3.0), - test_t("1 --1 + 1" , 3.0), - test_t("1-- 1 + 1" , 3.0), - test_t("1--1 + 1" , 3.0), - test_t("1 -- -1 + 1", 1.0), - test_t("1 + -1 + 1" , 1.0), - test_t("1 +-1 + 1" , 1.0), - test_t("1+- 1 + 1" , 1.0), - test_t("1+-1 + 1" , 1.0), - test_t("1 +- -1 + 1", 3.0), - test_t("1 + +1 + 1" , 3.0), - test_t("1 ++1 + 1" , 3.0), - test_t("1 - -1 - 1" , 1.0), - test_t("1 --1 - 1" , 1.0), - test_t("1-- 1 - 1" , 1.0), - test_t("1--1 - 1" , 1.0), - test_t("1 -- -1 - 1", -1.0), - test_t("1 + -1 - 1" , -1.0), - test_t("1 +-1 - 1" , -1.0), - test_t("1+- 1 - 1" , -1.0), - test_t("1+-1 - 1" , -1.0), - test_t("1 +- -1 - 1", 1.0), - test_t("1 + +1 - 1" , 1.0), - test_t("1 ++1 - 1" , 1.0), - test_t("-(1+2)",-3.0), - test_t("+(1+2)",+3.0), - test_t("+(1-2)",-1.0), - test_t("-(1-2)",+1.0), - test_t("(-3*-6)",+18.0), - test_t("(-6*-3)",+18.0), - test_t("-(-3*-6)",-18.0), - test_t("-(-6*-3)",-18.0), - test_t("1.1+2.2+3.3",+6.6), - test_t("+1.1+2.2+3.3",+6.6), - test_t("-1.1-2.2-3.3",-6.6), - test_t("1.1*2.2*3.3",+7.986), - test_t("+1.1*2.2*3.3",+7.986), - test_t("-1.1*-2.2*-3.3",-7.986), - test_t("1 + 1/2",+1.5), - test_t("1 + (1/2)",+1.5), - test_t("1.1 + 1.1/2.2",+1.6), - test_t("1.1 + (1.1/2.2)",+1.6), - test_t("2 * 1/2",+1.0), - test_t("2 * (1/2)",+1.0), - test_t("2.2 * 1.1/2.2",+1.1), - test_t("2.2 * (1.1/2.2)",+1.1), - test_t("1^2",1.0), - test_t("2^1",2.0), - test_t("2^3",8.0), - test_t("-2^3",-8.0), - test_t("-2^4",-16.0), - test_t("(-2)^3",-8.0), - test_t("(-2)^4",+16.0), - test_t("3^2^4",43046721.0), - test_t("1.1^2.2",1.23328630055466251099), - test_t("2.2^1.1",2.3804822576003541627), - test_t("2.2^3.3",13.48946876053338489127), - test_t("3.3^2.2^1.1",17.15193942371376191362), - test_t("+3.3^2.2^1.1",17.15193942371376191362), - test_t("3.3^+2.2^1.1",17.15193942371376191362), - test_t("3.3^2.2^+1.1",17.15193942371376191362), - test_t("3.3^2.2^-1.1",1.65127293793867959137), - test_t("+3.3^+2.2^-1.1",1.65127293793867959137), - test_t("1.1^(1.1 * 2.2)",1.25941916576299080582), - test_t("2.2^(1.1 * 3.3)",17.49823848953534759743), - test_t("3.3^(1.1 * 2.2)",17.98058156638874965269), - test_t("1.1^-2.2/1.1",0.73712884727743375853), - test_t("1.1^+2.2/1.1",1.121169364140602282717273261774), - test_t("1.1^2.2/+1.1",1.121169364140602282717273261774), - test_t("1.1^+2.2/+1.1",1.121169364140602282717273261774), - test_t("1.1^+2.2/-1.1",-1.121169364140602282717273261774), - test_t("1.1^2.2/-1.1",-1.121169364140602282717273261774), - test_t("1.1^+2.2/-1.1",-1.121169364140602282717273261774), - test_t("+1.1^-2.2/1.1",0.73712884727743375853), - test_t("+1.1^+2.2/1.1",1.121169364140602282717273261774), - test_t("+1.1^2.2/+1.1",1.121169364140602282717273261774), - test_t("+1.1^+2.2/+1.1",1.121169364140602282717273261774), - test_t("+1.1^+2.2/-1.1",-1.121169364140602282717273261774), - test_t("+1.1^2.2/-1.1",-1.121169364140602282717273261774), - test_t("+1.1^+2.2/-1.1",-1.121169364140602282717273261774), - test_t("equal(1.23^3,(1.23 * 1.23 * 1.23))",1.0), - test_t("equal(1.23^-3,1/(1.23 * 1.23 * 1.23))",1.0), - test_t("equal((2.1 + 1.23^3),(2.1 + [1.23 * 1.23 * 1.23]))",1.0), - test_t("equal((2.1 - 1.23^3),(2.1 - [1.23 * 1.23 * 1.23]))",1.0), - test_t("equal((2.1 * 1.23^3),(2.1 * [1.23 * 1.23 * 1.23]))",1.0), - test_t("equal((2.1 / 1.23^3),(2.1 / [1.23 * 1.23 * 1.23]))",1.0), - test_t("equal((1.23^3 + 2.1),({1.23 * 1.23 * 1.23} + 2.1))",1.0), - test_t("equal((1.23^3 - 2.1),({1.23 * 1.23 * 1.23} - 2.1))",1.0), - test_t("equal((1.23^3 * 2.1),({1.23 * 1.23 * 1.23} * 2.1))",1.0), - test_t("equal((1.23^3 / 2.1),({1.23 * 1.23 * 1.23} / 2.1))",1.0), - test_t("equal(1.0^(1.0/2.0),sqrt(1.0))",1.0), - test_t("equal(1.0^(1.0/2.0),root(1.0,2.0))",1.0), - test_t("equal(1.0^(1.0/3.0),root(1.0,3.0))",1.0), - test_t("equal(1.0^(1.0/4.0),root(1.0,4.0))",1.0), - test_t("equal(1.0^(1.0/5.0),root(1.0,5.0))",1.0), - test_t("equal(1.0^(1.0/6.0),root(1.0,6.0))",1.0), - test_t("equal(1.0^(1.0/7.0),root(1.0,7.0))",1.0), - test_t("equal(1.0^(1.0/8.0),root(1.0,8.0))",1.0), - test_t("equal(1.0^(1.0/9.0),root(1.0,9.0))",1.0), - test_t("equal(2.0^(1.0/2.0),sqrt(2.0))",1.0), - test_t("equal(2.0^(1.0/2.0),root(2.0,2.0))",1.0), - test_t("equal(3.0^(1.0/3.0),root(3.0,3.0))",1.0), - test_t("equal(4.0^(1.0/4.0),root(4.0,4.0))",1.0), - test_t("equal(5.0^(1.0/5.0),root(5.0,5.0))",1.0), - test_t("equal(6.0^(1.0/6.0),root(6.0,6.0))",1.0), - test_t("equal(7.0^(1.0/7.0),root(7.0,7.0))",1.0), - test_t("equal(8.0^(1.0/8.0),root(8.0,8.0))",1.0), - test_t("equal(9.0^(1.0/9.0),root(9.0,9.0))",1.0), - test_t("1 < 2", 1.0), - test_t("1 <= 2", 1.0), - test_t("1.1 <= 2.2", 1.0), - test_t("(1.0 + 0.1) <= (2.0 + 0.2)", 1.0), - test_t("1 > 2", 0.0), - test_t("1 >= 2", 0.0), - test_t("1.1 >= 2.2", 0.0), - test_t("(1.0 + 0.1) >= (2.0 + 0.2)", 0.0), - test_t("1 <> 2", 1.0), - test_t("1 != 2", 1.0), - test_t("1.1 <> 2.2", 1.0), - test_t("1.1 != 2.2", 1.0), - test_t("(1.0 + 0.1) <> (2.0 + 0.2)", 1.0), - test_t("(1.0 + 0.1) != (2.0 + 0.2)", 1.0), - test_t("1 == 1", 1.0), - test_t("1.1 == 1.1", 1.0), - test_t("1 = 1", 1.0), - test_t("1.1 = 1.1", 1.0), - test_t("1 <> 1", 0.0), - test_t("1 != 1", 0.0), - test_t("1.1 <> 1.1", 0.0), - test_t("1.1 != 1.1", 0.0), - test_t("(1.0 + 0.1) <> (1.0 + 0.1)", 0.0), - test_t("(1.0 + 0.1) != (1.0 + 0.1)", 0.0), - test_t("equal(1.1,1.1)",1.0), - test_t("equal(1.1,2.2)",0.0), - test_t("not_equal(1.1,1.1)",0.0), - test_t("not_equal(1.1,2.2)",1.0), - test_t("1 and 1",1.0), - test_t("1 and 0",0.0), - test_t("0 and 1",0.0), - test_t("0 and 0",0.0), - test_t("1.0 and 1.0",1.0), - test_t("1.0 and 0.0",0.0), - test_t("0.0 and 1.0",0.0), - test_t("0.0 and 0.0",0.0), - test_t("(1 and 1)",1.0), - test_t("(1 and 0)",0.0), - test_t("(0 and 1)",0.0), - test_t("(0 and 0)",0.0), - test_t("(1.0 and 1.0)",1.0), - test_t("(1.0 and 0.0)",0.0), - test_t("(0.0 and 1.0)",0.0), - test_t("(0.0 and 0.0)",0.0), - test_t("1 or 1",1.0), - test_t("1 or 0",1.0), - test_t("0 or 1",1.0), - test_t("0 or 0",0.0), - test_t("1.0 or 1.0",1.0), - test_t("1.0 or 0.0",1.0), - test_t("0.0 or 1.0",1.0), - test_t("0.0 or 0.0",0.0), - test_t("(1 or 1)",1.0), - test_t("(1 or 0)",1.0), - test_t("(0 or 1)",1.0), - test_t("(0 or 0)",0.0), - test_t("(1.0 or 1.0)",1.0), - test_t("(1.0 or 0.0)",1.0), - test_t("(0.0 or 1.0)",1.0), - test_t("(0.0 or 0.0)",0.0), - test_t("1 nand 1",0.0), - test_t("1 nand 0",1.0), - test_t("0 nand 1",1.0), - test_t("0 nand 0",1.0), - test_t("1.0 nand 1.0",0.0), - test_t("1.0 nand 0.0",1.0), - test_t("0.0 nand 1.0",1.0), - test_t("0.0 nand 0.0",1.0), - test_t("(1 nand 1)",0.0), - test_t("(1 nand 0)",1.0), - test_t("(0 nand 1)",1.0), - test_t("(0 nand 0)",1.0), - test_t("(1.0 nand 1.0)",0.0), - test_t("(1.0 nand 0.0)",1.0), - test_t("(0.0 nand 1.0)",1.0), - test_t("(0.0 nand 0.0)",1.0), - test_t("1 nor 1",0.0), - test_t("1 nor 0",0.0), - test_t("0 nor 1",0.0), - test_t("0 nor 0",1.0), - test_t("1.0 nor 1.0",0.0), - test_t("1.0 nor 0.0",0.0), - test_t("0.0 nor 1.0",0.0), - test_t("0.0 nor 0.0",1.0), - test_t("(1 nor 1)",0.0), - test_t("(1 nor 0)",0.0), - test_t("(0 nor 1)",0.0), - test_t("(0 nor 0)",1.0), - test_t("(1.0 nor 1.0)",0.0), - test_t("(1.0 nor 0.0)",0.0), - test_t("(0.0 nor 1.0)",0.0), - test_t("(0.0 nor 0.0)",1.0), - test_t("0 xor 0",0.0), - test_t("0 xor 1",1.0), - test_t("1 xor 0",1.0), - test_t("1 xor 1",0.0), - test_t("0.0 xor 0.0",0.0), - test_t("0.0 xor 1.0",1.0), - test_t("1.0 xor 0.0",1.0), - test_t("1.0 xor 1.0",0.0), - test_t("(0 xor 0)",0.0), - test_t("(0 xor 1)",1.0), - test_t("(1 xor 0)",1.0), - test_t("(1 xor 1)",0.0), - test_t("(0.0 xor 0.0)",0.0), - test_t("(0.0 xor 1.0)",1.0), - test_t("(1.0 xor 0.0)",1.0), - test_t("(1.0 xor 1.0)",0.0), - test_t("1 & 1",1.0), - test_t("1 & 0",0.0), - test_t("0 & 1",0.0), - test_t("0 & 0",0.0), - test_t("1.0 & 1.0",1.0), - test_t("1.0 & 0.0",0.0), - test_t("0.0 & 1.0",0.0), - test_t("0.0 & 0.0",0.0), - test_t("(1 & 1)",1.0), - test_t("(1 & 0)",0.0), - test_t("(0 & 1)",0.0), - test_t("(0 & 0)",0.0), - test_t("(1.0 & 1.0)",1.0), - test_t("(1.0 & 0.0)",0.0), - test_t("(0.0 & 1.0)",0.0), - test_t("(0.0 & 0.0)",0.0), - test_t("1 | 1",1.0), - test_t("1 | 0",1.0), - test_t("0 | 1",1.0), - test_t("0 | 0",0.0), - test_t("1.0 | 1.0",1.0), - test_t("1.0 | 0.0",1.0), - test_t("0.0 | 1.0",1.0), - test_t("0.0 | 0.0",0.0), - test_t("(1 | 1)",1.0), - test_t("(1 | 0)",1.0), - test_t("(0 | 1)",1.0), - test_t("(0 | 0)",0.0), - test_t("(1.0 | 1.0)",1.0), - test_t("(1.0 | 0.0)",1.0), - test_t("(0.0 | 1.0)",1.0), - test_t("(0.0 | 0.0)",0.0), - test_t("(1 nand 1) == not(1 and 1)",1.0), - test_t("(1 nand 0) == not(1 and 0)",1.0), - test_t("(0 nand 1) == not(0 and 1)",1.0), - test_t("(0 nand 0) == not(0 and 0)",1.0), - test_t("(1 nor 1) == not(1 or 1)",1.0), - test_t("(1 nor 0) == not(1 or 0)",1.0), - test_t("(0 nor 1) == not(0 or 1)",1.0), - test_t("(0 nor 0) == not(0 or 0)",1.0), - test_t("(1.0 nand 1.0) == not(1.0 and 1.0)",1.0), - test_t("(1.0 nand 0.0) == not(1.0 and 0.0)",1.0), - test_t("(0.0 nand 1.0) == not(0.0 and 1.0)",1.0), - test_t("(0.0 nand 0.0) == not(0.0 and 0.0)",1.0), - test_t("(1.0 nor 1.0) == not(1.0 or 1.0)",1.0), - test_t("(1.0 nor 0.0) == not(1.0 or 0.0)",1.0), - test_t("(0.0 nor 1.0) == not(0.0 or 1.0)",1.0), - test_t("(0.0 nor 0.0) == not(0.0 or 0.0)",1.0), - test_t("(1 nand 1) == not(1 & 1)",1.0), - test_t("(1 nand 0) == not(1 & 0)",1.0), - test_t("(0 nand 1) == not(0 & 1)",1.0), - test_t("(0 nand 0) == not(0 & 0)",1.0), - test_t("(1 nor 1) == not(1 | 1)",1.0), - test_t("(1 nor 0) == not(1 | 0)",1.0), - test_t("(0 nor 1) == not(0 | 1)",1.0), - test_t("(0 nor 0) == not(0 | 0)",1.0), - test_t("(1.0 nand 1.0) == not(1.0 & 1.0)",1.0), - test_t("(1.0 nand 0.0) == not(1.0 & 0.0)",1.0), - test_t("(0.0 nand 1.0) == not(0.0 & 1.0)",1.0), - test_t("(0.0 nand 0.0) == not(0.0 & 0.0)",1.0), - test_t("(1.0 nor 1.0) == not(1.0 | 1.0)",1.0), - test_t("(1.0 nor 0.0) == not(1.0 | 0.0)",1.0), - test_t("(0.0 nor 1.0) == not(0.0 | 1.0)",1.0), - test_t("(0.0 nor 0.0) == not(0.0 | 0.0)",1.0), - test_t("mand(1,1)",1.0), - test_t("mand(1,0)",0.0), - test_t("mand(0,1)",0.0), - test_t("mand(0,0)",0.0), - test_t("mand(1.0,1.0)",1.0), - test_t("mand(1.0,0.0)",0.0), - test_t("mand(0.0,1.0)",0.0), - test_t("mand(0.0,0.0)",0.0), - test_t("mor(1,1)",1.0), - test_t("mor(1,0)",1.0), - test_t("mor(0,1)",1.0), - test_t("mor(0,0)",0.0), - test_t("mor(1.0,1.0)",1.0), - test_t("mor(1.0,0.0)",1.0), - test_t("mor(0.0,1.0)",1.0), - test_t("mor(0.0,0.0)",0.0), - test_t("(1 nand 1) == not(mand(1,1))",1.0), - test_t("(1 nand 0) == not(mand(1,0))",1.0), - test_t("(0 nand 1) == not(mand(0,1))",1.0), - test_t("(0 nand 0) == not(mand(0,0))",1.0), - test_t("(1 nor 1) == not(mor(1,1))",1.0), - test_t("(1 nor 0) == not(mor(1,0))",1.0), - test_t("(0 nor 1) == not(mor(0,1))",1.0), - test_t("(0 nor 0) == not(mor(0,0))",1.0), - test_t("(1.0 nand 1.0) == not(mand(1.0,1.0))",1.0), - test_t("(1.0 nand 0.0) == not(mand(1.0,0.0))",1.0), - test_t("(0.0 nand 1.0) == not(mand(0.0,1.0))",1.0), - test_t("(0.0 nand 0.0) == not(mand(0.0,0.0))",1.0), - test_t("(1.0 nor 1.0) == not(mor(1.0,1.0))",1.0), - test_t("(1.0 nor 0.0) == not(mor(1.0,0.0))",1.0), - test_t("(0.0 nor 1.0) == not(mor(0.0,1.0))",1.0), - test_t("(0.0 nor 0.0) == not(mor(0.0,0.0))",1.0), - test_t("abs(1)",1.0), - test_t("abs(-1)",1.0), - test_t("abs(1.0)",1.0), - test_t("abs(-1.0)",1.0), - test_t("min(1,2)",1.0), - test_t("min(1,2,3)",1.0), - test_t("min(1,2,3,4)",1.0), - test_t("min(1,2,3,4,5)",1.0), - test_t("min(1,2,3,4,5,6)",1.0), - test_t("min(1.1,2.2)",1.1), - test_t("min(1.1,2.2,3.3)",1.1), - test_t("min(1.1,2.2,3.3,4.4)",1.1), - test_t("min(1.1,2.2,3.3,4.4,5.5)",1.1), - test_t("min(1.1,2.2,3.3,4.4,5.5,6.6)",1.1), - test_t("min(min(1,2),min(3,4))",1.0), - test_t("max(1,2)",2.0), - test_t("max(1,2,3)",3.0), - test_t("max(1,2,3,4)",4.0), - test_t("max(1,2,3,4,5)",5.0), - test_t("max(1,2,3,4,5,6)",6.0), - test_t("max(1.1,2.2)",2.2), - test_t("max(1.1,2.2,3.3)",3.3), - test_t("max(1.1,2.2,3.3,4.4)",4.4), - test_t("max(1.1,2.2,3.3,4.4,5.5)",5.5), - test_t("max(1.1,2.2,3.3,4.4,5.5,6.6)",6.6), - test_t("max(max(1,2),max(3,4))",4.0), - test_t("avg(1,2)",1.5), - test_t("avg(1,2,3)",2.0), - test_t("avg(1,2,3,4)",2.5), - test_t("avg(1,2,3,4,5)",3.0), - test_t("avg(1.1,2.2)",1.65), - test_t("avg(1.1,2.2,3.3)",2.2), - test_t("avg(1.1,2.2,3.3,4.4)",2.75), - test_t("avg(1.1,2.2,3.3,4.4,5.5)",3.3), - test_t("avg(1.1,2.2,3.3,4.4,5.5,6.6)",3.85), - test_t("sum(1,2)",3.0), - test_t("sum(1,2,3)",6.0), - test_t("sum(1,2,3,4)",10), - test_t("sum(1,2,3,4,5)",15.0), - test_t("sum(1,2,3,4,5,6)",21), - test_t("sum(1.1,2.2)",3.3), - test_t("sum(1.1,2.2,3.3)",6.6), - test_t("sum(1.1,2.2,3.3,4.4)",11.0), - test_t("sum(1.1,2.2,3.3,4.4,5.5)",16.5), - test_t("sum(1.1,2.2,3.3,4.4,5.5,6.6)",23.1), - test_t("mul(1,2)",2.0), - test_t("mul(1,2,3)",6.0), - test_t("mul(1,2,3,4)",24.0), - test_t("mul(1,2,3,4,5)",120.0), - test_t("mul(1,2,3,4,5,6)",720.0), - test_t("mul(1.1,2.2)",2.42), - test_t("mul(1.1,2.2,3.3)",7.986), - test_t("mul(1.1,2.2,3.3,4.4)",35.1384), - test_t("mul(1.1,2.2,3.3,4.4,5.5)",193.2612), - test_t("mul(1.1,2.2,3.3,4.4,5.5,6.6)",1275.52392), - test_t("equal(sum(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),(1.1+2.2+3.3+4.4+5.5+6.6+7.7+8.8+9.9))",1.0), - test_t("equal(mul(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),(1.1*2.2*3.3*4.4*5.5*6.6*7.7*8.8*9.9))",1.0), - test_t("equal(min(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),1.1)",1.0), - test_t("equal(max(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),9.9)",1.0), - test_t("equal(avg(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),5.5)",1.0), - test_t("floor(1.0)",1.0), - test_t("floor(1.1)",1.0), - test_t("floor(-1.0)",-1.0), - test_t("floor(-1.1)",-2.0), - test_t("ceil(1.0)",1.0), - test_t("ceil(1.1)",2.0), - test_t("ceil(-1.0)",-1.0), - test_t("ceil(-1.1)",-1.0), - test_t("round(1.1)",1.0), - test_t("round(1.49)",1.0), - test_t("round(1.5)",2.0), - test_t("round(1.9)",2.0), - test_t("roundn(1/3,2)",0.33), - test_t("roundn(1/3,5)",0.33333), - test_t("roundn(2/3,2)",0.67), - test_t("roundn(2/3,5)",0.66667), - test_t("roundn(1.0/3.0,2.0)",0.33), - test_t("roundn(1.0/3.0,5.0)",0.33333), - test_t("roundn(2.0/3.0,2.0)",0.67), - test_t("roundn(2.0/3.0,5.0)",0.66667), - test_t("cos(0.0)",1.0), - test_t("sin(0.0)",0.0), - test_t("equal(sin(pi/4.0),cos(pi/4.0))",1.0), - test_t("equal(sin(pi/6.0),cos(pi/3.0))",1.0), - test_t("(sin(pi/4.0) - cos(pi/4.0)) <= epsilon",1.0), - test_t("(cos(pi/3.0) - sin(pi/6.0)) <= epsilon",1.0), - test_t("sin(deg2rad(30))",0.5), - test_t("cos(deg2rad(60))",0.5), - test_t("sin(deg2rad(30)) + cos(deg2rad(60))",1.0), - test_t("equal(sin(deg2rad(30))/cos(deg2rad(30)),tan(deg2rad(30)))",1.0), - test_t("equal(sinh(pi),11.5487393572577483779773343153884) ",1.0), - test_t("equal(asinh(11.5487393572577483779773343153884),pi)",1.0), - test_t("equal(cosh(pi),11.5919532755215206277517520525601) ",1.0), - test_t("equal(acosh(11.5919532755215206277517520525601),pi)",1.0), - test_t("equal(tanh(pi),0.99627207622074994426469058001253) ",1.0), - test_t("equal(atanh(0.99627207622074994426469058001253),pi)",1.0), - test_t("exp(1.0)",2.71828182845904523536028747135266249775724), - test_t("exp(0.0)",1.0), - test_t("log(2.7182818284590451)",1.0), - test_t("log10(10.0)",1.0), - test_t("frac(12.34) + trunc(12.34)",12.34), - test_t("hypot(3.0,4.0)",5.0), - test_t("hypot(1.0,sqrt(3.0))",2.0), - test_t("if(1 < 2, 3, 4)",3.0), - test_t("if(1.1 < 2.2, 3.3, 4.4)",3.3), - test_t("if((1.0+1.1) < (2.0+1.2), 3.3, 4.4)",3.3), - test_t("if(1 = 2, 3, 4)",4.0), - test_t("if(1.1 = 2.2, 3.3, 4.4)",4.4), - test_t("if((1.0+1.1) = (2.0+1.2), 3.3, 4.4)",4.4), - test_t("if(1 == 2, 3, 4)",4.0), - test_t("if(1.1 == 2.2, 3.3, 4.4)",4.4), - test_t("if((1.0+1.1) == (2.0+1.2), 3.3, 4.4)",4.4), - test_t("if(1 >= 2, 3, 4)",4.0), - test_t("if(1.1 >= 2.2, 3.3, 4.4)",4.4), - test_t("if((1.0+1.1) >= (2.0+1.2), 3.3, 4.4)",4.4), - test_t("if(((1.0 + 2.0) == 3.0) and ((4.0 + 5.0) < 9.0),1,2)",2.0), - test_t("(3.0 - 1.0 - 2.0) == ((3.0 - 1.0) - 2.0)",1.0), - test_t("true == true",1.0), - test_t("false == false",1.0), - test_t("true != false",1.0), - test_t("false != true",1.0), - test_t("(1 < 2) == true",1.0), - test_t("(1 > 2) == false",1.0), - test_t("true == (1 < 2)",1.0), - test_t("false == (1 > 2)",1.0), - test_t("(1 > 2) != true",1.0), - test_t("(1 < 2) != false",1.0), - test_t("true != (1 > 2)",1.0), - test_t("false != (1 < 2)",1.0), - test_t("(true and true) == true",1.0), - test_t("(false and false) == false",1.0), - test_t("(true or true) == true",1.0), - test_t("(false or false) == false",1.0), - test_t("(true and false) == false",1.0), - test_t("(false and true) == false",1.0), - test_t("(true or false) == true",1.0), - test_t("(false or true) == true",1.0), - test_t("(true & true) == true",1.0), - test_t("(false & false) == false",1.0), - test_t("(true | true) == true",1.0), - test_t("(false | false) == false",1.0), - test_t("(true & false) == false",1.0), - test_t("(false & true) == false",1.0), - test_t("(true | false) == true",1.0), - test_t("(false | true) == true",1.0), - test_t("clamp(-1,1,+1)",1.0), - test_t("clamp(-1,-1.5,+1.0)",-1.0), - test_t("clamp(-1,+1.5,+1.0)",+1.0), - test_t("clamp(-1,-1.5,+1.0) + clamp(-1,+1.5,+1.0)",0.0), - test_t("inrange(-2,1,+2) == ((-2 <= 1) and (1 <= +2))",1.0), - test_t("inrange(-2,1,+2) == if(({-2 <= 1} and [1 <= +2]),1.0,0.0)",1.0), - test_t("sgn( 0)", 0.0), - test_t("sgn(+3)",+1.0), - test_t("sgn(-3)",-1.0), - test_t("equal($f00(1.1,2.2,3.3),(1.1+2.2)/3.3)",1.0), - test_t("equal($f01(1.1,2.2,3.3),(1.1+2.2)*3.3)",1.0), - test_t("equal($f02(1.1,2.2,3.3),(1.1+2.2)-3.3)",1.0), - test_t("equal($f03(1.1,2.2,3.3),(1.1+2.2)+3.3)",1.0), - test_t("equal($f04(1.1,2.2,3.3),(1.1-2.2)+3.3)",1.0), - test_t("equal($f05(1.1,2.2,3.3),(1.1-2.2)/3.3)",1.0), - test_t("equal($f06(1.1,2.2,3.3),(1.1-2.2)*3.3)",1.0), - test_t("equal($f07(1.1,2.2,3.3),(1.1*2.2)+3.3)",1.0), - test_t("equal($f08(1.1,2.2,3.3),(1.1*2.2)-3.3)",1.0), - test_t("equal($f09(1.1,2.2,3.3),(1.1*2.2)/3.3)",1.0), - test_t("equal($f10(1.1,2.2,3.3),(1.1*2.2)*3.3)",1.0), - test_t("equal($f11(1.1,2.2,3.3),(1.1/2.2)+3.3)",1.0), - test_t("equal($f12(1.1,2.2,3.3),(1.1/2.2)-3.3)",1.0), - test_t("equal($f13(1.1,2.2,3.3),(1.1/2.2)/3.3)",1.0), - test_t("equal($f14(1.1,2.2,3.3),(1.1/2.2)*3.3)",1.0), - test_t("equal($f15(1.1,2.2,3.3),1.1/(2.2+3.3))",1.0), - test_t("equal($f16(1.1,2.2,3.3),1.1/(2.2-3.3))",1.0), - test_t("equal($f17(1.1,2.2,3.3),1.1/(2.2*3.3))",1.0), - test_t("equal($f18(1.1,2.2,3.3),1.1/(2.2/3.3))",1.0), - test_t("equal($f19(1.1,2.2,3.3),1.1*(2.2+3.3))",1.0), - test_t("equal($f20(1.1,2.2,3.3),1.1*(2.2-3.3))",1.0), - test_t("equal($f21(1.1,2.2,3.3),1.1*(2.2*3.3))",1.0), - test_t("equal($f22(1.1,2.2,3.3),1.1*(2.2/3.3))",1.0), - test_t("equal($f23(1.1,2.2,3.3),1.1-(2.2+3.3))",1.0), - test_t("equal($f24(1.1,2.2,3.3),1.1-(2.2-3.3))",1.0), - test_t("equal($f25(1.1,2.2,3.3),1.1-(2.2/3.3))",1.0), - test_t("equal($f26(1.1,2.2,3.3),1.1-(2.2*3.3))",1.0), - test_t("equal($f27(1.1,2.2,3.3),1.1+(2.2*3.3))",1.0), - test_t("equal($f28(1.1,2.2,3.3),1.1+(2.2/3.3))",1.0), - test_t("equal($f29(1.1,2.2,3.3),1.1+(2.2+3.3))",1.0), - test_t("equal($f30(1.1,2.2,3.3),1.1+(2.2-3.3))",1.0), - test_t("equal($f31(1.1,2.2,3.3),1.1*2.2^2+3.3)",1.0), - test_t("equal($f32(1.1,2.2,3.3),1.1*2.2^3+3.3)",1.0), - test_t("equal($f33(1.1,2.2,3.3),1.1*2.2^4+3.3)",1.0), - test_t("equal($f34(1.1,2.2,3.3),1.1*2.2^5+3.3)",1.0), - test_t("equal($f35(1.1,2.2,3.3),1.1*2.2^6+3.3)",1.0), - test_t("equal($f36(1.1,2.2,3.3),1.1*2.2^7+3.3)",1.0), - test_t("equal($f37(1.1,2.2,3.3),1.1*2.2^8+3.3)",1.0), - test_t("equal($f38(1.1,2.2,3.3),1.1*2.2^9+3.3)",1.0), - test_t("equal($f39(1.1,2.2,3.3),1.1*log(2.2)+3.3)",1.0), - test_t("equal($f40(1.1,2.2,3.3),1.1*log(2.2)-3.3)",1.0), - test_t("equal($f41(1.1,2.2,3.3),1.1*log10(2.2)+3.3)",1.0), - test_t("equal($f42(1.1,2.2,3.3),1.1*log10(2.2)-3.3)",1.0), - test_t("equal($f43(1.1,2.2,3.3),1.1*sin(2.2)+3.3)",1.0), - test_t("equal($f44(1.1,2.2,3.3),1.1*sin(2.2)-3.3)",1.0), - test_t("equal($f45(1.1,2.2,3.3),1.1*cos(2.2)+3.3)",1.0), - test_t("equal($f46(1.1,2.2,3.3),1.1*cos(2.2)-3.3)",1.0), - test_t("equal($f47(1.1,2.2,3.3),if(0!=1.1,2.2,3.3))",1.0), - test_t("equal($f48(1.1,2.2,3.3,4.4),1.1+((2.2+3.3)/4.4))",1.0), - test_t("equal($f49(1.1,2.2,3.3,4.4),1.1+((2.2+3.3)*4.4))",1.0), - test_t("equal($f50(1.1,2.2,3.3,4.4),1.1+((2.2-3.3)/4.4))",1.0), - test_t("equal($f51(1.1,2.2,3.3,4.4),1.1+((2.2-3.3)*4.4))",1.0), - test_t("equal($f52(1.1,2.2,3.3,4.4),1.1+((2.2*3.3)/4.4))",1.0), - test_t("equal($f53(1.1,2.2,3.3,4.4),1.1+((2.2*3.3)*4.4))",1.0), - test_t("equal($f54(1.1,2.2,3.3,4.4),1.1+((2.2/3.3)+4.4))",1.0), - test_t("equal($f55(1.1,2.2,3.3,4.4),1.1+((2.2/3.3)/4.4))",1.0), - test_t("equal($f56(1.1,2.2,3.3,4.4),1.1+((2.2/3.3)*4.4))",1.0), - test_t("equal($f57(1.1,2.2,3.3,4.4),1.1-((2.2+3.3)/4.4))",1.0), - test_t("equal($f58(1.1,2.2,3.3,4.4),1.1-((2.2+3.3)*4.4))",1.0), - test_t("equal($f59(1.1,2.2,3.3,4.4),1.1-((2.2-3.3)/4.4))",1.0), - test_t("equal($f60(1.1,2.2,3.3,4.4),1.1-((2.2-3.3)*4.4))",1.0), - test_t("equal($f61(1.1,2.2,3.3,4.4),1.1-((2.2*3.3)/4.4))",1.0), - test_t("equal($f62(1.1,2.2,3.3,4.4),1.1-((2.2*3.3)*4.4))",1.0), - test_t("equal($f63(1.1,2.2,3.3,4.4),1.1-((2.2/3.3)/4.4))",1.0), - test_t("equal($f64(1.1,2.2,3.3,4.4),1.1-((2.2/3.3)*4.4))",1.0), - test_t("equal($f65(1.1,2.2,3.3,4.4),((1.1+2.2)*3.3)-4.4)",1.0), - test_t("equal($f66(1.1,2.2,3.3,4.4),((1.1-2.2)*3.3)-4.4)",1.0), - test_t("equal($f67(1.1,2.2,3.3,4.4),((1.1*2.2)*3.3)-4.4)",1.0), - test_t("equal($f68(1.1,2.2,3.3,4.4),((1.1/2.2)*3.3)-4.4)",1.0), - test_t("equal($f69(1.1,2.2,3.3,4.4),((1.1+2.2)/3.3)-4.4)",1.0), - test_t("equal($f70(1.1,2.2,3.3,4.4),((1.1-2.2)/3.3)-4.4)",1.0), - test_t("equal($f71(1.1,2.2,3.3,4.4),((1.1*2.2)/3.3)-4.4)",1.0), - test_t("equal($f72(1.1,2.2,3.3,4.4),((1.1/2.2)/3.3)-4.4)",1.0), - test_t("equal($f73(1.1,2.2,3.3,4.4),(1.1*2.2)+(3.3*4.4))",1.0), - test_t("equal($f74(1.1,2.2,3.3,4.4),(1.1*2.2)-(3.3*4.4))",1.0), - test_t("equal($f75(1.1,2.2,3.3,4.4),(1.1*2.2)+(3.3/4.4))",1.0), - test_t("equal($f76(1.1,2.2,3.3,4.4),(1.1*2.2)-(3.3/4.4))",1.0), - test_t("equal($f77(1.1,2.2,3.3,4.4),(1.1/2.2)+(3.3/4.4))",1.0), - test_t("equal($f78(1.1,2.2,3.3,4.4),(1.1/2.2)-(3.3/4.4))",1.0), - test_t("equal($f79(1.1,2.2,3.3,4.4),(1.1/2.2)-(3.3*4.4))",1.0), - test_t("equal($f80(1.1,2.2,3.3,4.4),1.1/(2.2+(3.3*4.4)))",1.0), - test_t("equal($f81(1.1,2.2,3.3,4.4),1.1/(2.2-(3.3*4.4)))",1.0), - test_t("equal($f82(1.1,2.2,3.3,4.4),1.1*(2.2+(3.3*4.4)))",1.0), - test_t("equal($f83(1.1,2.2,3.3,4.4),1.1*(2.2-(3.3*4.4)))",1.0), - test_t("equal($f84(1.1,2.2,3.3,4.4),1.1*2.2^2+3.3*4.4^2)",1.0), - test_t("equal($f85(1.1,2.2,3.3,4.4),1.1*2.2^3+3.3*4.4^3)",1.0), - test_t("equal($f86(1.1,2.2,3.3,4.4),1.1*2.2^4+3.3*4.4^4)",1.0), - test_t("equal($f87(1.1,2.2,3.3,4.4),1.1*2.2^5+3.3*4.4^5)",1.0), - test_t("equal($f88(1.1,2.2,3.3,4.4),1.1*2.2^6+3.3*4.4^6)",1.0), - test_t("equal($f89(1.1,2.2,3.3,4.4),1.1*2.2^7+3.3*4.4^7)",1.0), - test_t("equal($f90(1.1,2.2,3.3,4.4),1.1*2.2^8+3.3*4.4^8)",1.0), - test_t("equal($f91(1.1,2.2,3.3,4.4),1.1*2.2^9+3.3*4.4^9)",1.0), - test_t("equal($f92(1.1,2.2,3.3,4.4),if(1.1 and 2.2,3.3,4.4))",1.0), - test_t("equal($f93(1.1,2.2,3.3,4.4),if(1.1 or 2.2,3.3,4.4))",1.0), - test_t("equal($f94(1.1,2.2,3.3,4.4),if(1.1 < 2.2,3.3,4.4))",1.0), - test_t("equal($f95(1.1,2.2,3.3,4.4),if(1.1 <= 2.2,3.3,4.4))",1.0), - test_t("equal($f96(1.1,2.2,3.3,4.4),if(1.1 > 2.2,3.3,4.4))",1.0), - test_t("equal($f97(1.1,2.2,3.3,4.4),if(1.1 >= 2.2,3.3,4.4))",1.0), - test_t("equal($f98(1.1,2.2,3.3,4.4),if(equal(1.1,2.2),3.3,4.4))",1.0), - test_t("equal($f99(1.1,2.2,3.3,4.4),1.1*sin(2.2)+3.3*cos(4.4))",1.0), - test_t("equal((48.0/2.0*(9.0+3.0)),288.0)",1.0), - test_t("equal((48.0/2.0(9.0+3.0)),288.0)",1.0), - test_t("equal((6.0/2.0(1.0+2.0)),9.0)",1.0), - test_t("1+2+3+4+5+6+7+8+9+0",45.0), - test_t("1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0",45.0), - test_t("1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0 + 8.0 + 9.0 + 0.0",45.0), - test_t("(1+2)+(3+4)+(5+6)+(7+8)+(9+0)",45.0), - test_t("(1-2)+(3-4)+(5-6)+(7-8)+(9-0)",+5.0), - test_t("(1+2)-(3+4)-(5+6)-(7+8)-(9+0)",-39.0), - test_t("(1.0+2.0)+(3.0+4.0)+(5.0+6.0)+(7.0+8.0)+(9.0+0.0)",45.0), - test_t("(1.0-2.0)+(3.0-4.0)+(5.0-6.0)+(7.0-8.0)+(9.0-0.0)",+5.0), - test_t("(1.0+2.0)-(3.0+4.0)-(5.0+6.0)-(7.0+8.0)-(9.0+0.0)",-39.0), - test_t("[(1.0+2.0)+[3.0+4.0]+(5.0+6.0)]+([7.0+8.0]+(9.0+0.0))",45.0), - test_t("([1.0-2.0]+(3.0-4.0)+[5.0-6.0])+[(7.0-8.0)+[9.0-0.0]]",+5.0), - test_t("((1.0+2.0))-[(3.0+4.0)]-((5.0+6.0))-[(7.0+8.0)]-((9.0+0.0))",-39.0), - test_t("{[(1.0+2.0)+[3.0+4.0]+({5.0+6.0})]}+({[7.0+8.0]+(9.0+0.0)})",45.0), - test_t("{([1.0-2.0]+(3.0-4.0)+[5.0-6.0])}+[({+7.0}-{+8.0})+[{+9.0-0.0}]]",+5.0), - test_t("((+1.0+2.0))-[({+3.0+4.0})]-(({+5.0+6.0}))-[({+7.0}+8.0)]-(({+9.0}+{0.0}))",-39.0), - test_t("1+2-3*4/5+6-7*8/9+0",0.37777777777777777778), - test_t("1.1+2.2-3.3*4.4/5.5+6.6-7.7*8.8/9.9+0.0",0.41555555555555555556), - test_t("(1+2)-(3*4)/(5+6)-(7*8)/(9+0)",-4.31313131313131313131), - test_t("1/1+1/2+1/3+1/4+1/5+1/6+1/7+1/8+1/9",2.82896825396825396825), - test_t("(1/1)+(1/2)+(1/3)+(1/4)+(1/5)+(1/6)+(1/7)+(1/8)+(1/9)",2.82896825396825396825), - test_t("1.0/1.0+1.0/2.0+1.0/3.0+1.0/4.0+1.0/5.0+1.0/6.0+1.0/7.0+1.0/8.0+1.0/9",2.82896825396825396825), - test_t("(1.0/1.0)+(1.0/2.0)+(1.0/3.0)+(1.0/4.0)+(1.0/5.0)+(1.0/6.0)+(1.0/7.0)+(1.0/8.0)+(1.0/9)",2.82896825396825396825), - test_t("1/1*1/2*1/3*1/4*1/5*1/6*1/7*1/8*1/9",0.00000275573192239859), - test_t("(1/1)*(1/2)*(1/3)*(1/4)*(1/5)*(1/6)*(1/7)*(1/8)*(1/9)",0.00000275573192239859), - test_t("1.0/1.0*1.0/2.0*1.0/3.0*1.0/4.0*1.0/5.0*1.0/6.0*1.0/7.0*1.0/8.0*1.0/9",0.00000275573192239859), - test_t("(1.0/1.0)*(1.0/2.0)*(1.0/3.0)*(1.0/4.0)*(1.0/5.0)*(1.0/6.0)*(1.0/7.0)*(1.0/8.0)*(1.0/9)",0.00000275573192239859), - test_t("equal(poly01(1.2345,2.2,1.1),(2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly02(1.2345,3.3,2.2,1.1),(3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly03(1.2345,4.4,3.3,2.2,1.1),(4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly04(1.2345,5.5,4.4,3.3,2.2,1.1),(5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly05(1.2345,6.6,5.5,4.4,3.3,2.2,1.1),(6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly06(1.2345,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(7.7*1.2345^6+6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly07(1.2345,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(8.8*1.2345^7+7.7*1.2345^6+6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly08(1.2345,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(9.9*1.2345^8+8.8*1.2345^7+7.7*1.2345^6+6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly09(1.2345,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(1.1*1.2345^9+9.9*1.2345^8+8.8*1.2345^7+7.7*1.2345^6+6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), - test_t("equal(poly10(1.37,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(2.2*1.37^10+1.1*1.37^9+9.9*1.37^8+8.8*1.37^7+7.7*1.37^6+6.6*1.37^5+5.5*1.37^4+4.4*1.37^3+3.3*1.37^2+2.2*1.37^1+1.1))",1.0), - test_t("equal(poly11(1.37,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(3.3*1.37^11+2.2*1.37^10+1.1*1.37^9+9.9*1.37^8+8.8*1.37^7+7.7*1.37^6+6.6*1.37^5+5.5*1.37^4+4.4*1.37^3+3.3*1.37^2+2.2*1.37^1+1.1))",1.0), - test_t("equal(poly12(1.37,4.4,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(4.4*1.37^12+3.3*1.37^11+2.2*1.37^10+1.1*1.37^9+9.9*1.37^8+8.8*1.37^7+7.7*1.37^6+6.6*1.37^5+5.5*1.37^4+4.4*1.37^3+3.3*1.37^2+2.2*1.37^1+1.1))",1.0), - test_t("equal(\t \n(\n \r1.1\t\t - \n\n 2.2\n\n/\r3.3\t),(1.1-2.2/3.3))",1.0), - test_t("equal((pi^2^3),(pi^8))",1.0), - test_t("equal((pi^(2^3)),(pi^8))",1.0), - test_t("equal(pi^2^3-pi^8,0)",1.0), - test_t("equal((2*pi^2^3),2*(pi^8))",1.0), - test_t("equal((pi^2^3*2),2*(pi^8))",1.0), - test_t("equal((pi^2^3/2),(pi^8)/2)",1.0), - test_t("equal((pi^2.2^3.3),(pi^13.4894687605338489))",1.0), - test_t("equal((pi^(2.2^3.3)),(pi^13.4894687605338489))",1.0), - test_t("equal((2.2*pi^2.2^3.3),2.2*(pi^13.4894687605338489))",1.0), - test_t("equal((pi^2.2^3.3*2),2*(pi^13.4894687605338489))",1.0), - test_t("equal((pi^2.2^3.3/2.2),(pi^13.4894687605338489)/2.2)",1.0), - test_t("equal((pi^-2^3),1/(pi^8))",1.0), - test_t("equal((pi^(-2^3)),1/(pi^8))",1.0), - test_t("equal((pi^2^-3),(pi^(1/8)))",1.0), - test_t("equal((pi^(2^-3)),(pi^(1/8)))",1.0), - test_t("equal((pi^-2^-3),1/(pi^(1/8)))",1.0), - test_t("equal((pi^(-2^-3)),1/(pi^(1/8)))",1.0), - test_t("equal((-pi^2^3),(-pi^8))",1.0), - test_t("equal((-pi^(2^3)),(-pi^8))",1.0), - test_t("equal(-pi^2^3--pi^8,0)",1.0), - test_t("equal((2*-pi^2^3),2*(-pi^8))",1.0), - test_t("equal((-pi^2^3*2),2*(-pi^8))",1.0), - test_t("equal((-pi^2^3/2),(-pi^8)/2)",1.0), - test_t("equal((-pi^2.2^3.3),(-pi^13.4894687605338489))",1.0), - test_t("equal((-pi^(2.2^3.3)),(-pi^13.4894687605338489))",1.0), - test_t("equal((2.2*-pi^2.2^3.3),2.2*(-pi^13.4894687605338489))",1.0), - test_t("equal((-pi^2.2^3.3*2),2*(-pi^13.4894687605338489))",1.0), - test_t("equal((-pi^2.2^3.3/2.2),(-pi^13.4894687605338489)/2.2)",1.0), - test_t("equal((-pi^-2^3),1/(-pi^8))",1.0), - test_t("equal((-pi^(-2^3)),1/(-pi^8))",1.0), - test_t("equal((-pi^2^-3),(-pi^(1/8)))",1.0), - test_t("equal((-pi^(2^-3)),(-pi^(1/8)))",1.0), - test_t("equal((-pi^-2^-3),1/(-pi^(1/8)))",1.0), - test_t("equal((-pi^(-2^-3)),1/(-pi^(1/8)))",1.0), - test_t("equal((+pi^+2^+3),(+pi^+8))",1.0), - test_t("equal((+pi^(2^3)),(+pi^+8))",1.0), - test_t("equal(+pi^+2^+3-+pi^+8,0)",1.0), - test_t("equal((+2*+pi^+2^+3),+2*(+pi^+8))",1.0), - test_t("equal((+pi^+2^+3*+2),+2*(+pi^+8))",1.0), - test_t("equal((+pi^+2^+3/+2),(+pi^+8)/+2)",1.0), - test_t("equal((+pi^+2.2^+3.3),(+pi^+13.4894687605338489))",1.0), - test_t("equal((+pi^(+2.2^+3.3)),(+pi^+13.4894687605338489))",1.0), - test_t("equal((+2.2*+pi^+2.2^+3.3),+2.2*(+pi^+13.4894687605338489))",1.0), - test_t("equal((+pi^+2.2^+3.3*+2),+2*(+pi^+13.4894687605338489))",1.0), - test_t("equal((+pi^+2.2^+3.3/+2.2),(+pi^+13.4894687605338489)/+2.2)",1.0), - test_t("equal((+pi^-2^3),1/(+pi^+8))",1.0), - test_t("equal((+pi^(-2^3)),1/(+pi^+8))",1.0), - test_t("equal((+pi^2^-3),(+pi^(+1/+8)))",1.0), - test_t("equal((+pi^(2^-3)),(+pi^(+1/+8)))",1.0), - test_t("equal((+pi^-2^-3),1/(+pi^(+1/+8)))",1.0), - test_t("equal((+pi^(-2^-3)),1/(+pi^(+1/+8)))",1.0), - test_t("equal((-pi^+2^+3),(-pi^+8))",1.0), - test_t("equal((-pi^(2^3)),(-pi^+8))",1.0), - test_t("equal(-pi^+2^+3--pi^+8,0)",1.0), - test_t("equal((+2*-pi^+2^+3),2*(-pi^+8))",1.0), - test_t("equal((-pi^+2^+3*2),2*(-pi^+8))",1.0), - test_t("equal((-pi^+2^+3/+2),(-pi^+8)/+2)",1.0), - test_t("equal((-pi^+2.2^+3.3),(-pi^+13.4894687605338489))",1.0), - test_t("equal((-pi^(2.2^3.3)),(-pi^+13.4894687605338489))",1.0), - test_t("equal((+2.2*-pi^+2.2^+3.3),2.2*(-pi^+13.4894687605338489))",1.0), - test_t("equal((-pi^+2.2^+3.3*2),2*(-pi^+13.4894687605338489))",1.0), - test_t("equal((-pi^+2.2^+3.3/+2.2),(-pi^+13.4894687605338489)/+2.2)",1.0), - test_t("equal((-pi^-2^3),1/(-pi^+8))",1.0), - test_t("equal((-pi^(-2^3)),1/(-pi^+8))",1.0), - test_t("equal((-pi^2^-3),(-pi^(+1/+8)))",1.0), - test_t("equal((-pi^(2^-3)),(-pi^(+1/+8)))",1.0), - test_t("equal((-pi^-2^-3),1/(-pi^(+1/+8)))",1.0), - test_t("equal((-pi^(-2^-3)),1/(-pi^(+1/+8)))",1.0), - test_t("switch { case (1 <= 2) : 1; default: 1.12345; }",1.0), - test_t("switch { case (1 > 2) : 0; case (1 <= 2) : 1; default: 1.12345; }",1.0), - test_t("switch { case (1 <= 2) : switch { case (1 <= 2) : 1; default: 1.12345; }; default: 1.12345; }",1.0), - test_t("switch { case [1 <= 2] : 1; default: 1.12345; }",1.0), - test_t("switch { case [1 > 2] : 0; case [1 <= 2] : 1; default: 1.12345; }",1.0), - test_t("switch { case [1 <= 2] : switch { case [1 <= 2] : 1; default: 1.12345; }; default: 1.12345; }",1.0), - test_t("switch { case {1 <= 2} : 1; default: 1.12345; }",1.0), - test_t("switch { case {1 > 2} : 0; case {1 <= 2} : 1; default: 1.12345; }",1.0), - test_t("switch { case {1 <= 2} : switch { case {1 <= 2} : 1; default: 1.12345; }; default: 1.12345; }",1.0), - test_t("switch { case [(1 <= 2)] : {1}; default: 1.12345; }",1.0), - test_t("switch { case ([1 > 2]) : [0]; case ([1 <= 2]) : 1; default: 1.12345; }",1.0), - test_t("switch { case {(1 <= 2)} : switch { case ({1 <= 2}) : 1; default: 1.12345; }; default: 1.12345; }",1.0), - test_t("switch { case 1 > 1 : 1; case 2 > 2 : 2; case 3 = 3 : 3; case 4 > 4 : 4; default : 5; }",3.0), - test_t("repeat 1.1 + 2.2 until (1 < 2)",3.3), - test_t("repeat (1.1 + 2.2) until (1 < 2)",3.3), - test_t("repeat 1.1 + 2.2; until (1 < 2)",3.3), - test_t("repeat (1.1 + 2.2); until (1 < 2)",3.3), - test_t("repeat 1.1234; 1 < 2; 1.1 + 2.2 until (1 < 2)",3.3), - test_t("repeat 1.1234; 1 < 2; (1.1 + 2.2) until (1 < 2)",3.3), - test_t("repeat 1.1234; 1 < 2; 1.1 + 2.2; until (1 < 2)",3.3), - test_t("repeat 1.1234; 1 < 2; (1.1 + 2.2); until (1 < 2)",3.3), - test_t("[*] { case 1 < 2 : 1 / 2; case (1 < 3) : 2 / 2; case 1 < 4 : 3 / 2; case (1 < 5) : 4 / 2; }",2.0), - test_t(" 0 ? 1 : 2",2.0), - test_t(" 1 ? 3 : 4",3.0), - test_t("(0 ? 1 : 2) == 2",1.0), - test_t("(1 ? 3 : 4) == 3",1.0), - test_t("[(0)] ? [(1)] : [(2)]",2.0), - test_t("([(0)] ? [(1)] : [(2)]) == 2",1.0), - test_t("([(1)] ? [(3)] : [(4)]) == 3",1.0), - test_t("(1 < 2 ? 3 : 4) == 3",1.0), - test_t("(1 > 2 ? 3 : 4) == 4",1.0), - test_t("(1 < 2 ? 3 + 5 : 4) == 8",1.0), - test_t("(1 > 2 ? 3 : 4 + 5) == 9",1.0), - test_t("(2 < 3 + 3 ? 7 : 9) == 7",1.0), - test_t("(1 + 1 < 3 ? 7 : 9) == 7",1.0), - test_t("(1 + 1 < 3 + 3 ? 7 : 9) == 7",1.0), - test_t("(2 > 3 + 3 ? 7 : 9) == 9",1.0), - test_t("(1 + 1 > 3 ? 7 : 9) == 9",1.0), - test_t("(1 + 1 > 3 + 3 ? 7 : 9) == 9",1.0), - test_t("(2 < (3 + 3) ? 7 : 9) == 7",1.0), - test_t("((1 + 1) < 3 ? 7 : 9) == 7",1.0), - test_t("((1 + 1) < (3 + 3) ? 7 : 9) == 7",1.0), - test_t("(min(1,2) ? 1 + 3 : 1 + 4) == 4",1.0), - test_t("(min(0,1) ? 1 + 3 : 1 + 4) == 5",1.0), - test_t("if (1 < 2) 3; == 3",1.0), - test_t("if (1 > 2) 3; == null",1.0), - test_t("if (1 < 2) 3; else 4; == 3",1.0), - test_t("if (1 > 2) 3; else 4; == 4",1.0), - test_t("if (1 < 2) 3; else {1+2; 4;} == 3",1.0), - test_t("if (1 > 2) 3; else {1+2; 4;} == 4",1.0), - test_t("if (1 < 2) 3; else if (1 < 2) 4; == 3",1.0), - test_t("if (1 > 2) 3; else if (1 < 2) 4; == 4",1.0), - test_t("if (1 > 2) 3; else if (1 > 2) 4; == null",1.0), - test_t("if (1 < 2) 3; else if (1 < 2) {1+2; 4;} == 3",1.0), - test_t("if (1 > 2) 3; else if (1 < 2) {1+2; 4;} == 4",1.0), - test_t("if (1 > 2) 3; else if (1 > 2) {1+2; 4;} == null",1.0), - test_t("if (1 < 2) { 1+2; 3;} == 3",1.0), - test_t("if (1 > 2) { 1+2; 3;} == null",1.0), - test_t("if (1 < 2) { 1+2; 3;} else 4; == 3",1.0), - test_t("if (1 > 2) { 1+2; 3;} else 4; == 4",1.0), - test_t("if (1 < 2) { 1+2; 3;} else {1+2; 4;} == 3",1.0), - test_t("if (1 > 2) { 1+2; 3;} else {1+2; 4;} == 4",1.0), - test_t("if (1 < 2) { 1+2; 3;} else if (1 < 2) 4; == 3",1.0), - test_t("if (1 > 2) { 1+2; 3;} else if (1 < 2) 4; == 4",1.0), - test_t("if (1 > 2) { 1+2; 3;} else if (1 > 2) 4; == null",1.0), - test_t("if (1 < 2) { 1+2; 3;} else if (1 < 2) {1+2; 4;} == 3",1.0), - test_t("if (1 > 2) { 1+2; 3;} else if (1 < 2) {1+2; 4;} == 4",1.0), - test_t("if (1 > 2) { 1+2; 3;} else if (1 > 2) {1+2; 4;} == null",1.0) - }; +{ + // Note: Each of following tests must compile down + // to a single literal node. + test_t("0",0.0), + test_t("1",1.0), + test_t("2",2.0), + test_t("3",3.0), + test_t("4",4.0), + test_t("5",5.0), + test_t("6",6.0), + test_t("7",7.0), + test_t("8",8.0), + test_t("9",9.0), + test_t("12.12",12.12), + test_t("123.123",123.123), + test_t("1234.1234",1234.1234), + test_t("12345.12345",12345.12345), + test_t("123456.123456",123456.123456), + test_t("0.0",0.0), + test_t("1.0",1.0), + test_t("2.0",2.0), + test_t("3.0",3.0), + test_t("4.0",4.0), + test_t("5.0",5.0), + test_t("6.0",6.0), + test_t("7.0",7.0), + test_t("8.0",8.0), + test_t("9.0",9.0), + test_t("0.0",0.0), + test_t("1.1",1.1), + test_t("2.2",2.2), + test_t("3.3",3.3), + test_t("4.4",4.4), + test_t("5.5",5.5), + test_t("6.6",6.6), + test_t("7.7",7.7), + test_t("8.8",8.8), + test_t("9.9",9.9), + test_t("+0",0.0), + test_t("+1",1.0), + test_t("+2",2.0), + test_t("+3",3.0), + test_t("+4",4.0), + test_t("+5",5.0), + test_t("+6",6.0), + test_t("+7",7.0), + test_t("+8",8.0), + test_t("+9",9.0), + test_t("+0.0",0.0), + test_t("+1.0",1.0), + test_t("+2.0",2.0), + test_t("+3.0",3.0), + test_t("+4.0",4.0), + test_t("+5.0",5.0), + test_t("+6.0",6.0), + test_t("+7.0",7.0), + test_t("+8.0",8.0), + test_t("+9.0",9.0), + test_t("+0.0",0.0), + test_t("+1.1",1.1), + test_t("+2.2",2.2), + test_t("+3.3",3.3), + test_t("+4.4",4.4), + test_t("+5.5",5.5), + test_t("+6.6",6.6), + test_t("+7.7",7.7), + test_t("+8.8",8.8), + test_t("+9.9",9.9), + test_t("-0",-0.0), + test_t("-1",-1.0), + test_t("-2",-2.0), + test_t("-3",-3.0), + test_t("-4",-4.0), + test_t("-5",-5.0), + test_t("-6",-6.0), + test_t("-7",-7.0), + test_t("-8",-8.0), + test_t("-9",-9.0), + test_t("-0.0",-0.0), + test_t("-1.0",-1.0), + test_t("-2.0",-2.0), + test_t("-3.0",-3.0), + test_t("-4.0",-4.0), + test_t("-5.0",-5.0), + test_t("-6.0",-6.0), + test_t("-7.0",-7.0), + test_t("-8.0",-8.0), + test_t("-9.0",-9.0), + test_t("-0.0",-0.0), + test_t("-1.1",-1.1), + test_t("-2.2",-2.2), + test_t("-3.3",-3.3), + test_t("-4.4",-4.4), + test_t("-5.5",-5.5), + test_t("-6.6",-6.6), + test_t("-7.7",-7.7), + test_t("-8.8",-8.8), + test_t("-9.9",-9.9), + test_t("0.0e+0" ,+0.0e+0), + test_t("1.1e+1" ,+1.1e+1), + test_t("2.2e+2" ,+2.2e+2), + test_t("3.3e+3" ,+3.3e+3), + test_t("4.4e+4" ,+4.4e+4), + test_t("5.5e+5" ,+5.5e+5), + test_t("6.6e+6" ,+6.6e+6), + test_t("7.7e+7" ,+7.7e+7), + test_t("8.8e+8" ,+8.8e+8), + test_t("9.9e+9" ,+9.9e+9), + test_t("-0.0e+0",-0.0e+0), + test_t("-1.1e+1",-1.1e+1), + test_t("-2.2e+2",-2.2e+2), + test_t("-3.3e+3",-3.3e+3), + test_t("-4.4e+4",-4.4e+4), + test_t("-5.5e+5",-5.5e+5), + test_t("-6.6e+6",-6.6e+6), + test_t("-7.7e+7",-7.7e+7), + test_t("-8.8e+8",-8.8e+8), + test_t("-9.9e+9",-9.9e+9), + test_t("0.0E+0" ,+0.0E+0), + test_t("1.1E+1" ,+1.1E+1), + test_t("2.2E+2" ,+2.2E+2), + test_t("3.3E+3" ,+3.3E+3), + test_t("4.4E+4" ,+4.4E+4), + test_t("5.5E+5" ,+5.5E+5), + test_t("6.6E+6" ,+6.6E+6), + test_t("7.7E+7" ,+7.7E+7), + test_t("8.8E+8" ,+8.8E+8), + test_t("9.9E+9" ,+9.9E+9), + test_t("-0.0E+0",-0.0E+0), + test_t("-1.1E+1",-1.1E+1), + test_t("-2.2E+2",-2.2E+2), + test_t("-3.3E+3",-3.3E+3), + test_t("-4.4E+4",-4.4E+4), + test_t("-5.5E+5",-5.5E+5), + test_t("-6.6E+6",-6.6E+6), + test_t("-7.7E+7",-7.7E+7), + test_t("-8.8E+8",-8.8E+8), + test_t("-9.9E+9",-9.9E+9), + test_t("(0)",0.0), + test_t("(1)",1.0), + test_t("(2)",2.0), + test_t("(3)",3.0), + test_t("(4)",4.0), + test_t("(5)",5.0), + test_t("(6)",6.0), + test_t("(7)",7.0), + test_t("(8)",8.0), + test_t("(9)",9.0), + test_t("(0.0)",0.0), + test_t("(1.0)",1.0), + test_t("(2.0)",2.0), + test_t("(3.0)",3.0), + test_t("(4.0)",4.0), + test_t("(5.0)",5.0), + test_t("(6.0)",6.0), + test_t("(7.0)",7.0), + test_t("(8.0)",8.0), + test_t("(9.0)",9.0), + test_t("(0.0)",0.0), + test_t("(1.1)",1.1), + test_t("(2.2)",2.2), + test_t("(3.3)",3.3), + test_t("(4.4)",4.4), + test_t("(5.5)",5.5), + test_t("(6.6)",6.6), + test_t("(7.7)",7.7), + test_t("(8.8)",8.8), + test_t("(9.9)",9.9), + test_t("(+0)" ,0.0), + test_t("(+1)" ,1.0), + test_t("(+2)" ,2.0), + test_t("(+3)" ,3.0), + test_t("(+4)" ,4.0), + test_t("(+5)" ,5.0), + test_t("(+6)" ,6.0), + test_t("(+7)" ,7.0), + test_t("(+8)" ,8.0), + test_t("(+9)" ,9.0), + test_t("(+0.0)",0.0), + test_t("(+1.0)",1.0), + test_t("(+2.0)",2.0), + test_t("(+3.0)",3.0), + test_t("(+4.0)",4.0), + test_t("(+5.0)",5.0), + test_t("(+6.0)",6.0), + test_t("(+7.0)",7.0), + test_t("(+8.0)",8.0), + test_t("(+9.0)",9.0), + test_t("(+0.0)",0.0), + test_t("(+1.1)",1.1), + test_t("(+2.2)",2.2), + test_t("(+3.3)",3.3), + test_t("(+4.4)",4.4), + test_t("(+5.5)",5.5), + test_t("(+6.6)",6.6), + test_t("(+7.7)",7.7), + test_t("(+8.8)",8.8), + test_t("(+9.9)",9.9), + test_t("(-0)" ,-0.0), + test_t("(-1)" ,-1.0), + test_t("(-2)" ,-2.0), + test_t("(-3)" ,-3.0), + test_t("(-4)" ,-4.0), + test_t("(-5)" ,-5.0), + test_t("(-6)" ,-6.0), + test_t("(-7)" ,-7.0), + test_t("(-8)" ,-8.0), + test_t("(-9)" ,-9.0), + test_t("(-0.0)",-0.0), + test_t("(-1.0)",-1.0), + test_t("(-2.0)",-2.0), + test_t("(-3.0)",-3.0), + test_t("(-4.0)",-4.0), + test_t("(-5.0)",-5.0), + test_t("(-6.0)",-6.0), + test_t("(-7.0)",-7.0), + test_t("(-8.0)",-8.0), + test_t("(-9.0)",-9.0), + test_t("(-0.0)",-0.0), + test_t("(-1.1)",-1.1), + test_t("(-2.2)",-2.2), + test_t("(-3.3)",-3.3), + test_t("(-4.4)",-4.4), + test_t("(-5.5)",-5.5), + test_t("(-6.6)",-6.6), + test_t("(-7.7)",-7.7), + test_t("(-8.8)",-8.8), + test_t("(-9.9)",-9.9), + test_t("-(1.1)",-1.1), + test_t("-(1.1+2.2)",-3.3), + test_t("1234567890",1234567890), + test_t("123456789.0",123456789.0), + test_t("+1234567890",1234567890), + test_t("+123456789.0",123456789.0), + test_t("-1234567890",-1234567890), + test_t("-123456789.0",-123456789.0), + test_t("1234.567890",1234.567890), + test_t("-1234.567890",-1234.567890), + test_t("0+9",9.0), + test_t("1+8",9.0), + test_t("2+7",9.0), + test_t("3+6",9.0), + test_t("4+5",9.0), + test_t("5+4",9.0), + test_t("6+3",9.0), + test_t("7+2",9.0), + test_t("8+1",9.0), + test_t("9+0",9.0), + test_t(" 0 + 9 ",9.0), + test_t(" 1 + 8 ",9.0), + test_t(" 2 + 7 ",9.0), + test_t(" 3 + 6 ",9.0), + test_t(" 4 + 5 ",9.0), + test_t(" 5 + 4 ",9.0), + test_t(" 6 + 3 ",9.0), + test_t(" 7 + 2 ",9.0), + test_t(" 8 + 1 ",9.0), + test_t(" 9 + 0 ",9.0), + test_t("( 0 + 9 )",9.0), + test_t("( 1 + 8 )",9.0), + test_t("( 2 + 7 )",9.0), + test_t("( 3 + 6 )",9.0), + test_t("( 4 + 5 )",9.0), + test_t("( 5 + 4 )",9.0), + test_t("( 6 + 3 )",9.0), + test_t("( 7 + 2 )",9.0), + test_t("( 8 + 1 )",9.0), + test_t("( 9 + 0 )",9.0), + test_t("1E1+1",11.0), + test_t("1e1+1",11.0), + test_t("1E1-1", 9.0), + test_t("1e1-1", 9.0), + test_t("1E01+1",11.0), + test_t("1e01+1",11.0), + test_t("1E01-1", 9.0), + test_t("1e01-1", 9.0), + test_t("1+2",+3.0), + test_t("1-2",-1.0), + test_t("1*2",+2.0), + test_t("1/2",+0.5), + test_t("1.1+2.2", +3.3), + test_t("1.1-2.2", -1.1), + test_t("1.1*2.2",+2.42), + test_t("1.1/2.2", +0.5), + test_t("0-9",-9.0), + test_t("1-8",-7.0), + test_t("2-7",-5.0), + test_t("3-6",-3.0), + test_t("4-5",-1.0), + test_t("5-4",+1.0), + test_t("6-3",+3.0), + test_t("7-2",+5.0), + test_t("8-1",+7.0), + test_t("9-0",+9.0), + test_t("2.*3",+6.0), + test_t("2.*3.",+6.0), + test_t("2.+3",+5.0), + test_t("2.+3.",+5.0), + test_t("123.*456.",+56088.0), + test_t(" 0 - 9 ",-9.0), + test_t(" 1 - 8 ",-7.0), + test_t(" 2 - 7 ",-5.0), + test_t(" 3 - 6 ",-3.0), + test_t(" 4 - 5 ",-1.0), + test_t(" 5 - 4 ",+1.0), + test_t(" 6 - 3 ",+3.0), + test_t(" 7 - 2 ",+5.0), + test_t(" 8 - 1 ",+7.0), + test_t(" 9 - 0 ",+9.0), + test_t("( 0 - 9 )",-9.0), + test_t("( 1 - 8 )",-7.0), + test_t("( 2 - 7 )",-5.0), + test_t("( 3 - 6 )",-3.0), + test_t("( 4 - 5 )",-1.0), + test_t("( 5 - 4 )",+1.0), + test_t("( 6 - 3 )",+3.0), + test_t("( 7 - 2 )",+5.0), + test_t("( 8 - 1 )",+7.0), + test_t("( 9 - 0 )",+9.0), + test_t("1 - -1" , 2.0), + test_t("1 --1" , 2.0), + test_t("1-- 1" , 2.0), + test_t("1--1" , 2.0), + test_t("1 -- -1", 0.0), + test_t("1 + -1" , 0.0), + test_t("1 +-1" , 0.0), + test_t("1+- 1" , 0.0), + test_t("1+-1" , 0.0), + test_t("1 +- -1", 2.0), + test_t("1 + +1" , 2.0), + test_t("1 ++1" , 2.0), + test_t("1 - -1 + 1" , 3.0), + test_t("1 --1 + 1" , 3.0), + test_t("1-- 1 + 1" , 3.0), + test_t("1--1 + 1" , 3.0), + test_t("1 -- -1 + 1", 1.0), + test_t("1 + -1 + 1" , 1.0), + test_t("1 +-1 + 1" , 1.0), + test_t("1+- 1 + 1" , 1.0), + test_t("1+-1 + 1" , 1.0), + test_t("1 +- -1 + 1", 3.0), + test_t("1 + +1 + 1" , 3.0), + test_t("1 ++1 + 1" , 3.0), + test_t("1 - -1 - 1" , 1.0), + test_t("1 --1 - 1" , 1.0), + test_t("1-- 1 - 1" , 1.0), + test_t("1--1 - 1" , 1.0), + test_t("1 -- -1 - 1", -1.0), + test_t("1 + -1 - 1" , -1.0), + test_t("1 +-1 - 1" , -1.0), + test_t("1+- 1 - 1" , -1.0), + test_t("1+-1 - 1" , -1.0), + test_t("1 +- -1 - 1", 1.0), + test_t("1 + +1 - 1" , 1.0), + test_t("1 ++1 - 1" , 1.0), + test_t("-(1+2)",-3.0), + test_t("+(1+2)",+3.0), + test_t("+(1-2)",-1.0), + test_t("-(1-2)",+1.0), + test_t("(-3*-6)",+18.0), + test_t("(-6*-3)",+18.0), + test_t("-(-3*-6)",-18.0), + test_t("-(-6*-3)",-18.0), + test_t("1.1+2.2+3.3",+6.6), + test_t("+1.1+2.2+3.3",+6.6), + test_t("-1.1-2.2-3.3",-6.6), + test_t("1.1*2.2*3.3",+7.986), + test_t("+1.1*2.2*3.3",+7.986), + test_t("-1.1*-2.2*-3.3",-7.986), + test_t("1 + 1/2",+1.5), + test_t("1 + (1/2)",+1.5), + test_t("1.1 + 1.1/2.2",+1.6), + test_t("1.1 + (1.1/2.2)",+1.6), + test_t("2 * 1/2",+1.0), + test_t("2 * (1/2)",+1.0), + test_t("2.2 * 1.1/2.2",+1.1), + test_t("2.2 * (1.1/2.2)",+1.1), + test_t("1^2",1.0), + test_t("2^1",2.0), + test_t("2^3",8.0), + test_t("-2^3",-8.0), + test_t("-2^4",-16.0), + test_t("(-2)^3",-8.0), + test_t("(-2)^4",+16.0), + test_t("3^2^4",43046721.0), + test_t("1.1^2.2",1.23328630055466251099), + test_t("2.2^1.1",2.3804822576003541627), + test_t("2.2^3.3",13.48946876053338489127), + test_t("3.3^2.2^1.1",17.15193942371376191362), + test_t("+3.3^2.2^1.1",17.15193942371376191362), + test_t("3.3^+2.2^1.1",17.15193942371376191362), + test_t("3.3^2.2^+1.1",17.15193942371376191362), + test_t("3.3^2.2^-1.1",1.65127293793867959137), + test_t("+3.3^+2.2^-1.1",1.65127293793867959137), + test_t("1.1^(1.1 * 2.2)",1.25941916576299080582), + test_t("2.2^(1.1 * 3.3)",17.49823848953534759743), + test_t("3.3^(1.1 * 2.2)",17.98058156638874965269), + test_t("1.1^-2.2/1.1",0.73712884727743375853), + test_t("1.1^+2.2/1.1",1.121169364140602282717273261774), + test_t("1.1^2.2/+1.1",1.121169364140602282717273261774), + test_t("1.1^+2.2/+1.1",1.121169364140602282717273261774), + test_t("1.1^+2.2/-1.1",-1.121169364140602282717273261774), + test_t("1.1^2.2/-1.1",-1.121169364140602282717273261774), + test_t("1.1^+2.2/-1.1",-1.121169364140602282717273261774), + test_t("+1.1^-2.2/1.1",0.73712884727743375853), + test_t("+1.1^+2.2/1.1",1.121169364140602282717273261774), + test_t("+1.1^2.2/+1.1",1.121169364140602282717273261774), + test_t("+1.1^+2.2/+1.1",1.121169364140602282717273261774), + test_t("+1.1^+2.2/-1.1",-1.121169364140602282717273261774), + test_t("+1.1^2.2/-1.1",-1.121169364140602282717273261774), + test_t("+1.1^+2.2/-1.1",-1.121169364140602282717273261774), + test_t("equal(1.23^3,(1.23 * 1.23 * 1.23))",1.0), + test_t("equal(1.23^-3,1/(1.23 * 1.23 * 1.23))",1.0), + test_t("equal((2.1 + 1.23^3),(2.1 + [1.23 * 1.23 * 1.23]))",1.0), + test_t("equal((2.1 - 1.23^3),(2.1 - [1.23 * 1.23 * 1.23]))",1.0), + test_t("equal((2.1 * 1.23^3),(2.1 * [1.23 * 1.23 * 1.23]))",1.0), + test_t("equal((2.1 / 1.23^3),(2.1 / [1.23 * 1.23 * 1.23]))",1.0), + test_t("equal((1.23^3 + 2.1),({1.23 * 1.23 * 1.23} + 2.1))",1.0), + test_t("equal((1.23^3 - 2.1),({1.23 * 1.23 * 1.23} - 2.1))",1.0), + test_t("equal((1.23^3 * 2.1),({1.23 * 1.23 * 1.23} * 2.1))",1.0), + test_t("equal((1.23^3 / 2.1),({1.23 * 1.23 * 1.23} / 2.1))",1.0), + test_t("equal(1.0^(1.0/2.0),sqrt(1.0))",1.0), + test_t("equal(1.0^(1.0/2.0),root(1.0,2.0))",1.0), + test_t("equal(1.0^(1.0/3.0),root(1.0,3.0))",1.0), + test_t("equal(1.0^(1.0/4.0),root(1.0,4.0))",1.0), + test_t("equal(1.0^(1.0/5.0),root(1.0,5.0))",1.0), + test_t("equal(1.0^(1.0/6.0),root(1.0,6.0))",1.0), + test_t("equal(1.0^(1.0/7.0),root(1.0,7.0))",1.0), + test_t("equal(1.0^(1.0/8.0),root(1.0,8.0))",1.0), + test_t("equal(1.0^(1.0/9.0),root(1.0,9.0))",1.0), + test_t("equal(2.0^(1.0/2.0),sqrt(2.0))",1.0), + test_t("equal(2.0^(1.0/2.0),root(2.0,2.0))",1.0), + test_t("equal(3.0^(1.0/3.0),root(3.0,3.0))",1.0), + test_t("equal(4.0^(1.0/4.0),root(4.0,4.0))",1.0), + test_t("equal(5.0^(1.0/5.0),root(5.0,5.0))",1.0), + test_t("equal(6.0^(1.0/6.0),root(6.0,6.0))",1.0), + test_t("equal(7.0^(1.0/7.0),root(7.0,7.0))",1.0), + test_t("equal(8.0^(1.0/8.0),root(8.0,8.0))",1.0), + test_t("equal(9.0^(1.0/9.0),root(9.0,9.0))",1.0), + test_t("1 < 2", 1.0), + test_t("1 <= 2", 1.0), + test_t("1.1 <= 2.2", 1.0), + test_t("(1.0 + 0.1) <= (2.0 + 0.2)", 1.0), + test_t("1 > 2", 0.0), + test_t("1 >= 2", 0.0), + test_t("1.1 >= 2.2", 0.0), + test_t("(1.0 + 0.1) >= (2.0 + 0.2)", 0.0), + test_t("1 <> 2", 1.0), + test_t("1 != 2", 1.0), + test_t("1.1 <> 2.2", 1.0), + test_t("1.1 != 2.2", 1.0), + test_t("(1.0 + 0.1) <> (2.0 + 0.2)", 1.0), + test_t("(1.0 + 0.1) != (2.0 + 0.2)", 1.0), + test_t("1 == 1", 1.0), + test_t("1.1 == 1.1", 1.0), + test_t("1 = 1", 1.0), + test_t("1.1 = 1.1", 1.0), + test_t("1 <> 1", 0.0), + test_t("1 != 1", 0.0), + test_t("1.1 <> 1.1", 0.0), + test_t("1.1 != 1.1", 0.0), + test_t("(1.0 + 0.1) <> (1.0 + 0.1)", 0.0), + test_t("(1.0 + 0.1) != (1.0 + 0.1)", 0.0), + test_t("equal(1.1,1.1)",1.0), + test_t("equal(1.1,2.2)",0.0), + test_t("not_equal(1.1,1.1)",0.0), + test_t("not_equal(1.1,2.2)",1.0), + test_t("1 and 1",1.0), + test_t("1 and 0",0.0), + test_t("0 and 1",0.0), + test_t("0 and 0",0.0), + test_t("1.0 and 1.0",1.0), + test_t("1.0 and 0.0",0.0), + test_t("0.0 and 1.0",0.0), + test_t("0.0 and 0.0",0.0), + test_t("(1 and 1)",1.0), + test_t("(1 and 0)",0.0), + test_t("(0 and 1)",0.0), + test_t("(0 and 0)",0.0), + test_t("(1.0 and 1.0)",1.0), + test_t("(1.0 and 0.0)",0.0), + test_t("(0.0 and 1.0)",0.0), + test_t("(0.0 and 0.0)",0.0), + test_t("1 or 1",1.0), + test_t("1 or 0",1.0), + test_t("0 or 1",1.0), + test_t("0 or 0",0.0), + test_t("1.0 or 1.0",1.0), + test_t("1.0 or 0.0",1.0), + test_t("0.0 or 1.0",1.0), + test_t("0.0 or 0.0",0.0), + test_t("(1 or 1)",1.0), + test_t("(1 or 0)",1.0), + test_t("(0 or 1)",1.0), + test_t("(0 or 0)",0.0), + test_t("(1.0 or 1.0)",1.0), + test_t("(1.0 or 0.0)",1.0), + test_t("(0.0 or 1.0)",1.0), + test_t("(0.0 or 0.0)",0.0), + test_t("1 nand 1",0.0), + test_t("1 nand 0",1.0), + test_t("0 nand 1",1.0), + test_t("0 nand 0",1.0), + test_t("1.0 nand 1.0",0.0), + test_t("1.0 nand 0.0",1.0), + test_t("0.0 nand 1.0",1.0), + test_t("0.0 nand 0.0",1.0), + test_t("(1 nand 1)",0.0), + test_t("(1 nand 0)",1.0), + test_t("(0 nand 1)",1.0), + test_t("(0 nand 0)",1.0), + test_t("(1.0 nand 1.0)",0.0), + test_t("(1.0 nand 0.0)",1.0), + test_t("(0.0 nand 1.0)",1.0), + test_t("(0.0 nand 0.0)",1.0), + test_t("1 nor 1",0.0), + test_t("1 nor 0",0.0), + test_t("0 nor 1",0.0), + test_t("0 nor 0",1.0), + test_t("1.0 nor 1.0",0.0), + test_t("1.0 nor 0.0",0.0), + test_t("0.0 nor 1.0",0.0), + test_t("0.0 nor 0.0",1.0), + test_t("(1 nor 1)",0.0), + test_t("(1 nor 0)",0.0), + test_t("(0 nor 1)",0.0), + test_t("(0 nor 0)",1.0), + test_t("(1.0 nor 1.0)",0.0), + test_t("(1.0 nor 0.0)",0.0), + test_t("(0.0 nor 1.0)",0.0), + test_t("(0.0 nor 0.0)",1.0), + test_t("0 xor 0",0.0), + test_t("0 xor 1",1.0), + test_t("1 xor 0",1.0), + test_t("1 xor 1",0.0), + test_t("0.0 xor 0.0",0.0), + test_t("0.0 xor 1.0",1.0), + test_t("1.0 xor 0.0",1.0), + test_t("1.0 xor 1.0",0.0), + test_t("(0 xor 0)",0.0), + test_t("(0 xor 1)",1.0), + test_t("(1 xor 0)",1.0), + test_t("(1 xor 1)",0.0), + test_t("(0.0 xor 0.0)",0.0), + test_t("(0.0 xor 1.0)",1.0), + test_t("(1.0 xor 0.0)",1.0), + test_t("(1.0 xor 1.0)",0.0), + test_t("1 & 1",1.0), + test_t("1 & 0",0.0), + test_t("0 & 1",0.0), + test_t("0 & 0",0.0), + test_t("1.0 & 1.0",1.0), + test_t("1.0 & 0.0",0.0), + test_t("0.0 & 1.0",0.0), + test_t("0.0 & 0.0",0.0), + test_t("(1 & 1)",1.0), + test_t("(1 & 0)",0.0), + test_t("(0 & 1)",0.0), + test_t("(0 & 0)",0.0), + test_t("(1.0 & 1.0)",1.0), + test_t("(1.0 & 0.0)",0.0), + test_t("(0.0 & 1.0)",0.0), + test_t("(0.0 & 0.0)",0.0), + test_t("1 | 1",1.0), + test_t("1 | 0",1.0), + test_t("0 | 1",1.0), + test_t("0 | 0",0.0), + test_t("1.0 | 1.0",1.0), + test_t("1.0 | 0.0",1.0), + test_t("0.0 | 1.0",1.0), + test_t("0.0 | 0.0",0.0), + test_t("(1 | 1)",1.0), + test_t("(1 | 0)",1.0), + test_t("(0 | 1)",1.0), + test_t("(0 | 0)",0.0), + test_t("(1.0 | 1.0)",1.0), + test_t("(1.0 | 0.0)",1.0), + test_t("(0.0 | 1.0)",1.0), + test_t("(0.0 | 0.0)",0.0), + test_t("(1 nand 1) == not(1 and 1)",1.0), + test_t("(1 nand 0) == not(1 and 0)",1.0), + test_t("(0 nand 1) == not(0 and 1)",1.0), + test_t("(0 nand 0) == not(0 and 0)",1.0), + test_t("(1 nor 1) == not(1 or 1)",1.0), + test_t("(1 nor 0) == not(1 or 0)",1.0), + test_t("(0 nor 1) == not(0 or 1)",1.0), + test_t("(0 nor 0) == not(0 or 0)",1.0), + test_t("(1.0 nand 1.0) == not(1.0 and 1.0)",1.0), + test_t("(1.0 nand 0.0) == not(1.0 and 0.0)",1.0), + test_t("(0.0 nand 1.0) == not(0.0 and 1.0)",1.0), + test_t("(0.0 nand 0.0) == not(0.0 and 0.0)",1.0), + test_t("(1.0 nor 1.0) == not(1.0 or 1.0)",1.0), + test_t("(1.0 nor 0.0) == not(1.0 or 0.0)",1.0), + test_t("(0.0 nor 1.0) == not(0.0 or 1.0)",1.0), + test_t("(0.0 nor 0.0) == not(0.0 or 0.0)",1.0), + test_t("(1 nand 1) == not(1 & 1)",1.0), + test_t("(1 nand 0) == not(1 & 0)",1.0), + test_t("(0 nand 1) == not(0 & 1)",1.0), + test_t("(0 nand 0) == not(0 & 0)",1.0), + test_t("(1 nor 1) == not(1 | 1)",1.0), + test_t("(1 nor 0) == not(1 | 0)",1.0), + test_t("(0 nor 1) == not(0 | 1)",1.0), + test_t("(0 nor 0) == not(0 | 0)",1.0), + test_t("(1.0 nand 1.0) == not(1.0 & 1.0)",1.0), + test_t("(1.0 nand 0.0) == not(1.0 & 0.0)",1.0), + test_t("(0.0 nand 1.0) == not(0.0 & 1.0)",1.0), + test_t("(0.0 nand 0.0) == not(0.0 & 0.0)",1.0), + test_t("(1.0 nor 1.0) == not(1.0 | 1.0)",1.0), + test_t("(1.0 nor 0.0) == not(1.0 | 0.0)",1.0), + test_t("(0.0 nor 1.0) == not(0.0 | 1.0)",1.0), + test_t("(0.0 nor 0.0) == not(0.0 | 0.0)",1.0), + test_t("mand(1,1)",1.0), + test_t("mand(1,0)",0.0), + test_t("mand(0,1)",0.0), + test_t("mand(0,0)",0.0), + test_t("mand(1.0,1.0)",1.0), + test_t("mand(1.0,0.0)",0.0), + test_t("mand(0.0,1.0)",0.0), + test_t("mand(0.0,0.0)",0.0), + test_t("mor(1,1)",1.0), + test_t("mor(1,0)",1.0), + test_t("mor(0,1)",1.0), + test_t("mor(0,0)",0.0), + test_t("mor(1.0,1.0)",1.0), + test_t("mor(1.0,0.0)",1.0), + test_t("mor(0.0,1.0)",1.0), + test_t("mor(0.0,0.0)",0.0), + test_t("(1 nand 1) == not(mand(1,1))",1.0), + test_t("(1 nand 0) == not(mand(1,0))",1.0), + test_t("(0 nand 1) == not(mand(0,1))",1.0), + test_t("(0 nand 0) == not(mand(0,0))",1.0), + test_t("(1 nor 1) == not(mor(1,1))",1.0), + test_t("(1 nor 0) == not(mor(1,0))",1.0), + test_t("(0 nor 1) == not(mor(0,1))",1.0), + test_t("(0 nor 0) == not(mor(0,0))",1.0), + test_t("(1.0 nand 1.0) == not(mand(1.0,1.0))",1.0), + test_t("(1.0 nand 0.0) == not(mand(1.0,0.0))",1.0), + test_t("(0.0 nand 1.0) == not(mand(0.0,1.0))",1.0), + test_t("(0.0 nand 0.0) == not(mand(0.0,0.0))",1.0), + test_t("(1.0 nor 1.0) == not(mor(1.0,1.0))",1.0), + test_t("(1.0 nor 0.0) == not(mor(1.0,0.0))",1.0), + test_t("(0.0 nor 1.0) == not(mor(0.0,1.0))",1.0), + test_t("(0.0 nor 0.0) == not(mor(0.0,0.0))",1.0), + test_t("abs(1)",1.0), + test_t("abs(-1)",1.0), + test_t("abs(1.0)",1.0), + test_t("abs(-1.0)",1.0), + test_t("min(1,2)",1.0), + test_t("min(1,2,3)",1.0), + test_t("min(1,2,3,4)",1.0), + test_t("min(1,2,3,4,5)",1.0), + test_t("min(1,2,3,4,5,6)",1.0), + test_t("min(1.1,2.2)",1.1), + test_t("min(1.1,2.2,3.3)",1.1), + test_t("min(1.1,2.2,3.3,4.4)",1.1), + test_t("min(1.1,2.2,3.3,4.4,5.5)",1.1), + test_t("min(1.1,2.2,3.3,4.4,5.5,6.6)",1.1), + test_t("min(min(1,2),min(3,4))",1.0), + test_t("max(1,2)",2.0), + test_t("max(1,2,3)",3.0), + test_t("max(1,2,3,4)",4.0), + test_t("max(1,2,3,4,5)",5.0), + test_t("max(1,2,3,4,5,6)",6.0), + test_t("max(1.1,2.2)",2.2), + test_t("max(1.1,2.2,3.3)",3.3), + test_t("max(1.1,2.2,3.3,4.4)",4.4), + test_t("max(1.1,2.2,3.3,4.4,5.5)",5.5), + test_t("max(1.1,2.2,3.3,4.4,5.5,6.6)",6.6), + test_t("max(max(1,2),max(3,4))",4.0), + test_t("avg(1,2)",1.5), + test_t("avg(1,2,3)",2.0), + test_t("avg(1,2,3,4)",2.5), + test_t("avg(1,2,3,4,5)",3.0), + test_t("avg(1.1,2.2)",1.65), + test_t("avg(1.1,2.2,3.3)",2.2), + test_t("avg(1.1,2.2,3.3,4.4)",2.75), + test_t("avg(1.1,2.2,3.3,4.4,5.5)",3.3), + test_t("avg(1.1,2.2,3.3,4.4,5.5,6.6)",3.85), + test_t("sum(1,2)",3.0), + test_t("sum(1,2,3)",6.0), + test_t("sum(1,2,3,4)",10), + test_t("sum(1,2,3,4,5)",15.0), + test_t("sum(1,2,3,4,5,6)",21), + test_t("sum(1.1,2.2)",3.3), + test_t("sum(1.1,2.2,3.3)",6.6), + test_t("sum(1.1,2.2,3.3,4.4)",11.0), + test_t("sum(1.1,2.2,3.3,4.4,5.5)",16.5), + test_t("sum(1.1,2.2,3.3,4.4,5.5,6.6)",23.1), + test_t("mul(1,2)",2.0), + test_t("mul(1,2,3)",6.0), + test_t("mul(1,2,3,4)",24.0), + test_t("mul(1,2,3,4,5)",120.0), + test_t("mul(1,2,3,4,5,6)",720.0), + test_t("mul(1.1,2.2)",2.42), + test_t("mul(1.1,2.2,3.3)",7.986), + test_t("mul(1.1,2.2,3.3,4.4)",35.1384), + test_t("mul(1.1,2.2,3.3,4.4,5.5)",193.2612), + test_t("mul(1.1,2.2,3.3,4.4,5.5,6.6)",1275.52392), + test_t("equal(sum(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),(1.1+2.2+3.3+4.4+5.5+6.6+7.7+8.8+9.9))",1.0), + test_t("equal(mul(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),(1.1*2.2*3.3*4.4*5.5*6.6*7.7*8.8*9.9))",1.0), + test_t("equal(min(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),1.1)",1.0), + test_t("equal(max(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),9.9)",1.0), + test_t("equal(avg(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9),5.5)",1.0), + test_t("floor(1.0)",1.0), + test_t("floor(1.1)",1.0), + test_t("floor(-1.0)",-1.0), + test_t("floor(-1.1)",-2.0), + test_t("ceil(1.0)",1.0), + test_t("ceil(1.1)",2.0), + test_t("ceil(-1.0)",-1.0), + test_t("ceil(-1.1)",-1.0), + test_t("round(1.1)",1.0), + test_t("round(1.49)",1.0), + test_t("round(1.5)",2.0), + test_t("round(1.9)",2.0), + test_t("roundn(1/3,2)",0.33), + test_t("roundn(1/3,5)",0.33333), + test_t("roundn(2/3,2)",0.67), + test_t("roundn(2/3,5)",0.66667), + test_t("roundn(1.0/3.0,2.0)",0.33), + test_t("roundn(1.0/3.0,5.0)",0.33333), + test_t("roundn(2.0/3.0,2.0)",0.67), + test_t("roundn(2.0/3.0,5.0)",0.66667), + test_t("cos(0.0)",1.0), + test_t("sin(0.0)",0.0), + test_t("equal(sin(pi/4.0),cos(pi/4.0))",1.0), + test_t("equal(sin(pi/6.0),cos(pi/3.0))",1.0), + test_t("(sin(pi/4.0) - cos(pi/4.0)) <= epsilon",1.0), + test_t("(cos(pi/3.0) - sin(pi/6.0)) <= epsilon",1.0), + test_t("sin(deg2rad(30))",0.5), + test_t("cos(deg2rad(60))",0.5), + test_t("sin(deg2rad(30)) + cos(deg2rad(60))",1.0), + test_t("equal(sin(deg2rad(30))/cos(deg2rad(30)),tan(deg2rad(30)))",1.0), + test_t("equal(sinh(pi),11.5487393572577483779773343153884) ",1.0), + test_t("equal(asinh(11.5487393572577483779773343153884),pi)",1.0), + test_t("equal(cosh(pi),11.5919532755215206277517520525601) ",1.0), + test_t("equal(acosh(11.5919532755215206277517520525601),pi)",1.0), + test_t("equal(tanh(pi),0.99627207622074994426469058001253) ",1.0), + test_t("equal(atanh(0.99627207622074994426469058001253),pi)",1.0), + test_t("exp(1.0)",2.71828182845904523536028747135266249775724), + test_t("exp(0.0)",1.0), + test_t("log(2.7182818284590451)",1.0), + test_t("log10(10.0)",1.0), + test_t("frac(12.34) + trunc(12.34)",12.34), + test_t("hypot(3.0,4.0)",5.0), + test_t("hypot(1.0,sqrt(3.0))",2.0), + test_t("if(1 < 2, 3, 4)",3.0), + test_t("if(1.1 < 2.2, 3.3, 4.4)",3.3), + test_t("if((1.0+1.1) < (2.0+1.2), 3.3, 4.4)",3.3), + test_t("if(1 = 2, 3, 4)",4.0), + test_t("if(1.1 = 2.2, 3.3, 4.4)",4.4), + test_t("if((1.0+1.1) = (2.0+1.2), 3.3, 4.4)",4.4), + test_t("if(1 == 2, 3, 4)",4.0), + test_t("if(1.1 == 2.2, 3.3, 4.4)",4.4), + test_t("if((1.0+1.1) == (2.0+1.2), 3.3, 4.4)",4.4), + test_t("if(1 >= 2, 3, 4)",4.0), + test_t("if(1.1 >= 2.2, 3.3, 4.4)",4.4), + test_t("if((1.0+1.1) >= (2.0+1.2), 3.3, 4.4)",4.4), + test_t("if(((1.0 + 2.0) == 3.0) and ((4.0 + 5.0) < 9.0),1,2)",2.0), + test_t("(3.0 - 1.0 - 2.0) == ((3.0 - 1.0) - 2.0)",1.0), + test_t("true == true",1.0), + test_t("false == false",1.0), + test_t("true != false",1.0), + test_t("false != true",1.0), + test_t("(1 < 2) == true",1.0), + test_t("(1 > 2) == false",1.0), + test_t("true == (1 < 2)",1.0), + test_t("false == (1 > 2)",1.0), + test_t("(1 > 2) != true",1.0), + test_t("(1 < 2) != false",1.0), + test_t("true != (1 > 2)",1.0), + test_t("false != (1 < 2)",1.0), + test_t("(true and true) == true",1.0), + test_t("(false and false) == false",1.0), + test_t("(true or true) == true",1.0), + test_t("(false or false) == false",1.0), + test_t("(true and false) == false",1.0), + test_t("(false and true) == false",1.0), + test_t("(true or false) == true",1.0), + test_t("(false or true) == true",1.0), + test_t("(true & true) == true",1.0), + test_t("(false & false) == false",1.0), + test_t("(true | true) == true",1.0), + test_t("(false | false) == false",1.0), + test_t("(true & false) == false",1.0), + test_t("(false & true) == false",1.0), + test_t("(true | false) == true",1.0), + test_t("(false | true) == true",1.0), + test_t("clamp(-1,1,+1)",1.0), + test_t("clamp(-1,-1.5,+1.0)",-1.0), + test_t("clamp(-1,+1.5,+1.0)",+1.0), + test_t("clamp(-1,-1.5,+1.0) + clamp(-1,+1.5,+1.0)",0.0), + test_t("inrange(-2,1,+2) == ((-2 <= 1) and (1 <= +2))",1.0), + test_t("inrange(-2,1,+2) == if(({-2 <= 1} and [1 <= +2]),1.0,0.0)",1.0), + test_t("sgn( 0)", 0.0), + test_t("sgn(+3)",+1.0), + test_t("sgn(-3)",-1.0), + test_t("equal($f00(1.1,2.2,3.3),(1.1+2.2)/3.3)",1.0), + test_t("equal($f01(1.1,2.2,3.3),(1.1+2.2)*3.3)",1.0), + test_t("equal($f02(1.1,2.2,3.3),(1.1+2.2)-3.3)",1.0), + test_t("equal($f03(1.1,2.2,3.3),(1.1+2.2)+3.3)",1.0), + test_t("equal($f04(1.1,2.2,3.3),(1.1-2.2)+3.3)",1.0), + test_t("equal($f05(1.1,2.2,3.3),(1.1-2.2)/3.3)",1.0), + test_t("equal($f06(1.1,2.2,3.3),(1.1-2.2)*3.3)",1.0), + test_t("equal($f07(1.1,2.2,3.3),(1.1*2.2)+3.3)",1.0), + test_t("equal($f08(1.1,2.2,3.3),(1.1*2.2)-3.3)",1.0), + test_t("equal($f09(1.1,2.2,3.3),(1.1*2.2)/3.3)",1.0), + test_t("equal($f10(1.1,2.2,3.3),(1.1*2.2)*3.3)",1.0), + test_t("equal($f11(1.1,2.2,3.3),(1.1/2.2)+3.3)",1.0), + test_t("equal($f12(1.1,2.2,3.3),(1.1/2.2)-3.3)",1.0), + test_t("equal($f13(1.1,2.2,3.3),(1.1/2.2)/3.3)",1.0), + test_t("equal($f14(1.1,2.2,3.3),(1.1/2.2)*3.3)",1.0), + test_t("equal($f15(1.1,2.2,3.3),1.1/(2.2+3.3))",1.0), + test_t("equal($f16(1.1,2.2,3.3),1.1/(2.2-3.3))",1.0), + test_t("equal($f17(1.1,2.2,3.3),1.1/(2.2*3.3))",1.0), + test_t("equal($f18(1.1,2.2,3.3),1.1/(2.2/3.3))",1.0), + test_t("equal($f19(1.1,2.2,3.3),1.1*(2.2+3.3))",1.0), + test_t("equal($f20(1.1,2.2,3.3),1.1*(2.2-3.3))",1.0), + test_t("equal($f21(1.1,2.2,3.3),1.1*(2.2*3.3))",1.0), + test_t("equal($f22(1.1,2.2,3.3),1.1*(2.2/3.3))",1.0), + test_t("equal($f23(1.1,2.2,3.3),1.1-(2.2+3.3))",1.0), + test_t("equal($f24(1.1,2.2,3.3),1.1-(2.2-3.3))",1.0), + test_t("equal($f25(1.1,2.2,3.3),1.1-(2.2/3.3))",1.0), + test_t("equal($f26(1.1,2.2,3.3),1.1-(2.2*3.3))",1.0), + test_t("equal($f27(1.1,2.2,3.3),1.1+(2.2*3.3))",1.0), + test_t("equal($f28(1.1,2.2,3.3),1.1+(2.2/3.3))",1.0), + test_t("equal($f29(1.1,2.2,3.3),1.1+(2.2+3.3))",1.0), + test_t("equal($f30(1.1,2.2,3.3),1.1+(2.2-3.3))",1.0), + test_t("equal($f31(1.1,2.2,3.3),1.1*2.2^2+3.3)",1.0), + test_t("equal($f32(1.1,2.2,3.3),1.1*2.2^3+3.3)",1.0), + test_t("equal($f33(1.1,2.2,3.3),1.1*2.2^4+3.3)",1.0), + test_t("equal($f34(1.1,2.2,3.3),1.1*2.2^5+3.3)",1.0), + test_t("equal($f35(1.1,2.2,3.3),1.1*2.2^6+3.3)",1.0), + test_t("equal($f36(1.1,2.2,3.3),1.1*2.2^7+3.3)",1.0), + test_t("equal($f37(1.1,2.2,3.3),1.1*2.2^8+3.3)",1.0), + test_t("equal($f38(1.1,2.2,3.3),1.1*2.2^9+3.3)",1.0), + test_t("equal($f39(1.1,2.2,3.3),1.1*log(2.2)+3.3)",1.0), + test_t("equal($f40(1.1,2.2,3.3),1.1*log(2.2)-3.3)",1.0), + test_t("equal($f41(1.1,2.2,3.3),1.1*log10(2.2)+3.3)",1.0), + test_t("equal($f42(1.1,2.2,3.3),1.1*log10(2.2)-3.3)",1.0), + test_t("equal($f43(1.1,2.2,3.3),1.1*sin(2.2)+3.3)",1.0), + test_t("equal($f44(1.1,2.2,3.3),1.1*sin(2.2)-3.3)",1.0), + test_t("equal($f45(1.1,2.2,3.3),1.1*cos(2.2)+3.3)",1.0), + test_t("equal($f46(1.1,2.2,3.3),1.1*cos(2.2)-3.3)",1.0), + test_t("equal($f47(1.1,2.2,3.3),if(0!=1.1,2.2,3.3))",1.0), + test_t("equal($f48(1.1,2.2,3.3,4.4),1.1+((2.2+3.3)/4.4))",1.0), + test_t("equal($f49(1.1,2.2,3.3,4.4),1.1+((2.2+3.3)*4.4))",1.0), + test_t("equal($f50(1.1,2.2,3.3,4.4),1.1+((2.2-3.3)/4.4))",1.0), + test_t("equal($f51(1.1,2.2,3.3,4.4),1.1+((2.2-3.3)*4.4))",1.0), + test_t("equal($f52(1.1,2.2,3.3,4.4),1.1+((2.2*3.3)/4.4))",1.0), + test_t("equal($f53(1.1,2.2,3.3,4.4),1.1+((2.2*3.3)*4.4))",1.0), + test_t("equal($f54(1.1,2.2,3.3,4.4),1.1+((2.2/3.3)+4.4))",1.0), + test_t("equal($f55(1.1,2.2,3.3,4.4),1.1+((2.2/3.3)/4.4))",1.0), + test_t("equal($f56(1.1,2.2,3.3,4.4),1.1+((2.2/3.3)*4.4))",1.0), + test_t("equal($f57(1.1,2.2,3.3,4.4),1.1-((2.2+3.3)/4.4))",1.0), + test_t("equal($f58(1.1,2.2,3.3,4.4),1.1-((2.2+3.3)*4.4))",1.0), + test_t("equal($f59(1.1,2.2,3.3,4.4),1.1-((2.2-3.3)/4.4))",1.0), + test_t("equal($f60(1.1,2.2,3.3,4.4),1.1-((2.2-3.3)*4.4))",1.0), + test_t("equal($f61(1.1,2.2,3.3,4.4),1.1-((2.2*3.3)/4.4))",1.0), + test_t("equal($f62(1.1,2.2,3.3,4.4),1.1-((2.2*3.3)*4.4))",1.0), + test_t("equal($f63(1.1,2.2,3.3,4.4),1.1-((2.2/3.3)/4.4))",1.0), + test_t("equal($f64(1.1,2.2,3.3,4.4),1.1-((2.2/3.3)*4.4))",1.0), + test_t("equal($f65(1.1,2.2,3.3,4.4),((1.1+2.2)*3.3)-4.4)",1.0), + test_t("equal($f66(1.1,2.2,3.3,4.4),((1.1-2.2)*3.3)-4.4)",1.0), + test_t("equal($f67(1.1,2.2,3.3,4.4),((1.1*2.2)*3.3)-4.4)",1.0), + test_t("equal($f68(1.1,2.2,3.3,4.4),((1.1/2.2)*3.3)-4.4)",1.0), + test_t("equal($f69(1.1,2.2,3.3,4.4),((1.1+2.2)/3.3)-4.4)",1.0), + test_t("equal($f70(1.1,2.2,3.3,4.4),((1.1-2.2)/3.3)-4.4)",1.0), + test_t("equal($f71(1.1,2.2,3.3,4.4),((1.1*2.2)/3.3)-4.4)",1.0), + test_t("equal($f72(1.1,2.2,3.3,4.4),((1.1/2.2)/3.3)-4.4)",1.0), + test_t("equal($f73(1.1,2.2,3.3,4.4),(1.1*2.2)+(3.3*4.4))",1.0), + test_t("equal($f74(1.1,2.2,3.3,4.4),(1.1*2.2)-(3.3*4.4))",1.0), + test_t("equal($f75(1.1,2.2,3.3,4.4),(1.1*2.2)+(3.3/4.4))",1.0), + test_t("equal($f76(1.1,2.2,3.3,4.4),(1.1*2.2)-(3.3/4.4))",1.0), + test_t("equal($f77(1.1,2.2,3.3,4.4),(1.1/2.2)+(3.3/4.4))",1.0), + test_t("equal($f78(1.1,2.2,3.3,4.4),(1.1/2.2)-(3.3/4.4))",1.0), + test_t("equal($f79(1.1,2.2,3.3,4.4),(1.1/2.2)-(3.3*4.4))",1.0), + test_t("equal($f80(1.1,2.2,3.3,4.4),1.1/(2.2+(3.3*4.4)))",1.0), + test_t("equal($f81(1.1,2.2,3.3,4.4),1.1/(2.2-(3.3*4.4)))",1.0), + test_t("equal($f82(1.1,2.2,3.3,4.4),1.1*(2.2+(3.3*4.4)))",1.0), + test_t("equal($f83(1.1,2.2,3.3,4.4),1.1*(2.2-(3.3*4.4)))",1.0), + test_t("equal($f84(1.1,2.2,3.3,4.4),1.1*2.2^2+3.3*4.4^2)",1.0), + test_t("equal($f85(1.1,2.2,3.3,4.4),1.1*2.2^3+3.3*4.4^3)",1.0), + test_t("equal($f86(1.1,2.2,3.3,4.4),1.1*2.2^4+3.3*4.4^4)",1.0), + test_t("equal($f87(1.1,2.2,3.3,4.4),1.1*2.2^5+3.3*4.4^5)",1.0), + test_t("equal($f88(1.1,2.2,3.3,4.4),1.1*2.2^6+3.3*4.4^6)",1.0), + test_t("equal($f89(1.1,2.2,3.3,4.4),1.1*2.2^7+3.3*4.4^7)",1.0), + test_t("equal($f90(1.1,2.2,3.3,4.4),1.1*2.2^8+3.3*4.4^8)",1.0), + test_t("equal($f91(1.1,2.2,3.3,4.4),1.1*2.2^9+3.3*4.4^9)",1.0), + test_t("equal($f92(1.1,2.2,3.3,4.4),if(1.1 and 2.2,3.3,4.4))",1.0), + test_t("equal($f93(1.1,2.2,3.3,4.4),if(1.1 or 2.2,3.3,4.4))",1.0), + test_t("equal($f94(1.1,2.2,3.3,4.4),if(1.1 < 2.2,3.3,4.4))",1.0), + test_t("equal($f95(1.1,2.2,3.3,4.4),if(1.1 <= 2.2,3.3,4.4))",1.0), + test_t("equal($f96(1.1,2.2,3.3,4.4),if(1.1 > 2.2,3.3,4.4))",1.0), + test_t("equal($f97(1.1,2.2,3.3,4.4),if(1.1 >= 2.2,3.3,4.4))",1.0), + test_t("equal($f98(1.1,2.2,3.3,4.4),if(equal(1.1,2.2),3.3,4.4))",1.0), + test_t("equal($f99(1.1,2.2,3.3,4.4),1.1*sin(2.2)+3.3*cos(4.4))",1.0), + test_t("equal((48.0/2.0*(9.0+3.0)),288.0)",1.0), + test_t("equal((48.0/2.0(9.0+3.0)),288.0)",1.0), + test_t("equal((6.0/2.0(1.0+2.0)),9.0)",1.0), + test_t("1+2+3+4+5+6+7+8+9+0",45.0), + test_t("1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0",45.0), + test_t("1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0 + 8.0 + 9.0 + 0.0",45.0), + test_t("(1+2)+(3+4)+(5+6)+(7+8)+(9+0)",45.0), + test_t("(1-2)+(3-4)+(5-6)+(7-8)+(9-0)",+5.0), + test_t("(1+2)-(3+4)-(5+6)-(7+8)-(9+0)",-39.0), + test_t("(1.0+2.0)+(3.0+4.0)+(5.0+6.0)+(7.0+8.0)+(9.0+0.0)",45.0), + test_t("(1.0-2.0)+(3.0-4.0)+(5.0-6.0)+(7.0-8.0)+(9.0-0.0)",+5.0), + test_t("(1.0+2.0)-(3.0+4.0)-(5.0+6.0)-(7.0+8.0)-(9.0+0.0)",-39.0), + test_t("[(1.0+2.0)+[3.0+4.0]+(5.0+6.0)]+([7.0+8.0]+(9.0+0.0))",45.0), + test_t("([1.0-2.0]+(3.0-4.0)+[5.0-6.0])+[(7.0-8.0)+[9.0-0.0]]",+5.0), + test_t("((1.0+2.0))-[(3.0+4.0)]-((5.0+6.0))-[(7.0+8.0)]-((9.0+0.0))",-39.0), + test_t("{[(1.0+2.0)+[3.0+4.0]+({5.0+6.0})]}+({[7.0+8.0]+(9.0+0.0)})",45.0), + test_t("{([1.0-2.0]+(3.0-4.0)+[5.0-6.0])}+[({+7.0}-{+8.0})+[{+9.0-0.0}]]",+5.0), + test_t("((+1.0+2.0))-[({+3.0+4.0})]-(({+5.0+6.0}))-[({+7.0}+8.0)]-(({+9.0}+{0.0}))",-39.0), + test_t("1+2-3*4/5+6-7*8/9+0",0.37777777777777777778), + test_t("1.1+2.2-3.3*4.4/5.5+6.6-7.7*8.8/9.9+0.0",0.41555555555555555556), + test_t("(1+2)-(3*4)/(5+6)-(7*8)/(9+0)",-4.31313131313131313131), + test_t("1/1+1/2+1/3+1/4+1/5+1/6+1/7+1/8+1/9",2.82896825396825396825), + test_t("(1/1)+(1/2)+(1/3)+(1/4)+(1/5)+(1/6)+(1/7)+(1/8)+(1/9)",2.82896825396825396825), + test_t("1.0/1.0+1.0/2.0+1.0/3.0+1.0/4.0+1.0/5.0+1.0/6.0+1.0/7.0+1.0/8.0+1.0/9",2.82896825396825396825), + test_t("(1.0/1.0)+(1.0/2.0)+(1.0/3.0)+(1.0/4.0)+(1.0/5.0)+(1.0/6.0)+(1.0/7.0)+(1.0/8.0)+(1.0/9)",2.82896825396825396825), + test_t("1/1*1/2*1/3*1/4*1/5*1/6*1/7*1/8*1/9",0.00000275573192239859), + test_t("(1/1)*(1/2)*(1/3)*(1/4)*(1/5)*(1/6)*(1/7)*(1/8)*(1/9)",0.00000275573192239859), + test_t("1.0/1.0*1.0/2.0*1.0/3.0*1.0/4.0*1.0/5.0*1.0/6.0*1.0/7.0*1.0/8.0*1.0/9",0.00000275573192239859), + test_t("(1.0/1.0)*(1.0/2.0)*(1.0/3.0)*(1.0/4.0)*(1.0/5.0)*(1.0/6.0)*(1.0/7.0)*(1.0/8.0)*(1.0/9)",0.00000275573192239859), + test_t("equal(poly01(1.2345,2.2,1.1),(2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly02(1.2345,3.3,2.2,1.1),(3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly03(1.2345,4.4,3.3,2.2,1.1),(4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly04(1.2345,5.5,4.4,3.3,2.2,1.1),(5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly05(1.2345,6.6,5.5,4.4,3.3,2.2,1.1),(6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly06(1.2345,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(7.7*1.2345^6+6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly07(1.2345,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(8.8*1.2345^7+7.7*1.2345^6+6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly08(1.2345,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(9.9*1.2345^8+8.8*1.2345^7+7.7*1.2345^6+6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly09(1.2345,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(1.1*1.2345^9+9.9*1.2345^8+8.8*1.2345^7+7.7*1.2345^6+6.6*1.2345^5+5.5*1.2345^4+4.4*1.2345^3+3.3*1.2345^2+2.2*1.2345^1+1.1))",1.0), + test_t("equal(poly10(1.37,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(2.2*1.37^10+1.1*1.37^9+9.9*1.37^8+8.8*1.37^7+7.7*1.37^6+6.6*1.37^5+5.5*1.37^4+4.4*1.37^3+3.3*1.37^2+2.2*1.37^1+1.1))",1.0), + test_t("equal(poly11(1.37,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(3.3*1.37^11+2.2*1.37^10+1.1*1.37^9+9.9*1.37^8+8.8*1.37^7+7.7*1.37^6+6.6*1.37^5+5.5*1.37^4+4.4*1.37^3+3.3*1.37^2+2.2*1.37^1+1.1))",1.0), + test_t("equal(poly12(1.37,4.4,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(4.4*1.37^12+3.3*1.37^11+2.2*1.37^10+1.1*1.37^9+9.9*1.37^8+8.8*1.37^7+7.7*1.37^6+6.6*1.37^5+5.5*1.37^4+4.4*1.37^3+3.3*1.37^2+2.2*1.37^1+1.1))",1.0), + test_t("equal(\t \n(\n \r1.1\t\t - \n\n 2.2\n\n/\r3.3\t),(1.1-2.2/3.3))",1.0), + test_t("equal((pi^2^3),(pi^8))",1.0), + test_t("equal((pi^(2^3)),(pi^8))",1.0), + test_t("equal(pi^2^3-pi^8,0)",1.0), + test_t("equal((2*pi^2^3),2*(pi^8))",1.0), + test_t("equal((pi^2^3*2),2*(pi^8))",1.0), + test_t("equal((pi^2^3/2),(pi^8)/2)",1.0), + test_t("equal((pi^2.2^3.3),(pi^13.4894687605338489))",1.0), + test_t("equal((pi^(2.2^3.3)),(pi^13.4894687605338489))",1.0), + test_t("equal((2.2*pi^2.2^3.3),2.2*(pi^13.4894687605338489))",1.0), + test_t("equal((pi^2.2^3.3*2),2*(pi^13.4894687605338489))",1.0), + test_t("equal((pi^2.2^3.3/2.2),(pi^13.4894687605338489)/2.2)",1.0), + test_t("equal((pi^-2^3),1/(pi^8))",1.0), + test_t("equal((pi^(-2^3)),1/(pi^8))",1.0), + test_t("equal((pi^2^-3),(pi^(1/8)))",1.0), + test_t("equal((pi^(2^-3)),(pi^(1/8)))",1.0), + test_t("equal((pi^-2^-3),1/(pi^(1/8)))",1.0), + test_t("equal((pi^(-2^-3)),1/(pi^(1/8)))",1.0), + test_t("equal((-pi^2^3),(-pi^8))",1.0), + test_t("equal((-pi^(2^3)),(-pi^8))",1.0), + test_t("equal(-pi^2^3--pi^8,0)",1.0), + test_t("equal((2*-pi^2^3),2*(-pi^8))",1.0), + test_t("equal((-pi^2^3*2),2*(-pi^8))",1.0), + test_t("equal((-pi^2^3/2),(-pi^8)/2)",1.0), + test_t("equal((-pi^2.2^3.3),(-pi^13.4894687605338489))",1.0), + test_t("equal((-pi^(2.2^3.3)),(-pi^13.4894687605338489))",1.0), + test_t("equal((2.2*-pi^2.2^3.3),2.2*(-pi^13.4894687605338489))",1.0), + test_t("equal((-pi^2.2^3.3*2),2*(-pi^13.4894687605338489))",1.0), + test_t("equal((-pi^2.2^3.3/2.2),(-pi^13.4894687605338489)/2.2)",1.0), + test_t("equal((-pi^-2^3),1/(-pi^8))",1.0), + test_t("equal((-pi^(-2^3)),1/(-pi^8))",1.0), + test_t("equal((-pi^2^-3),(-pi^(1/8)))",1.0), + test_t("equal((-pi^(2^-3)),(-pi^(1/8)))",1.0), + test_t("equal((-pi^-2^-3),1/(-pi^(1/8)))",1.0), + test_t("equal((-pi^(-2^-3)),1/(-pi^(1/8)))",1.0), + test_t("equal((+pi^+2^+3),(+pi^+8))",1.0), + test_t("equal((+pi^(2^3)),(+pi^+8))",1.0), + test_t("equal(+pi^+2^+3-+pi^+8,0)",1.0), + test_t("equal((+2*+pi^+2^+3),+2*(+pi^+8))",1.0), + test_t("equal((+pi^+2^+3*+2),+2*(+pi^+8))",1.0), + test_t("equal((+pi^+2^+3/+2),(+pi^+8)/+2)",1.0), + test_t("equal((+pi^+2.2^+3.3),(+pi^+13.4894687605338489))",1.0), + test_t("equal((+pi^(+2.2^+3.3)),(+pi^+13.4894687605338489))",1.0), + test_t("equal((+2.2*+pi^+2.2^+3.3),+2.2*(+pi^+13.4894687605338489))",1.0), + test_t("equal((+pi^+2.2^+3.3*+2),+2*(+pi^+13.4894687605338489))",1.0), + test_t("equal((+pi^+2.2^+3.3/+2.2),(+pi^+13.4894687605338489)/+2.2)",1.0), + test_t("equal((+pi^-2^3),1/(+pi^+8))",1.0), + test_t("equal((+pi^(-2^3)),1/(+pi^+8))",1.0), + test_t("equal((+pi^2^-3),(+pi^(+1/+8)))",1.0), + test_t("equal((+pi^(2^-3)),(+pi^(+1/+8)))",1.0), + test_t("equal((+pi^-2^-3),1/(+pi^(+1/+8)))",1.0), + test_t("equal((+pi^(-2^-3)),1/(+pi^(+1/+8)))",1.0), + test_t("equal((-pi^+2^+3),(-pi^+8))",1.0), + test_t("equal((-pi^(2^3)),(-pi^+8))",1.0), + test_t("equal(-pi^+2^+3--pi^+8,0)",1.0), + test_t("equal((+2*-pi^+2^+3),2*(-pi^+8))",1.0), + test_t("equal((-pi^+2^+3*2),2*(-pi^+8))",1.0), + test_t("equal((-pi^+2^+3/+2),(-pi^+8)/+2)",1.0), + test_t("equal((-pi^+2.2^+3.3),(-pi^+13.4894687605338489))",1.0), + test_t("equal((-pi^(2.2^3.3)),(-pi^+13.4894687605338489))",1.0), + test_t("equal((+2.2*-pi^+2.2^+3.3),2.2*(-pi^+13.4894687605338489))",1.0), + test_t("equal((-pi^+2.2^+3.3*2),2*(-pi^+13.4894687605338489))",1.0), + test_t("equal((-pi^+2.2^+3.3/+2.2),(-pi^+13.4894687605338489)/+2.2)",1.0), + test_t("equal((-pi^-2^3),1/(-pi^+8))",1.0), + test_t("equal((-pi^(-2^3)),1/(-pi^+8))",1.0), + test_t("equal((-pi^2^-3),(-pi^(+1/+8)))",1.0), + test_t("equal((-pi^(2^-3)),(-pi^(+1/+8)))",1.0), + test_t("equal((-pi^-2^-3),1/(-pi^(+1/+8)))",1.0), + test_t("equal((-pi^(-2^-3)),1/(-pi^(+1/+8)))",1.0), + test_t("switch { case (1 <= 2) : 1; default: 1.12345; }",1.0), + test_t("switch { case (1 > 2) : 0; case (1 <= 2) : 1; default: 1.12345; }",1.0), + test_t("switch { case (1 <= 2) : switch { case (1 <= 2) : 1; default: 1.12345; }; default: 1.12345; }",1.0), + test_t("switch { case [1 <= 2] : 1; default: 1.12345; }",1.0), + test_t("switch { case [1 > 2] : 0; case [1 <= 2] : 1; default: 1.12345; }",1.0), + test_t("switch { case [1 <= 2] : switch { case [1 <= 2] : 1; default: 1.12345; }; default: 1.12345; }",1.0), + test_t("switch { case {1 <= 2} : 1; default: 1.12345; }",1.0), + test_t("switch { case {1 > 2} : 0; case {1 <= 2} : 1; default: 1.12345; }",1.0), + test_t("switch { case {1 <= 2} : switch { case {1 <= 2} : 1; default: 1.12345; }; default: 1.12345; }",1.0), + test_t("switch { case [(1 <= 2)] : {1}; default: 1.12345; }",1.0), + test_t("switch { case ([1 > 2]) : [0]; case ([1 <= 2]) : 1; default: 1.12345; }",1.0), + test_t("switch { case {(1 <= 2)} : switch { case ({1 <= 2}) : 1; default: 1.12345; }; default: 1.12345; }",1.0), + test_t("switch { case 1 > 1 : 1; case 2 > 2 : 2; case 3 = 3 : 3; case 4 > 4 : 4; default : 5; }",3.0), + test_t("repeat 1.1 + 2.2 until (1 < 2)",3.3), + test_t("repeat (1.1 + 2.2) until (1 < 2)",3.3), + test_t("repeat 1.1 + 2.2; until (1 < 2)",3.3), + test_t("repeat (1.1 + 2.2); until (1 < 2)",3.3), + test_t("repeat 1.1234; 1 < 2; 1.1 + 2.2 until (1 < 2)",3.3), + test_t("repeat 1.1234; 1 < 2; (1.1 + 2.2) until (1 < 2)",3.3), + test_t("repeat 1.1234; 1 < 2; 1.1 + 2.2; until (1 < 2)",3.3), + test_t("repeat 1.1234; 1 < 2; (1.1 + 2.2); until (1 < 2)",3.3), + test_t("[*] { case 1 < 2 : 1 / 2; case (1 < 3) : 2 / 2; case 1 < 4 : 3 / 2; case (1 < 5) : 4 / 2; }",2.0), + test_t(" 0 ? 1 : 2",2.0), + test_t(" 1 ? 3 : 4",3.0), + test_t("(0 ? 1 : 2) == 2",1.0), + test_t("(1 ? 3 : 4) == 3",1.0), + test_t("[(0)] ? [(1)] : [(2)]",2.0), + test_t("([(0)] ? [(1)] : [(2)]) == 2",1.0), + test_t("([(1)] ? [(3)] : [(4)]) == 3",1.0), + test_t("(1 < 2 ? 3 : 4) == 3",1.0), + test_t("(1 > 2 ? 3 : 4) == 4",1.0), + test_t("(1 < 2 ? 3 + 5 : 4) == 8",1.0), + test_t("(1 > 2 ? 3 : 4 + 5) == 9",1.0), + test_t("(2 < 3 + 3 ? 7 : 9) == 7",1.0), + test_t("(1 + 1 < 3 ? 7 : 9) == 7",1.0), + test_t("(1 + 1 < 3 + 3 ? 7 : 9) == 7",1.0), + test_t("(2 > 3 + 3 ? 7 : 9) == 9",1.0), + test_t("(1 + 1 > 3 ? 7 : 9) == 9",1.0), + test_t("(1 + 1 > 3 + 3 ? 7 : 9) == 9",1.0), + test_t("(2 < (3 + 3) ? 7 : 9) == 7",1.0), + test_t("((1 + 1) < 3 ? 7 : 9) == 7",1.0), + test_t("((1 + 1) < (3 + 3) ? 7 : 9) == 7",1.0), + test_t("(min(1,2) ? 1 + 3 : 1 + 4) == 4",1.0), + test_t("(min(0,1) ? 1 + 3 : 1 + 4) == 5",1.0), + test_t("(if (1 < 2) 3;) == 3",1.0), + test_t("(if (1 > 2) 3;) == null",1.0), + test_t("(if (1 < 2) 3; else 4;) == 3",1.0), + test_t("(if (1 > 2) 3; else 4;) == 4",1.0), + test_t("if (1 < 2) 3; else {1+2; 4;} == 3",1.0), + test_t("if (1 > 2) 3; else {1+2; 4;} == 4",1.0), + test_t("(if (1 < 2) 3; else if (1 < 2) 4;) == 3",1.0), + test_t("(if (1 > 2) 3; else if (1 < 2) 4;) == 4",1.0), + test_t("(if (1 > 2) 3; else if (1 > 2) 4;) == null",1.0), + test_t("if (1 < 2) 3; else if (1 < 2) {1+2; 4;} == 3",1.0), + test_t("if (1 > 2) 3; else if (1 < 2) {1+2; 4;} == 4",1.0), + test_t("if (1 > 2) 3; else if (1 > 2) {1+2; 4;} == null",1.0), + test_t("if (1 < 2) { 1+2; 3;} == 3",1.0), + test_t("if (1 > 2) { 1+2; 3;} == null",1.0), + test_t("(if (1 < 2) { 1+2; 3;} else 4;) == 3",1.0), + test_t("(if (1 > 2) { 1+2; 3;} else 4;) == 4",1.0), + test_t("if (1 < 2) { 1+2; 3;} else {1+2; 4;} == 3",1.0), + test_t("if (1 > 2) { 1+2; 3;} else {1+2; 4;} == 4",1.0), + test_t("(if (1 < 2) { 1+2; 3;} else if (1 < 2) 4;) == 3",1.0), + test_t("(if (1 > 2) { 1+2; 3;} else if (1 < 2) 4;) == 4",1.0), + test_t("(if (1 > 2) { 1+2; 3;} else if (1 > 2) 4;) == null",1.0), + test_t("if (1 < 2) { 1+2; 3;} else if (1 < 2) {1+2; 4;} == 3",1.0), + test_t("if (1 > 2) { 1+2; 3;} else if (1 < 2) {1+2; 4;} == 4",1.0), + test_t("if (1 > 2) { 1+2; 3;} else if (1 > 2) {1+2; 4;} == null",1.0) +}; static const std::size_t global_test_list_size = sizeof(global_test_list) / sizeof(test_t); @@ -1190,7 +1200,7 @@ inline bool test_expression(const std::string& expression_string, const T& expec } } - if (!exprtk::expression_helper::is_constant(expression)) + if (!exprtk::expression_helper::is_literal(expression)) { printf("test_expression() - Error: Expression did not compile to a constant! Expression: %s\n", expression_string.c_str()); @@ -1251,12 +1261,14 @@ struct edge_cases }; template -inline bool run_test00() +bool run_test00() { const std::size_t rounds = 10; + for (std::size_t r = 0; r < rounds; ++r) { bool result = true; + for (std::size_t i = 0; i < global_test_list_size; ++i) { if (!test_expression(global_test_list[i].first,T(global_test_list[i].second))) @@ -1297,10 +1309,10 @@ template struct test_xy { test_xy(const std::string& e, const T& v0, const T& v1, const T& r) - : expr(e), - x(v0), - y(v1), - result(r) + : expr(e) + , x(v0) + , y(v1) + , result(r) {} std::string expr; @@ -1313,12 +1325,12 @@ template struct test_xyzw { test_xyzw(const std::string& e, const T& v0, const T& v1, const T& v2, const T& v3, const T& r) - : expr(e), - x(v0), - y(v1), - z(v2), - w(v3), - result(r) + : expr(e) + , x(v0) + , y(v1) + , z(v2) + , w(v3) + , result(r) {} std::string expr; @@ -1330,448 +1342,448 @@ struct test_xyzw }; template -inline bool run_test01() +bool run_test01() { { static const test_xy test_list[] = - { - test_xy("x + y" ,T(2.2),T(3.3),T(5.5 )), - test_xy("x - y" ,T(3.3),T(2.2),T(1.1 )), - test_xy("x * y" ,T(3.3),T(2.2),T(7.26 )), - test_xy("x / y" ,T(3.3),T(2.2),T(1.5 )), - test_xy("(x + y) * (x + y)" ,T(2.2),T(3.3),T(30.25)), - test_xy("(x + y) / (x + y)" ,T(2.2),T(3.3),T(1.0 )), - test_xy("x + y > x and x + y > y" ,T(2.2),T(3.3),T(1.0)), - test_xy("1 + (x + y)" ,T(2.2),T(3.3),T(6.5 )), - test_xy("(x + y) - 1" ,T(2.2),T(3.3),T(4.5 )), - test_xy("1 + (x + y) * 2" ,T(2.2),T(3.3),T(12.0 )), - test_xy("2 * (x + y) - 1" ,T(2.2),T(3.3),T(10.0 )), - test_xy("y + (x + 1)" ,T(2.2),T(3.3),T(6.5 )), - test_xy("(x + 1) + y" ,T(2.2),T(3.3),T(6.5 )), - test_xy("2 * x" ,T(2.2),T(0.0),T(4.4)), - test_xy("x * 2" ,T(2.2),T(0.0),T(4.4)), - test_xy("1.1 + x" ,T(2.2),T(0.0),T(3.3)), - test_xy("x + 1.1" ,T(2.2),T(0.0),T(3.3)), - test_xy("x - -1 " ,T(1.0),T(0.0),T(2)), - test_xy("x --1 " ,T(1.0),T(0.0),T(2)), - test_xy("x-- 1 " ,T(1.0),T(0.0),T(2)), - test_xy("x--1 " ,T(1.0),T(0.0),T(2)), - test_xy("x -- -1" ,T(1.0),T(0.0),T(0)), - test_xy("x + -1 " ,T(1.0),T(0.0),T(0)), - test_xy("x +-1 " ,T(1.0),T(0.0),T(0)), - test_xy("x+- 1 " ,T(1.0),T(0.0),T(0)), - test_xy("x+-1 " ,T(1.0),T(0.0),T(0)), - test_xy("x +- -1" ,T(1.0),T(0.0),T(2)), - test_xy("x + +1 " ,T(1.0),T(0.0),T(2)), - test_xy("x ++1 " ,T(1.0),T(0.0),T(2)), - test_xy("1 - -x " ,T(1.0),T(0.0),T(2)), - test_xy("1 --x " ,T(1.0),T(0.0),T(2)), - test_xy("1-- x " ,T(1.0),T(0.0),T(2)), - test_xy("1--x " ,T(1.0),T(0.0),T(2)), - test_xy("1 -- -x" ,T(1.0),T(0.0),T(0)), - test_xy("1 + -x " ,T(1.0),T(0.0),T(0)), - test_xy("1 +-x " ,T(1.0),T(0.0),T(0)), - test_xy("1+- x " ,T(1.0),T(0.0),T(0)), - test_xy("1+-x " ,T(1.0),T(0.0),T(0)), - test_xy("1 +- -x" ,T(1.0),T(0.0),T(2)), - test_xy("1 + +x " ,T(1.0),T(0.0),T(2)), - test_xy("1 ++x " ,T(1.0),T(0.0),T(2)), - test_xy("(x - -1 + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(x --1 + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(x-- 1 + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(x--1 + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(x -- -1 + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x + -1 + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x +-1 + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x+- 1 + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x+-1 + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x +- -1 + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(x + +1 + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(x ++1 + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(1 - -x + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(1 --x + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(1-- x + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(1--x + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(1 -- -x + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1 + -x + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1 +-x + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1+- x + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1+-x + 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1 +- -x + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(1 + +x + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(1 ++x + 1)" ,T(1.0),T(0.0),T(3)), - test_xy("(x - -1 - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x --1 - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x-- 1 - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x--1 - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x -- -1 - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(x + -1 - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(x +-1 - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(x+- 1 - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(x+-1 - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(x +- -1 - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x + +1 - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(x ++1 - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1 - -x - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1 --x - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1-- x - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1--x - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1 -- -x - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(1 + -x - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(1 +-x - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(1+- x - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(1+-x - 1)" ,T(1.0),T(0.0),T(-1)), - test_xy("(1 +- -x - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1 + +x - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("(1 ++x - 1)" ,T(1.0),T(0.0),T(1)), - test_xy("x * 1 == x" ,T(2.0),T(3.0),T(1.0)), - test_xy("1 * x == x" ,T(2.0),T(3.0),T(1.0)), - test_xy("y * 1 == y" ,T(2.0),T(3.0),T(1.0)), - test_xy("1 * y == y" ,T(2.0),T(3.0),T(1.0)), - test_xy("x * 0 == 0" ,T(2.0),T(3.0),T(1.0)), - test_xy("0 * x == 0" ,T(2.0),T(3.0),T(1.0)), - test_xy("y * 0 == 0" ,T(2.0),T(3.0),T(1.0)), - test_xy("0 * y == 0" ,T(2.0),T(3.0),T(1.0)), - test_xy("x + 1 == 1 + x" ,T(2.0),T(3.0),T(1.0)), - test_xy("y + 1 == 1 + y" ,T(2.0),T(3.0),T(1.0)), - test_xy("x + y == y + x" ,T(2.0),T(3.0),T(1.0)), - test_xy("x * y == y * x" ,T(2.0),T(3.0),T(1.0)), - test_xy("x < y" ,T(2.0),T(3.0),T(1.0)), - test_xy("y > x" ,T(2.0),T(3.0),T(1.0)), - test_xy("x <= y" ,T(2.0),T(3.0),T(1.0)), - test_xy("y >= x" ,T(2.0),T(3.0),T(1.0)), - test_xy("x + y > y" ,T(2.0),T(3.0),T(1.0)), - test_xy("x + y > x" ,T(2.0),T(3.0),T(1.0)), - test_xy("x * y > y" ,T(2.0),T(3.0),T(1.0)), - test_xy("x * y > x" ,T(2.0),T(3.0),T(1.0)), - test_xy("(x + y) > y" ,T(2.0),T(3.0),T(1.0)), - test_xy("(x + y) > x" ,T(2.0),T(3.0),T(1.0)), - test_xy("(x * y) > y" ,T(2.0),T(3.0),T(1.0)), - test_xy("(x * y) > x" ,T(2.0),T(3.0),T(1.0)), - test_xy("(2x + 3y) == (2*x + 3*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy("2(x + y) == (2*x + 2*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (x + y)3 == (3*x + 3*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy("2x + 3y == 2*x + 3*y" ,T(2.0),T(3.0),T(1.0)), - test_xy("2(x + y) == 2*x + 2*y" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (x + y)3 == 3*x + 3*y" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (x)y == (x*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" x(y) == (x*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (x) y == (x*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" x (y) == (x*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" ((x) y) == (x*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (x (y)) == (x*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (x)3 == (x*3)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" x(3) == (x*3)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (x) 3 == (x*3)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" x (3) == (x*3)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" ((x) 3) == (x*3)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (x (3)) == (x*3)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (2)y == (2*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" 2(y) == (2*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (2) y == (2*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" 2 (y) == (2*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" ((2) y) == (2*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy(" (2 (y)) == (2*y)" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; (a)(3) == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; (A){3} == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; (a)[3] == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; {a}(3) == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; {a}{3} == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; {a}[3] == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; (a)(b) == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; (a){B} == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; (a)[b] == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; {a}(b) == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; {a}{b} == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; {a}[b] == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; (a)(a+1) == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; (a){a+1} == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; (a)[a+1] == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; {a}(a+1) == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; {a}{a+1} == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; {a}[a+1] == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; (b-1)(b) == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; (b-1){b} == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; (b-1)[b] == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; {b-1}(b) == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; {b-1}{b} == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("var a := 2; var b := 3; {b-1}[b] == 6" ,T(2.0),T(3.0),T(1.0)), - test_xy("equal(x^2.2^1.1,17.15193942371376191362)" ,T(3.3),T(0.0),T(1.0)), - test_xy("equal(3.3^x^1.1,17.15193942371376191362)" ,T(2.2),T(0.0),T(1.0)), - test_xy("equal(3.3^2.2^x,17.15193942371376191362)" ,T(1.1),T(0.0),T(1.0)), - test_xy("equal(x^2.2^y,17.15193942371376191362)" ,T(3.3),T(1.1),T(1.0)), - test_xy("equal(x^y^1.1,17.15193942371376191362)" ,T(3.3),T(2.2),T(1.0)), - test_xy("equal(3.3^x^y,17.15193942371376191362)" ,T(2.2),T(1.1),T(1.0)), - test_xy("equal(x+y^3/7,x+(y*y*y)/7)",T(2.0),T(3.0),T(1.0)), - test_xy("equal(1-x^3+y^2*7,1-(x*x*x)+(y*y)*7)",T(2.0),T(3.0),T(1.0)), - test_xy("equal( x^0,1)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^1,x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^2,x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^3,x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^4,x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^5,x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^6,x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^7,x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^8,x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^9,x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^10,x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^11,x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^12,x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^13,x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^14,x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^15,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^16,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^17,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^18,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^19,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^20,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^21,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^22,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^23,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^24,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^25,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( y^0,1)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^1,y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^2,y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^3,y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^4,y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^5,y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^6,y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^7,y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^8,y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^9,y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^10,y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^11,y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^12,y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^13,y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^14,y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^15,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^16,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^17,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^18,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^19,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^20,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^21,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^22,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^23,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^24,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^25,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( x^-0,1/1)",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-1,1/(x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-2,1/(x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-3,1/(x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-4,1/(x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-5,1/(x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-6,1/(x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-7,1/(x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-8,1/(x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( x^-9,1/(x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-10,1/(x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-11,1/(x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-12,1/(x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-13,1/(x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-14,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-15,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-16,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-17,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-18,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-19,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-20,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-21,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-22,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-23,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-24,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal(x^-25,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), - test_xy("equal( y^-0,1/1)",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-1,1/(y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-2,1/(y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-3,1/(y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-4,1/(y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-5,1/(y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-6,1/(y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-7,1/(y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-8,1/(y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal( y^-9,1/(y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-10,1/(y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-11,1/(y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-12,1/(y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-13,1/(y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-14,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-15,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-16,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-17,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-18,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-19,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-20,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-21,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-22,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-23,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-24,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("equal(y^-25,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), - test_xy("(2 + x) + 7",T(3.0),T(0.0),T((2.0 + 3.0) + 7.0)), - test_xy("(2 + x) - 7",T(3.0),T(0.0),T((2.0 + 3.0) - 7.0)), - test_xy("(2 - x) + 7",T(3.0),T(0.0),T((2.0 - 3.0) + 7.0)), - test_xy("(2 - x) - 7",T(3.0),T(0.0),T((2.0 - 3.0) - 7.0)), - test_xy("(2 * x) * 7",T(3.0),T(0.0),T((2.0 * 3.0) * 7.0)), - test_xy("(2 * x) / 7",T(3.0),T(0.0),T((2.0 * 3.0) / 7.0)), - test_xy("(2 / x) * 7",T(3.0),T(0.0),T((2.0 / 3.0) * 7.0)), - test_xy("(2 / x) / 7",T(3.0),T(0.0),T((2.0 / 3.0) / 7.0)), - test_xy("2 + (x + 7)",T(3.0),T(0.0),T(2.0 + (3.0 + 7.0))), - test_xy("2 + (x - 7)",T(3.0),T(0.0),T(2.0 + (3.0 - 7.0))), - test_xy("2 - (x + 7)",T(3.0),T(0.0),T(2.0 - (3.0 + 7.0))), - test_xy("2 - (x - 7)",T(3.0),T(0.0),T(2.0 - (3.0 - 7.0))), - test_xy("2 * (x * 7)",T(3.0),T(0.0),T(2.0 * (3.0 * 7.0))), - test_xy("2 * (x / 7)",T(3.0),T(0.0),T(2.0 * (3.0 / 7.0))), - test_xy("2 / (x * 7)",T(3.0),T(0.0),T(2.0 / (3.0 * 7.0))), - test_xy("2 / (x / 7)",T(3.0),T(0.0),T(2.0 / (3.0 / 7.0))), - test_xy("2 + (7 + x)",T(3.0),T(0.0),T(2.0 + (7.0 + 3.0))), - test_xy("2 + (7 - x)",T(3.0),T(0.0),T(2.0 + (7.0 - 3.0))), - test_xy("2 - (7 + x)",T(3.0),T(0.0),T(2.0 - (7.0 + 3.0))), - test_xy("2 - (7 - x)",T(3.0),T(0.0),T(2.0 - (7.0 - 3.0))), - test_xy("2 * (7 * x)",T(3.0),T(0.0),T(2.0 * (7.0 * 3.0))), - test_xy("2 * (7 / x)",T(3.0),T(0.0),T(2.0 * (7.0 / 3.0))), - test_xy("2 / (7 * x)",T(3.0),T(0.0),T(2.0 / (7.0 * 3.0))), - test_xy("2 / (7 / x)",T(3.0),T(0.0),T(2.0 / (7.0 / 3.0))), - test_xy("(x + 2) + 7",T(3.0),T(0.0),T((3.0 + 2.0) + 7.0)), - test_xy("(x + 2) - 7",T(3.0),T(0.0),T((3.0 + 2.0) - 7.0)), - test_xy("(x - 2) + 7",T(3.0),T(0.0),T((3.0 - 2.0) + 7.0)), - test_xy("(x - 2) - 7",T(3.0),T(0.0),T((3.0 - 2.0) - 7.0)), - test_xy("(x * 2) * 7",T(3.0),T(0.0),T((3.0 * 2.0) * 7.0)), - test_xy("(x * 2) / 7",T(3.0),T(0.0),T((3.0 * 2.0) / 7.0)), - test_xy("(x / 2) * 7",T(3.0),T(0.0),T((3.0 / 2.0) * 7.0)), - test_xy("(x / 2) / 7",T(3.0),T(0.0),T((3.0 / 2.0) / 7.0)), - test_xy("((2 + x) + (3 + y))",T(7.0),T(9.0),T(((2.0 + 7.0) + (3.0 + 9.0)))), - test_xy("((2 + x) - (3 + y))",T(7.0),T(9.0),T(((2.0 + 7.0) - (3.0 + 9.0)))), - test_xy("((2 - x) - (3 - y))",T(7.0),T(9.0),T(((2.0 - 7.0) - (3.0 - 9.0)))), - test_xy("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), - test_xy("((x + 2) + (y + 3))",T(7.0),T(9.0),T(((7.0 + 2.0) + (9.0 + 3.0)))), - test_xy("((x + 2) - (y + 3))",T(7.0),T(9.0),T(((7.0 + 2.0) - (9.0 + 3.0)))), - test_xy("((x - 2) - (y - 3))",T(7.0),T(9.0),T(((7.0 - 2.0) - (9.0 - 3.0)))), - test_xy("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), - test_xy("((2 + x) + (y + 3))",T(7.0),T(9.0),T(((2.0 + 7.0) + (9.0 + 3.0)))), - test_xy("((2 + x) - (y + 3))",T(7.0),T(9.0),T(((2.0 + 7.0) - (9.0 + 3.0)))), - test_xy("((2 - x) - (y - 3))",T(7.0),T(9.0),T(((2.0 - 7.0) - (9.0 - 3.0)))), - test_xy("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), - test_xy("((x + 2) + (3 + y))",T(7.0),T(9.0),T(((7.0 + 2.0) + (3.0 + 9.0)))), - test_xy("((x + 2) - (3 + y))",T(7.0),T(9.0),T(((7.0 + 2.0) - (3.0 + 9.0)))), - test_xy("((x - 2) - (3 - y))",T(7.0),T(9.0),T(((7.0 - 2.0) - (3.0 - 9.0)))), - test_xy("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), - test_xy("((2 * x) / (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) / (3.0 * 9.0)))), - test_xy("((2 / x) * (3 / y))",T(7.0),T(9.0),T(((2.0 / 7.0) * (3.0 / 9.0)))), - test_xy("((2 * x) / (3 / y))",T(7.0),T(9.0),T(((2.0 * 7.0) / (3.0 / 9.0)))), - test_xy("((2 / x) / (3 * y))",T(7.0),T(9.0),T(((2.0 / 7.0) / (3.0 * 9.0)))), - test_xy("((x * 2) / (y * 3))",T(7.0),T(9.0),T(((7.0 * 2.0) / (9.0 * 3.0)))), - test_xy("((x / 2) * (y / 3))",T(7.0),T(9.0),T(((7.0 / 2.0) * (9.0 / 3.0)))), - test_xy("((x * 2) / (y / 3))",T(7.0),T(9.0),T(((7.0 * 2.0) / (9.0 / 3.0)))), - test_xy("((x / 2) / (y * 3))",T(7.0),T(9.0),T(((7.0 / 2.0) / (9.0 * 3.0)))), - test_xy("((2 * x) / (y * 3))",T(7.0),T(9.0),T(((2.0 * 7.0) / (9.0 * 3.0)))), - test_xy("((2 / x) * (y / 3))",T(7.0),T(9.0),T(((2.0 / 7.0) * (9.0 / 3.0)))), - test_xy("((2 * x) / (y / 3))",T(7.0),T(9.0),T(((2.0 * 7.0) / (9.0 / 3.0)))), - test_xy("((2 / x) / (y * 3))",T(7.0),T(9.0),T(((2.0 / 7.0) / (9.0 * 3.0)))), - test_xy("((x * 2) / (3 * y))",T(7.0),T(9.0),T(((7.0 * 2.0) / (3.0 * 9.0)))), - test_xy("((x / 2) * (3 / y))",T(7.0),T(9.0),T(((7.0 / 2.0) * (3.0 / 9.0)))), - test_xy("((x * 2) / (3 / y))",T(7.0),T(9.0),T(((7.0 * 2.0) / (3.0 / 9.0)))), - test_xy("((x / 2) / (3 * y))",T(7.0),T(9.0),T(((7.0 / 2.0) / (3.0 * 9.0)))), - test_xy("([(min(x,8) + y) + 3] - 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) + 3.0) - 4.0))), - test_xy("([(min(x,8) + y) + 3] + 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) + 3.0) + 4.0))), - test_xy("([(min(x,8) + y) + 3] * 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) + 3.0) * 4.0))), - test_xy("([(min(x,8) + y) + 3] / 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) + 3.0) / 4.0))), - test_xy("([(min(x,8) + y) - 3] - 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) - 3.0) - 4.0))), - test_xy("([(min(x,8) + y) - 3] + 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) - 3.0) + 4.0))), - test_xy("([(min(x,8) + y) - 3] * 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) - 3.0) * 4.0))), - test_xy("([(min(x,8) + y) - 3] / 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) - 3.0) / 4.0))), - test_xy("([(min(x,8) + y) * 3] - 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) * 3.0) - 4.0))), - test_xy("([(min(x,8) + y) * 3] + 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) * 3.0) + 4.0))), - test_xy("([(min(x,8) + y) * 3] * 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) * 3.0) * 4.0))), - test_xy("([(min(x,8) + y) * 3] / 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) * 3.0) / 4.0))), - test_xy("([(min(x,8) + y) / 3] - 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) / 3.0) - 4.0))), - test_xy("([(min(x,8) + y) / 3] + 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) / 3.0) + 4.0))), - test_xy("([(min(x,8) + y) / 3] * 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) / 3.0) * 4.0))), - test_xy("([(min(x,8) + y) / 3] / 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) / 3.0) / 4.0))), - test_xy("(4 - [3 + (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 - (3.0 + (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 + [3 + (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 + (3.0 + (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 * [3 + (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 * (3.0 + (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 / [3 + (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 / (3.0 + (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 - [3 - (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 - (3.0 - (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 + [3 - (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 + (3.0 - (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 * [3 - (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 * (3.0 - (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 / [3 - (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 / (3.0 - (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 - [3 * (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 - (3.0 * (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 + [3 * (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 + (3.0 * (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 * [3 * (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 * (3.0 * (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 / [3 * (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 / (3.0 * (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 - [3 / (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 - (3.0 / (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 + [3 / (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 + (3.0 / (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 * [3 / (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 * (3.0 / (std::min(7.0,8.0) + 9.0))))), - test_xy("(4 / [3 / (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 / (3.0 / (std::min(7.0,8.0) + 9.0))))), - test_xy("((2 * x) + (2 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) + (2.0 * 9.0)))), - test_xy("((2 * x) - (2 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) - (2.0 * 9.0)))), - test_xy("((2 * x) + (y * 2))",T(7.0),T(9.0),T(((2.0 * 7.0) + (9.0 * 2.0)))), - test_xy("((x * 2) - (y * 2))",T(7.0),T(9.0),T(((7.0 * 2.0) - (9.0 * 2.0)))), - test_xy("0 * (abs (x) + acos (y) + asin (x) + atan (y))",T(1.0),T(1.0),T(0.0)), - test_xy("0 * (ceil (x) + cos (y) + cosh (x) + exp (y))",T(1.0),T(1.0),T(0.0)), - test_xy("0 * (floor(x) + log (y) + log10(x) + round(y))",T(1.0),T(1.0),T(0.0)), - test_xy("0 * (sin (x) + sinh (y) + sqrt (x) + tan (y))",T(1.0),T(1.0),T(0.0)), - test_xy("0 * (sec (x) + csc (y) + tanh (x) + cot (y))",T(1.0),T(1.0),T(0.0)), - test_xy("0 * (erf (x) + erfc (y) + sgn (y) + frac (y))",T(1.0),T(1.0),T(0.0)), - test_xy("0 * (log1p(x) + expm1(y) + acosh(x) + asinh(y))",T(1.0),T(1.0),T(0.0)), - test_xy("0 * (deg2grad(x) + grad2deg(y) + rad2deg(x) + deg2rad(y))",T(1.0),T(1.0),T(0.0)), - test_xy("switch { case (x <= y) : (y - x); default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case (x > y) : 0; case (x <= y) : (y - x); default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case (x <= y) : switch { case (x <= y) : (y - x); default: 1.12345; }; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case [x <= y] : [y - x]; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case [x > y] : 0; case [x <= y] : [y - x]; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case [x <= y] : switch { case [x <= y] : {y - x}; default: 1.12345; }; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case {x <= y} : x; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case {x > y} : 0; case {x <= y} : {y - x}; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case {x <= y} : switch { case {x <= y} : x; default: 1.12345; }; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case [(x <= y)] : {y - x}; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case ([x > y]) : [0]; case ([x <= y]) : [y - x]; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("switch { case {(x <= y)} : switch { case ({x <= y}) : x; default: 1.12345; }; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), - test_xy("[*]{ case x < y : x + y; case y < x : y - x; }",T(2.0),T(3.0),T(5.0)), - test_xy("[*]{ case x > y : x + y; case y > x : y - x; }",T(2.0),T(3.0),T(1.0)), - test_xy("[*]{ case x > y : x - y; case y < x : y + x; }",T(2.0),T(3.0),T(0.0)), - test_xy("0 ? x : y" ,T(1.0),T(2.0),T( 2.0)), - test_xy("1 ? x : y" ,T(1.0),T(2.0),T( 1.0)), - test_xy("x ? x : y" ,T(1.0),T(2.0),T( 1.0)), - test_xy("x ? x : y" ,T(0.0),T(2.0),T( 2.0)), - test_xy("(x + y < 4) ? 1 : 2" ,T(1.0),T(2.0),T( 1.0)), - test_xy("(x + y > 4) ? 1 : 2" ,T(1.0),T(2.0),T( 2.0)), - test_xy("x < y ? x + y : x - y" ,T(1.0),T(2.0),T( 3.0)), - test_xy("x > y ? x + y : x - y" ,T(1.0),T(2.0),T(-1.0)), - test_xy("(x + x < y ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)), - test_xy("(x + x < y + y ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)), - test_xy("(x > y + y ? 7 : 9) == 9" ,T(1.0),T(3.0),T( 1.0)), - test_xy("(x + x > y ? 7 : 9) == 9" ,T(1.0),T(3.0),T( 1.0)), - test_xy("(x + x > y + 3 ? 7 : 9) == 9" ,T(1.0),T(3.0),T( 1.0)), - test_xy("(x < (y + y) ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)), - test_xy("((x + x) < y ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)), - test_xy("((x + x) < (y + y) ? 7 : 9) == 7",T(1.0),T(3.0),T( 1.0)), - test_xy("(x += 2 ) == 3 " ,T(1),T(3),T(1)), - test_xy("(x += 2y) == 7 " ,T(1),T(3),T(1)), - test_xy("(x -= 2 ) == -1 " ,T(1),T(3),T(1)), - test_xy("(x -= 2y) == -5 " ,T(1),T(3),T(1)), - test_xy("(x *= 2 ) == 2 " ,T(1),T(3),T(1)), - test_xy("(x *= 2y) == 6 " ,T(1),T(3),T(1)), - test_xy("(x /= 2 ) == (1/2)" ,T(1),T(3),T(1)), - test_xy("(x /= 2y) == (1/6)" ,T(1),T(3),T(1)), - test_xy("for(var i := 0; (i < 10);) { i += 1; }; x;" ,T(1),T(20),T( 1)), - test_xy("for(var i := 0; (i < 10) and (i != y); i+=2) { x += i; }; x;" ,T(1),T(20),T(21)), - test_xy("for(var i := 0; (i < 10) and (i != y);) { x += i; i+=2; }; x;",T(1),T(20),T(21)), - test_xy("for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) x += i; else break; }; x;" ,T(0),T(10),T(15)), - test_xy("for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) continue; else x += i; }; x;" ,T(0),T(10),T(30)), - test_xy("var a := 2; (0 * a) == 0",T(0),T(0),T(1)), - test_xy("var a := 2; (0 / a) == 0",T(0),T(0),T(1)), - test_xy("var a := 2; (a * 0) == 0",T(0),T(0),T(1)), - test_xy("var a := 2; (a / 1) == a",T(0),T(0),T(1)), - test_xy("var a := 2; (0 + a) == a",T(0),T(0),T(1)), - test_xy("var a := 2; (a + 0) == a",T(0),T(0),T(1)), - test_xy("var a := 2; (1 * a) == a",T(0),T(0),T(1)), - test_xy("var a.b := 3; (2 * a.b ) == 6",T(0),T(0),T(1)), - test_xy("var aa.bb := 3; (2 * aa.bb ) == 6",T(0),T(0),T(1)), - test_xy("var aaa.bbb := 3; (2 * aAa.BbB) == 6",T(0),T(0),T(1)), - test_xy("var a1.b2 := 3; (2 * a1.b2 ) == 6",T(0),T(0),T(1)) - }; + { + test_xy("x + y" ,T(2.2),T(3.3),T(5.5 )), + test_xy("x - y" ,T(3.3),T(2.2),T(1.1 )), + test_xy("x * y" ,T(3.3),T(2.2),T(7.26 )), + test_xy("x / y" ,T(3.3),T(2.2),T(1.5 )), + test_xy("(x + y) * (x + y)" ,T(2.2),T(3.3),T(30.25)), + test_xy("(x + y) / (x + y)" ,T(2.2),T(3.3),T(1.0 )), + test_xy("x + y > x and x + y > y" ,T(2.2),T(3.3),T(1.0)), + test_xy("1 + (x + y)" ,T(2.2),T(3.3),T(6.5 )), + test_xy("(x + y) - 1" ,T(2.2),T(3.3),T(4.5 )), + test_xy("1 + (x + y) * 2" ,T(2.2),T(3.3),T(12.0 )), + test_xy("2 * (x + y) - 1" ,T(2.2),T(3.3),T(10.0 )), + test_xy("y + (x + 1)" ,T(2.2),T(3.3),T(6.5 )), + test_xy("(x + 1) + y" ,T(2.2),T(3.3),T(6.5 )), + test_xy("2 * x" ,T(2.2),T(0.0),T(4.4)), + test_xy("x * 2" ,T(2.2),T(0.0),T(4.4)), + test_xy("1.1 + x" ,T(2.2),T(0.0),T(3.3)), + test_xy("x + 1.1" ,T(2.2),T(0.0),T(3.3)), + test_xy("x - -1 " ,T(1.0),T(0.0),T(2)), + test_xy("x --1 " ,T(1.0),T(0.0),T(2)), + test_xy("x-- 1 " ,T(1.0),T(0.0),T(2)), + test_xy("x--1 " ,T(1.0),T(0.0),T(2)), + test_xy("x -- -1" ,T(1.0),T(0.0),T(0)), + test_xy("x + -1 " ,T(1.0),T(0.0),T(0)), + test_xy("x +-1 " ,T(1.0),T(0.0),T(0)), + test_xy("x+- 1 " ,T(1.0),T(0.0),T(0)), + test_xy("x+-1 " ,T(1.0),T(0.0),T(0)), + test_xy("x +- -1" ,T(1.0),T(0.0),T(2)), + test_xy("x + +1 " ,T(1.0),T(0.0),T(2)), + test_xy("x ++1 " ,T(1.0),T(0.0),T(2)), + test_xy("1 - -x " ,T(1.0),T(0.0),T(2)), + test_xy("1 --x " ,T(1.0),T(0.0),T(2)), + test_xy("1-- x " ,T(1.0),T(0.0),T(2)), + test_xy("1--x " ,T(1.0),T(0.0),T(2)), + test_xy("1 -- -x" ,T(1.0),T(0.0),T(0)), + test_xy("1 + -x " ,T(1.0),T(0.0),T(0)), + test_xy("1 +-x " ,T(1.0),T(0.0),T(0)), + test_xy("1+- x " ,T(1.0),T(0.0),T(0)), + test_xy("1+-x " ,T(1.0),T(0.0),T(0)), + test_xy("1 +- -x" ,T(1.0),T(0.0),T(2)), + test_xy("1 + +x " ,T(1.0),T(0.0),T(2)), + test_xy("1 ++x " ,T(1.0),T(0.0),T(2)), + test_xy("(x - -1 + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(x --1 + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(x-- 1 + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(x--1 + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(x -- -1 + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x + -1 + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x +-1 + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x+- 1 + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x+-1 + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x +- -1 + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(x + +1 + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(x ++1 + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(1 - -x + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(1 --x + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(1-- x + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(1--x + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(1 -- -x + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1 + -x + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1 +-x + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1+- x + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1+-x + 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1 +- -x + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(1 + +x + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(1 ++x + 1)" ,T(1.0),T(0.0),T(3)), + test_xy("(x - -1 - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x --1 - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x-- 1 - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x--1 - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x -- -1 - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(x + -1 - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(x +-1 - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(x+- 1 - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(x+-1 - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(x +- -1 - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x + +1 - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(x ++1 - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1 - -x - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1 --x - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1-- x - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1--x - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1 -- -x - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(1 + -x - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(1 +-x - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(1+- x - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(1+-x - 1)" ,T(1.0),T(0.0),T(-1)), + test_xy("(1 +- -x - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1 + +x - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("(1 ++x - 1)" ,T(1.0),T(0.0),T(1)), + test_xy("x * 1 == x" ,T(2.0),T(3.0),T(1.0)), + test_xy("1 * x == x" ,T(2.0),T(3.0),T(1.0)), + test_xy("y * 1 == y" ,T(2.0),T(3.0),T(1.0)), + test_xy("1 * y == y" ,T(2.0),T(3.0),T(1.0)), + test_xy("x * 0 == 0" ,T(2.0),T(3.0),T(1.0)), + test_xy("0 * x == 0" ,T(2.0),T(3.0),T(1.0)), + test_xy("y * 0 == 0" ,T(2.0),T(3.0),T(1.0)), + test_xy("0 * y == 0" ,T(2.0),T(3.0),T(1.0)), + test_xy("x + 1 == 1 + x" ,T(2.0),T(3.0),T(1.0)), + test_xy("y + 1 == 1 + y" ,T(2.0),T(3.0),T(1.0)), + test_xy("x + y == y + x" ,T(2.0),T(3.0),T(1.0)), + test_xy("x * y == y * x" ,T(2.0),T(3.0),T(1.0)), + test_xy("x < y" ,T(2.0),T(3.0),T(1.0)), + test_xy("y > x" ,T(2.0),T(3.0),T(1.0)), + test_xy("x <= y" ,T(2.0),T(3.0),T(1.0)), + test_xy("y >= x" ,T(2.0),T(3.0),T(1.0)), + test_xy("x + y > y" ,T(2.0),T(3.0),T(1.0)), + test_xy("x + y > x" ,T(2.0),T(3.0),T(1.0)), + test_xy("x * y > y" ,T(2.0),T(3.0),T(1.0)), + test_xy("x * y > x" ,T(2.0),T(3.0),T(1.0)), + test_xy("(x + y) > y" ,T(2.0),T(3.0),T(1.0)), + test_xy("(x + y) > x" ,T(2.0),T(3.0),T(1.0)), + test_xy("(x * y) > y" ,T(2.0),T(3.0),T(1.0)), + test_xy("(x * y) > x" ,T(2.0),T(3.0),T(1.0)), + test_xy("(2x + 3y) == (2*x + 3*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy("2(x + y) == (2*x + 2*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (x + y)3 == (3*x + 3*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy("2x + 3y == 2*x + 3*y" ,T(2.0),T(3.0),T(1.0)), + test_xy("2(x + y) == 2*x + 2*y" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (x + y)3 == 3*x + 3*y" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (x)y == (x*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" x(y) == (x*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (x) y == (x*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" x (y) == (x*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" ((x) y) == (x*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (x (y)) == (x*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (x)3 == (x*3)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" x(3) == (x*3)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (x) 3 == (x*3)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" x (3) == (x*3)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" ((x) 3) == (x*3)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (x (3)) == (x*3)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (2)y == (2*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" 2(y) == (2*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (2) y == (2*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" 2 (y) == (2*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" ((2) y) == (2*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy(" (2 (y)) == (2*y)" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; (a)(3) == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; (A){3} == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; (a)[3] == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; {a}(3) == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; {a}{3} == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; {a}[3] == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; (a)(b) == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; (a){B} == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; (a)[b] == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; {a}(b) == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; {a}{b} == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; {a}[b] == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; (a)(a+1) == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; (a){a+1} == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; (a)[a+1] == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; {a}(a+1) == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; {a}{a+1} == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; {a}[a+1] == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; (b-1)(b) == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; (b-1){b} == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; (b-1)[b] == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; {b-1}(b) == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; {b-1}{b} == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("var a := 2; var b := 3; {b-1}[b] == 6" ,T(2.0),T(3.0),T(1.0)), + test_xy("equal(x^2.2^1.1,17.15193942371376191362)" ,T(3.3),T(0.0),T(1.0)), + test_xy("equal(3.3^x^1.1,17.15193942371376191362)" ,T(2.2),T(0.0),T(1.0)), + test_xy("equal(3.3^2.2^x,17.15193942371376191362)" ,T(1.1),T(0.0),T(1.0)), + test_xy("equal(x^2.2^y,17.15193942371376191362)" ,T(3.3),T(1.1),T(1.0)), + test_xy("equal(x^y^1.1,17.15193942371376191362)" ,T(3.3),T(2.2),T(1.0)), + test_xy("equal(3.3^x^y,17.15193942371376191362)" ,T(2.2),T(1.1),T(1.0)), + test_xy("equal(x+y^3/7,x+(y*y*y)/7)",T(2.0),T(3.0),T(1.0)), + test_xy("equal(1-x^3+y^2*7,1-(x*x*x)+(y*y)*7)",T(2.0),T(3.0),T(1.0)), + test_xy("equal( x^0,1)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^1,x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^2,x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^3,x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^4,x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^5,x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^6,x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^7,x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^8,x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^9,x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^10,x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^11,x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^12,x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^13,x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^14,x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^15,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^16,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^17,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^18,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^19,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^20,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^21,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^22,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^23,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^24,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^25,x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( y^0,1)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^1,y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^2,y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^3,y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^4,y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^5,y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^6,y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^7,y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^8,y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^9,y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^10,y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^11,y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^12,y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^13,y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^14,y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^15,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^16,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^17,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^18,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^19,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^20,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^21,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^22,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^23,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^24,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^25,y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( x^-0,1/1)",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-1,1/(x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-2,1/(x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-3,1/(x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-4,1/(x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-5,1/(x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-6,1/(x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-7,1/(x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-8,1/(x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( x^-9,1/(x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-10,1/(x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-11,1/(x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-12,1/(x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-13,1/(x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-14,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-15,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-16,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-17,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-18,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-19,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-20,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-21,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-22,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-23,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-24,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal(x^-25,1/(x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x))",T(12.34),T(0.0),T(1.0)), + test_xy("equal( y^-0,1/1)",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-1,1/(y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-2,1/(y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-3,1/(y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-4,1/(y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-5,1/(y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-6,1/(y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-7,1/(y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-8,1/(y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal( y^-9,1/(y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-10,1/(y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-11,1/(y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-12,1/(y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-13,1/(y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-14,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-15,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-16,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-17,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-18,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-19,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-20,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-21,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-22,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-23,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-24,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("equal(y^-25,1/(y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y*y))",T(0.0),T(12.34),T(1.0)), + test_xy("(2 + x) + 7",T(3.0),T(0.0),T((2.0 + 3.0) + 7.0)), + test_xy("(2 + x) - 7",T(3.0),T(0.0),T((2.0 + 3.0) - 7.0)), + test_xy("(2 - x) + 7",T(3.0),T(0.0),T((2.0 - 3.0) + 7.0)), + test_xy("(2 - x) - 7",T(3.0),T(0.0),T((2.0 - 3.0) - 7.0)), + test_xy("(2 * x) * 7",T(3.0),T(0.0),T((2.0 * 3.0) * 7.0)), + test_xy("(2 * x) / 7",T(3.0),T(0.0),T((2.0 * 3.0) / 7.0)), + test_xy("(2 / x) * 7",T(3.0),T(0.0),T((2.0 / 3.0) * 7.0)), + test_xy("(2 / x) / 7",T(3.0),T(0.0),T((2.0 / 3.0) / 7.0)), + test_xy("2 + (x + 7)",T(3.0),T(0.0),T(2.0 + (3.0 + 7.0))), + test_xy("2 + (x - 7)",T(3.0),T(0.0),T(2.0 + (3.0 - 7.0))), + test_xy("2 - (x + 7)",T(3.0),T(0.0),T(2.0 - (3.0 + 7.0))), + test_xy("2 - (x - 7)",T(3.0),T(0.0),T(2.0 - (3.0 - 7.0))), + test_xy("2 * (x * 7)",T(3.0),T(0.0),T(2.0 * (3.0 * 7.0))), + test_xy("2 * (x / 7)",T(3.0),T(0.0),T(2.0 * (3.0 / 7.0))), + test_xy("2 / (x * 7)",T(3.0),T(0.0),T(2.0 / (3.0 * 7.0))), + test_xy("2 / (x / 7)",T(3.0),T(0.0),T(2.0 / (3.0 / 7.0))), + test_xy("2 + (7 + x)",T(3.0),T(0.0),T(2.0 + (7.0 + 3.0))), + test_xy("2 + (7 - x)",T(3.0),T(0.0),T(2.0 + (7.0 - 3.0))), + test_xy("2 - (7 + x)",T(3.0),T(0.0),T(2.0 - (7.0 + 3.0))), + test_xy("2 - (7 - x)",T(3.0),T(0.0),T(2.0 - (7.0 - 3.0))), + test_xy("2 * (7 * x)",T(3.0),T(0.0),T(2.0 * (7.0 * 3.0))), + test_xy("2 * (7 / x)",T(3.0),T(0.0),T(2.0 * (7.0 / 3.0))), + test_xy("2 / (7 * x)",T(3.0),T(0.0),T(2.0 / (7.0 * 3.0))), + test_xy("2 / (7 / x)",T(3.0),T(0.0),T(2.0 / (7.0 / 3.0))), + test_xy("(x + 2) + 7",T(3.0),T(0.0),T((3.0 + 2.0) + 7.0)), + test_xy("(x + 2) - 7",T(3.0),T(0.0),T((3.0 + 2.0) - 7.0)), + test_xy("(x - 2) + 7",T(3.0),T(0.0),T((3.0 - 2.0) + 7.0)), + test_xy("(x - 2) - 7",T(3.0),T(0.0),T((3.0 - 2.0) - 7.0)), + test_xy("(x * 2) * 7",T(3.0),T(0.0),T((3.0 * 2.0) * 7.0)), + test_xy("(x * 2) / 7",T(3.0),T(0.0),T((3.0 * 2.0) / 7.0)), + test_xy("(x / 2) * 7",T(3.0),T(0.0),T((3.0 / 2.0) * 7.0)), + test_xy("(x / 2) / 7",T(3.0),T(0.0),T((3.0 / 2.0) / 7.0)), + test_xy("((2 + x) + (3 + y))",T(7.0),T(9.0),T(((2.0 + 7.0) + (3.0 + 9.0)))), + test_xy("((2 + x) - (3 + y))",T(7.0),T(9.0),T(((2.0 + 7.0) - (3.0 + 9.0)))), + test_xy("((2 - x) - (3 - y))",T(7.0),T(9.0),T(((2.0 - 7.0) - (3.0 - 9.0)))), + test_xy("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), + test_xy("((x + 2) + (y + 3))",T(7.0),T(9.0),T(((7.0 + 2.0) + (9.0 + 3.0)))), + test_xy("((x + 2) - (y + 3))",T(7.0),T(9.0),T(((7.0 + 2.0) - (9.0 + 3.0)))), + test_xy("((x - 2) - (y - 3))",T(7.0),T(9.0),T(((7.0 - 2.0) - (9.0 - 3.0)))), + test_xy("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), + test_xy("((2 + x) + (y + 3))",T(7.0),T(9.0),T(((2.0 + 7.0) + (9.0 + 3.0)))), + test_xy("((2 + x) - (y + 3))",T(7.0),T(9.0),T(((2.0 + 7.0) - (9.0 + 3.0)))), + test_xy("((2 - x) - (y - 3))",T(7.0),T(9.0),T(((2.0 - 7.0) - (9.0 - 3.0)))), + test_xy("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), + test_xy("((x + 2) + (3 + y))",T(7.0),T(9.0),T(((7.0 + 2.0) + (3.0 + 9.0)))), + test_xy("((x + 2) - (3 + y))",T(7.0),T(9.0),T(((7.0 + 2.0) - (3.0 + 9.0)))), + test_xy("((x - 2) - (3 - y))",T(7.0),T(9.0),T(((7.0 - 2.0) - (3.0 - 9.0)))), + test_xy("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), + test_xy("((2 * x) / (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) / (3.0 * 9.0)))), + test_xy("((2 / x) * (3 / y))",T(7.0),T(9.0),T(((2.0 / 7.0) * (3.0 / 9.0)))), + test_xy("((2 * x) / (3 / y))",T(7.0),T(9.0),T(((2.0 * 7.0) / (3.0 / 9.0)))), + test_xy("((2 / x) / (3 * y))",T(7.0),T(9.0),T(((2.0 / 7.0) / (3.0 * 9.0)))), + test_xy("((x * 2) / (y * 3))",T(7.0),T(9.0),T(((7.0 * 2.0) / (9.0 * 3.0)))), + test_xy("((x / 2) * (y / 3))",T(7.0),T(9.0),T(((7.0 / 2.0) * (9.0 / 3.0)))), + test_xy("((x * 2) / (y / 3))",T(7.0),T(9.0),T(((7.0 * 2.0) / (9.0 / 3.0)))), + test_xy("((x / 2) / (y * 3))",T(7.0),T(9.0),T(((7.0 / 2.0) / (9.0 * 3.0)))), + test_xy("((2 * x) / (y * 3))",T(7.0),T(9.0),T(((2.0 * 7.0) / (9.0 * 3.0)))), + test_xy("((2 / x) * (y / 3))",T(7.0),T(9.0),T(((2.0 / 7.0) * (9.0 / 3.0)))), + test_xy("((2 * x) / (y / 3))",T(7.0),T(9.0),T(((2.0 * 7.0) / (9.0 / 3.0)))), + test_xy("((2 / x) / (y * 3))",T(7.0),T(9.0),T(((2.0 / 7.0) / (9.0 * 3.0)))), + test_xy("((x * 2) / (3 * y))",T(7.0),T(9.0),T(((7.0 * 2.0) / (3.0 * 9.0)))), + test_xy("((x / 2) * (3 / y))",T(7.0),T(9.0),T(((7.0 / 2.0) * (3.0 / 9.0)))), + test_xy("((x * 2) / (3 / y))",T(7.0),T(9.0),T(((7.0 * 2.0) / (3.0 / 9.0)))), + test_xy("((x / 2) / (3 * y))",T(7.0),T(9.0),T(((7.0 / 2.0) / (3.0 * 9.0)))), + test_xy("([(min(x,8) + y) + 3] - 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) + 3.0) - 4.0))), + test_xy("([(min(x,8) + y) + 3] + 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) + 3.0) + 4.0))), + test_xy("([(min(x,8) + y) + 3] * 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) + 3.0) * 4.0))), + test_xy("([(min(x,8) + y) + 3] / 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) + 3.0) / 4.0))), + test_xy("([(min(x,8) + y) - 3] - 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) - 3.0) - 4.0))), + test_xy("([(min(x,8) + y) - 3] + 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) - 3.0) + 4.0))), + test_xy("([(min(x,8) + y) - 3] * 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) - 3.0) * 4.0))), + test_xy("([(min(x,8) + y) - 3] / 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) - 3.0) / 4.0))), + test_xy("([(min(x,8) + y) * 3] - 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) * 3.0) - 4.0))), + test_xy("([(min(x,8) + y) * 3] + 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) * 3.0) + 4.0))), + test_xy("([(min(x,8) + y) * 3] * 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) * 3.0) * 4.0))), + test_xy("([(min(x,8) + y) * 3] / 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) * 3.0) / 4.0))), + test_xy("([(min(x,8) + y) / 3] - 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) / 3.0) - 4.0))), + test_xy("([(min(x,8) + y) / 3] + 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) / 3.0) + 4.0))), + test_xy("([(min(x,8) + y) / 3] * 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) / 3.0) * 4.0))), + test_xy("([(min(x,8) + y) / 3] / 4)",T(7.0),T(9.0),T((((std::min(7.0,8.0) + 9.0) / 3.0) / 4.0))), + test_xy("(4 - [3 + (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 - (3.0 + (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 + [3 + (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 + (3.0 + (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 * [3 + (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 * (3.0 + (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 / [3 + (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 / (3.0 + (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 - [3 - (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 - (3.0 - (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 + [3 - (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 + (3.0 - (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 * [3 - (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 * (3.0 - (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 / [3 - (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 / (3.0 - (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 - [3 * (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 - (3.0 * (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 + [3 * (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 + (3.0 * (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 * [3 * (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 * (3.0 * (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 / [3 * (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 / (3.0 * (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 - [3 / (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 - (3.0 / (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 + [3 / (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 + (3.0 / (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 * [3 / (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 * (3.0 / (std::min(7.0,8.0) + 9.0))))), + test_xy("(4 / [3 / (min(x,8) + y)])",T(7.0),T(9.0),T((4.0 / (3.0 / (std::min(7.0,8.0) + 9.0))))), + test_xy("((2 * x) + (2 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) + (2.0 * 9.0)))), + test_xy("((2 * x) - (2 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) - (2.0 * 9.0)))), + test_xy("((2 * x) + (y * 2))",T(7.0),T(9.0),T(((2.0 * 7.0) + (9.0 * 2.0)))), + test_xy("((x * 2) - (y * 2))",T(7.0),T(9.0),T(((7.0 * 2.0) - (9.0 * 2.0)))), + test_xy("0 * (abs (x) + acos (y) + asin (x) + atan (y))",T(1.0),T(1.0),T(0.0)), + test_xy("0 * (ceil (x) + cos (y) + cosh (x) + exp (y))",T(1.0),T(1.0),T(0.0)), + test_xy("0 * (floor(x) + log (y) + log10(x) + round(y))",T(1.0),T(1.0),T(0.0)), + test_xy("0 * (sin (x) + sinh (y) + sqrt (x) + tan (y))",T(1.0),T(1.0),T(0.0)), + test_xy("0 * (sec (x) + csc (y) + tanh (x) + cot (y))",T(1.0),T(1.0),T(0.0)), + test_xy("0 * (erf (x) + erfc (y) + sgn (y) + frac (y))",T(1.0),T(1.0),T(0.0)), + test_xy("0 * (log1p(x) + expm1(y) + acosh(x) + asinh(y))",T(1.0),T(1.0),T(0.0)), + test_xy("0 * (deg2grad(x) + grad2deg(y) + rad2deg(x) + deg2rad(y))",T(1.0),T(1.0),T(0.0)), + test_xy("switch { case (x <= y) : (y - x); default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case (x > y) : 0; case (x <= y) : (y - x); default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case (x <= y) : switch { case (x <= y) : (y - x); default: 1.12345; }; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case [x <= y] : [y - x]; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case [x > y] : 0; case [x <= y] : [y - x]; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case [x <= y] : switch { case [x <= y] : {y - x}; default: 1.12345; }; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case {x <= y} : x; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case {x > y} : 0; case {x <= y} : {y - x}; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case {x <= y} : switch { case {x <= y} : x; default: 1.12345; }; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case [(x <= y)] : {y - x}; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case ([x > y]) : [0]; case ([x <= y]) : [y - x]; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("switch { case {(x <= y)} : switch { case ({x <= y}) : x; default: 1.12345; }; default: 1.12345; }",T(1.0),T(2.0),T(1.0)), + test_xy("[*]{ case x < y : x + y; case y < x : y - x; }",T(2.0),T(3.0),T(5.0)), + test_xy("[*]{ case x > y : x + y; case y > x : y - x; }",T(2.0),T(3.0),T(1.0)), + test_xy("[*]{ case x > y : x - y; case y < x : y + x; }",T(2.0),T(3.0),T(0.0)), + test_xy("0 ? x : y" ,T(1.0),T(2.0),T( 2.0)), + test_xy("1 ? x : y" ,T(1.0),T(2.0),T( 1.0)), + test_xy("x ? x : y" ,T(1.0),T(2.0),T( 1.0)), + test_xy("x ? x : y" ,T(0.0),T(2.0),T( 2.0)), + test_xy("(x + y < 4) ? 1 : 2" ,T(1.0),T(2.0),T( 1.0)), + test_xy("(x + y > 4) ? 1 : 2" ,T(1.0),T(2.0),T( 2.0)), + test_xy("x < y ? x + y : x - y" ,T(1.0),T(2.0),T( 3.0)), + test_xy("x > y ? x + y : x - y" ,T(1.0),T(2.0),T(-1.0)), + test_xy("(x + x < y ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)), + test_xy("(x + x < y + y ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)), + test_xy("(x > y + y ? 7 : 9) == 9" ,T(1.0),T(3.0),T( 1.0)), + test_xy("(x + x > y ? 7 : 9) == 9" ,T(1.0),T(3.0),T( 1.0)), + test_xy("(x + x > y + 3 ? 7 : 9) == 9" ,T(1.0),T(3.0),T( 1.0)), + test_xy("(x < (y + y) ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)), + test_xy("((x + x) < y ? 7 : 9) == 7" ,T(1.0),T(3.0),T( 1.0)), + test_xy("((x + x) < (y + y) ? 7 : 9) == 7",T(1.0),T(3.0),T( 1.0)), + test_xy("(x += 2 ) == 3 " ,T(1),T(3),T(1)), + test_xy("(x += 2y) == 7 " ,T(1),T(3),T(1)), + test_xy("(x -= 2 ) == -1 " ,T(1),T(3),T(1)), + test_xy("(x -= 2y) == -5 " ,T(1),T(3),T(1)), + test_xy("(x *= 2 ) == 2 " ,T(1),T(3),T(1)), + test_xy("(x *= 2y) == 6 " ,T(1),T(3),T(1)), + test_xy("(x /= 2 ) == (1/2)" ,T(1),T(3),T(1)), + test_xy("(x /= 2y) == (1/6)" ,T(1),T(3),T(1)), + test_xy("for(var i := 0; (i < 10);) { i += 1; }; x;" ,T(1),T(20),T( 1)), + test_xy("for(var i := 0; (i < 10) and (i != y); i+=2) { x += i; }; x;" ,T(1),T(20),T(21)), + test_xy("for(var i := 0; (i < 10) and (i != y);) { x += i; i+=2; }; x;",T(1),T(20),T(21)), + test_xy("for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) x += i; else break; }; x;" ,T(0),T(10),T(15)), + test_xy("for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) continue; else x += i; }; x;" ,T(0),T(10),T(30)), + test_xy("var a := 2; (0 * a) == 0",T(0),T(0),T(1)), + test_xy("var a := 2; (0 / a) == 0",T(0),T(0),T(1)), + test_xy("var a := 2; (a * 0) == 0",T(0),T(0),T(1)), + test_xy("var a := 2; (a / 1) == a",T(0),T(0),T(1)), + test_xy("var a := 2; (0 + a) == a",T(0),T(0),T(1)), + test_xy("var a := 2; (a + 0) == a",T(0),T(0),T(1)), + test_xy("var a := 2; (1 * a) == a",T(0),T(0),T(1)), + test_xy("var a.b := 3; (2 * a.b ) == 6",T(0),T(0),T(1)), + test_xy("var aa.bb := 3; (2 * aa.bb ) == 6",T(0),T(0),T(1)), + test_xy("var aaa.bbb := 3; (2 * aAa.BbB) == 6",T(0),T(0),T(1)), + test_xy("var a1.b2 := 3; (2 * a1.b2 ) == 6",T(0),T(0),T(1)) + }; static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_xy); @@ -1832,60 +1844,60 @@ inline bool run_test01() { static const test_xyzw test_list[] = - { - test_xyzw("((x / y) / z )",T(7.0),T(9.0),T(3.0),T(0.0),T(((7.0 / 9.0) / 3.0 ))), - test_xyzw("((x / y) / 2 )",T(7.0),T(9.0),T(3.0),T(0.0),T(((7.0 / 9.0) / 2.0 ))), - test_xyzw("((x / 2) / y )",T(7.0),T(9.0),T(3.0),T(0.0),T(((7.0 / 2.0) / 9.0 ))), - test_xyzw("((2 / x) / y )",T(7.0),T(9.0),T(3.0),T(0.0),T(((2.0 / 7.0) / 9.0 ))), - test_xyzw("( x / (y / z))",T(7.0),T(9.0),T(3.0),T(0.0),T(( 7.0 / (9.0 / 3.0)))), - test_xyzw("( x / (y / 2))",T(7.0),T(9.0),T(3.0),T(0.0),T(( 7.0 / (9.0 / 2.0)))), - test_xyzw("( x / (2 / y))",T(7.0),T(9.0),T(3.0),T(0.0),T(( 7.0 / (2.0 / 9.0)))), - test_xyzw("( 2 / (x / y))",T(7.0),T(9.0),T(3.0),T(0.0),T(( 2.0 / (7.0 / 9.0)))), - test_xyzw("([(min(x,y) + z) + 3] - 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) + 3.0) - 4.0))), - test_xyzw("([(min(x,y) + z) + 3] + 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) + 3.0) + 4.0))), - test_xyzw("([(min(x,y) + z) + 3] * 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) + 3.0) * 4.0))), - test_xyzw("([(min(x,y) + z) + 3] / 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) + 3.0) / 4.0))), - test_xyzw("([(min(x,y) + z) - 3] - 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) - 3.0) - 4.0))), - test_xyzw("([(min(x,y) + z) - 3] + 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) - 3.0) + 4.0))), - test_xyzw("([(min(x,y) + z) - 3] * 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) - 3.0) * 4.0))), - test_xyzw("([(min(x,y) + z) - 3] / 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) - 3.0) / 4.0))), - test_xyzw("([(min(x,y) + z) * 3] - 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) * 3.0) - 4.0))), - test_xyzw("([(min(x,y) + z) * 3] + 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) * 3.0) + 4.0))), - test_xyzw("([(min(x,y) + z) * 3] * 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) * 3.0) * 4.0))), - test_xyzw("([(min(x,y) + z) * 3] / 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) * 3.0) / 4.0))), - test_xyzw("([(min(x,y) + z) / 3] - 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) / 3.0) - 4.0))), - test_xyzw("([(min(x,y) + z) / 3] + 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) / 3.0) + 4.0))), - test_xyzw("([(min(x,y) + z) / 3] * 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) / 3.0) * 4.0))), - test_xyzw("([(min(x,y) + z) / 3] / 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) / 3.0) / 4.0))), - test_xyzw("(4 - [3 + (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 - (3.0 + (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 + [3 + (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 + (3.0 + (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 * [3 + (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 * (3.0 + (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 / [3 + (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 / (3.0 + (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 - [3 - (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 - (3.0 - (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 + [3 - (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 + (3.0 - (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 * [3 - (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 * (3.0 - (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 / [3 - (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 / (3.0 - (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 - [3 * (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 - (3.0 * (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 + [3 * (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 + (3.0 * (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 * [3 * (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 * (3.0 * (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 / [3 * (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 / (3.0 * (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 - [3 / (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 - (3.0 / (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 + [3 / (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 + (3.0 / (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 * [3 / (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 * (3.0 / (std::min(5.0,7.0) + 9.0))))), - test_xyzw("(4 / [3 / (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 / (3.0 / (std::min(5.0,7.0) + 9.0))))), - test_xyzw("if (x < y) { z+2; z;} == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x > y) { z+2; z;} == null" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x < y) { z+2; z;} else w; == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x > y) { z+2; z;} else 1 + w; == (w + 1)" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x < y) { z+2; z;} else {1+2; w;} == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x > y) { z+2; z;} else {1+2; w;} == w" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x < y) { z+2; z;} else if (x < y) w; == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x > y) { z+2; z;} else if (x < y) 1 + w; == w + 1" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x > y) { z+2; z;} else if (x > y) w; == null" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x < y) { z+2; z;} else if (x < y) {w+2; w;} == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x > y) { z+2; z;} else if (x < y) {w+2; w;} == w" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), - test_xyzw("if (x > y) { z+2; z;} else if (x > y) {w+2; w;} == null",T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)) - }; + { + test_xyzw("((x / y) / z )",T(7.0),T(9.0),T(3.0),T(0.0),T(((7.0 / 9.0) / 3.0 ))), + test_xyzw("((x / y) / 2 )",T(7.0),T(9.0),T(3.0),T(0.0),T(((7.0 / 9.0) / 2.0 ))), + test_xyzw("((x / 2) / y )",T(7.0),T(9.0),T(3.0),T(0.0),T(((7.0 / 2.0) / 9.0 ))), + test_xyzw("((2 / x) / y )",T(7.0),T(9.0),T(3.0),T(0.0),T(((2.0 / 7.0) / 9.0 ))), + test_xyzw("( x / (y / z))",T(7.0),T(9.0),T(3.0),T(0.0),T(( 7.0 / (9.0 / 3.0)))), + test_xyzw("( x / (y / 2))",T(7.0),T(9.0),T(3.0),T(0.0),T(( 7.0 / (9.0 / 2.0)))), + test_xyzw("( x / (2 / y))",T(7.0),T(9.0),T(3.0),T(0.0),T(( 7.0 / (2.0 / 9.0)))), + test_xyzw("( 2 / (x / y))",T(7.0),T(9.0),T(3.0),T(0.0),T(( 2.0 / (7.0 / 9.0)))), + test_xyzw("([(min(x,y) + z) + 3] - 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) + 3.0) - 4.0))), + test_xyzw("([(min(x,y) + z) + 3] + 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) + 3.0) + 4.0))), + test_xyzw("([(min(x,y) + z) + 3] * 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) + 3.0) * 4.0))), + test_xyzw("([(min(x,y) + z) + 3] / 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) + 3.0) / 4.0))), + test_xyzw("([(min(x,y) + z) - 3] - 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) - 3.0) - 4.0))), + test_xyzw("([(min(x,y) + z) - 3] + 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) - 3.0) + 4.0))), + test_xyzw("([(min(x,y) + z) - 3] * 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) - 3.0) * 4.0))), + test_xyzw("([(min(x,y) + z) - 3] / 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) - 3.0) / 4.0))), + test_xyzw("([(min(x,y) + z) * 3] - 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) * 3.0) - 4.0))), + test_xyzw("([(min(x,y) + z) * 3] + 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) * 3.0) + 4.0))), + test_xyzw("([(min(x,y) + z) * 3] * 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) * 3.0) * 4.0))), + test_xyzw("([(min(x,y) + z) * 3] / 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) * 3.0) / 4.0))), + test_xyzw("([(min(x,y) + z) / 3] - 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) / 3.0) - 4.0))), + test_xyzw("([(min(x,y) + z) / 3] + 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) / 3.0) + 4.0))), + test_xyzw("([(min(x,y) + z) / 3] * 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) / 3.0) * 4.0))), + test_xyzw("([(min(x,y) + z) / 3] / 4)",T(5.0),T(7.0),T(9.0),T(0.0),T((((std::min(5.0,7.0) + 9.0) / 3.0) / 4.0))), + test_xyzw("(4 - [3 + (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 - (3.0 + (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 + [3 + (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 + (3.0 + (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 * [3 + (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 * (3.0 + (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 / [3 + (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 / (3.0 + (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 - [3 - (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 - (3.0 - (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 + [3 - (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 + (3.0 - (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 * [3 - (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 * (3.0 - (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 / [3 - (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 / (3.0 - (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 - [3 * (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 - (3.0 * (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 + [3 * (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 + (3.0 * (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 * [3 * (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 * (3.0 * (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 / [3 * (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 / (3.0 * (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 - [3 / (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 - (3.0 / (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 + [3 / (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 + (3.0 / (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 * [3 / (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 * (3.0 / (std::min(5.0,7.0) + 9.0))))), + test_xyzw("(4 / [3 / (min(x,y) + z)])",T(5.0),T(7.0),T(9.0),T(0.0),T((4.0 / (3.0 / (std::min(5.0,7.0) + 9.0))))), + test_xyzw("if (x < y) { z+2; z;} == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("if (x > y) { z+2; z;} == null" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("if (x < y) { z+2; z;} else w; == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("if (x > y) { z+2; z;} else 1 + w; == (w + 1)" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("if (x < y) { z+2; z;} else {1+2; w;} == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("if (x > y) { z+2; z;} else {1+2; w;} == w" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("(if (x < y) { z+2; z;} else if (x < y) w;) == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("(if (x > y) { z+2; z;} else if (x < y) 1 + w;) == w + 1" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("(if (x > y) { z+2; z;} else if (x > y) w;) == null" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("if (x < y) { z+2; z;} else if (x < y) {w + 2; w;} == z" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("if (x > y) { z+2; z;} else if (x < y) {w + 2; w;} == w" ,T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)), + test_xyzw("if (x > y) { z+2; z;} else if (x > y) {w + 2; w;} == null",T(1.0),T(2.0),T(3.0),T(4.0),T(1.0)) + }; static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_xyzw); @@ -1944,24 +1956,24 @@ inline bool run_test01() { const std::string expr_list[] = - { - "((v[1] + x) == (x + v[1]))", - "((v[0] += x) == x)", - "((v[0] += x + y) == (x + y))", - "((v[0] -= x) == -x)", - "((v[0] -= (x + y)) == -(x + y))", - "((v[1] + v[2]) == (v[3 - 1] + v[2 * 1/2]))", - "(v[v[1]] == v[1])", - "(v[1] += v[1]) == v[1 + 1]", - "((v[i[1]] + x) == (x + v[i[1]]))", - "((v[i[0]] += x) == x)", - "((v[i[0]] += x + y) == (x + y))", - "((v[i[0]] -= x) == -x)", - "((v[i[0]] -= (x + y)) == -(x + y))", - "((v[i[1]] + v[2]) == (v[i[3] - i[1]] + v[i[2] * 1/2]))", - "(v[v[i[1]]] == v[i[1]])", - "(v[i[1]] += v[i[1]]) == v[i[1] + 1]" - }; + { + "((v[1] + x) == (x + v[1]))", + "((v[0] += x) == x)", + "((v[0] += x + y) == (x + y))", + "((v[0] -= x) == -x)", + "((v[0] -= (x + y)) == -(x + y))", + "((v[1] + v[2]) == (v[3 - 1] + v[2 * 1/2]))", + "(v[v[1]] == v[1])", + "(v[1] += v[1]) == v[1 + 1]", + "((v[i[1]] + x) == (x + v[i[1]]))", + "((v[i[0]] += x) == x)", + "((v[i[0]] += x + y) == (x + y))", + "((v[i[0]] -= x) == -x)", + "((v[i[0]] -= (x + y)) == -(x + y))", + "((v[i[1]] + v[2]) == (v[i[3] - i[1]] + v[i[2] * 1/2]))", + "(v[v[i[1]]] == v[i[1]])", + "(v[i[1]] += v[i[1]]) == v[i[1] + 1]" + }; const std::size_t expr_list_size = sizeof(expr_list) / sizeof(std::string); @@ -2091,11 +2103,11 @@ template struct test_ab { test_ab(const std::string& e, const std::string& v0, const std::string& v1, const T& r) - : expr(e), - a(v0), - b(v1), - c("ccc"), - result(r) + : expr(e) + , a(v0) + , b(v1) + , c("ccc") + , result(r) {} std::string expr; @@ -2106,613 +2118,712 @@ struct test_ab }; template -inline bool run_test02() +bool run_test02() { static const test_ab test_list[] = - { - test_ab("'aaa' == 'aaa'" ,"","",T(1.0)), - test_ab("'aaa' < 'bbb'" ,"","",T(1.0)), - test_ab("'aaa' <= 'bbb'" ,"","",T(1.0)), - test_ab("'bbb' > 'aaa'" ,"","",T(1.0)), - test_ab("'bbb' >= 'aaa'" ,"","",T(1.0)), - test_ab("'aaa' != 'aaa'" ,"","",T(0.0)), - test_ab("'aaa' != 'bbb'" ,"","",T(1.0)), - test_ab("'aaa' + '123' == 'aaa123'" ,"","",T(1.0)), - test_ab("'aaa123' == 'aaa' + '123'" ,"","",T(1.0)), - test_ab("('aaa' + '123') == 'aaa123'" ,"","",T(1.0)), - test_ab("'aaa123' == ('aaa' + '123')" ,"","",T(1.0)), - test_ab("'aaa' in 'aaa123'" ,"","",T(1.0)), - test_ab("'123' in 'aaa123'" ,"","",T(1.0)), - test_ab("'a123b' like '*123*'" ,"","",T(1.0)), - test_ab("'a123b' like '*123?'" ,"","",T(1.0)), - test_ab("'1XYZ2' ilike '*xyz*'" ,"","",T(1.0)), - test_ab("'1XYZ2' ilike '*xyz?'" ,"","",T(1.0)), - test_ab("inrange('aaa','bbb','ccc')" ,"","",T(1.0)), - test_ab("a == b" ,"aaa","aaa",T(1.0)), - test_ab("a != b" ,"aaa","bbb",T(1.0)), - test_ab("a < b" ,"aaa","bbb",T(1.0)), - test_ab("a <= b" ,"aaa","bbb",T(1.0)), - test_ab("b > a" ,"aaa","bbb",T(1.0)), - test_ab("b >= a" ,"aaa","bbb",T(1.0)), - test_ab("a in b" ,"aaa","aaa123",T(1.0)), - test_ab("a in b" ,"123","aaa123",T(1.0)), - test_ab("a == 'aaa'" ,"aaa","aaa",T(1.0)), - test_ab("'aaa' == a" ,"aaa","aaa",T(1.0)), - test_ab("a != 'bbb'" ,"aaa","bbb",T(1.0)), - test_ab("'bbb' != a" ,"aaa","bbb",T(1.0)), - test_ab("a < 'bbb'" ,"aaa","bbb",T(1.0)), - test_ab("a <= 'bbb'" ,"aaa","bbb",T(1.0)), - test_ab("'bbb' > a" ,"aaa","bbb",T(1.0)), - test_ab("'bbb' >= a" ,"aaa","bbb",T(1.0)), - test_ab("a in 'aaa123'" ,"aaa","aaa123",T(1.0)), - test_ab("a in 'aaa123'" ,"123","aaa123",T(1.0)), - test_ab("'aaa' in b" ,"aaa","aaa123",T(1.0)), - test_ab("'123' in b" ,"aaa","aaa123",T(1.0)), - test_ab("(a < b) or (a == b)" ,"aaa","bbb",T(1.0)), - test_ab("(a == b) or (a < b)" ,"aaa","bbb",T(1.0)), - test_ab("(b > a) or (b == a)" ,"aaa","bbb",T(1.0)), - test_ab("(b == a) or (b > a)" ,"aaa","bbb",T(1.0)), - test_ab("(a < b) and (b > a)" ,"aaa","bbb",T(1.0)), - test_ab("a like '*123*'" ,"a123b","",T(1.0)), - test_ab("a like '*123?'" ,"a123b","",T(1.0)), - test_ab("'a123b' like b" ,"a123b","*123*",T(1.0)), - test_ab("'a123b' like b" ,"a123b","*123?",T(1.0)), - test_ab("a ilike '*xyz*'" ,"1XYZ2","",T(1.0)), - test_ab("a ilike '*xyz?'" ,"1XYZ2","",T(1.0)), - test_ab("'1XYZ2' ilike b" ,"","*xyz*",T(1.0)), - test_ab("'1XYZ2' ilike b" ,"","*xyz?",T(1.0)), - test_ab("inrange(a,'bbb',c)" ,"aaa","bbb",T(1.0)), - test_ab("inrange('aaa',b,'ccc')" ,"aaa","bbb",T(1.0)), - test_ab("inrange(a,b,c)" ,"aaa","bbb",T(1.0)), - test_ab("inrange(a,b,'ccc')" ,"aaa","bbb",T(1.0)), - test_ab("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)), - test_ab("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)), - test_ab("(a < b ? a : b) == a" ,"aaa","bbb",T(1.0)), - test_ab("(a > b ? a : b) == b" ,"aaa","bbb",T(1.0)), - test_ab("(a == (a + '1') ? a : b) == b" ,"aaa","bbb",T(1.0)), - test_ab("((a + '2') != a ? a : b) == a" ,"aaa","bbb",T(1.0)), - test_ab("(a < b ? a + '1' : b) == 'aaa1'","aaa","bbb",T(1.0)), - test_ab("(a > b ? a : b + '2') == 'bbb2'","aaa","bbb",T(1.0)), - test_ab("b == (a == (a + '1') ? a : b)" ,"aaa","bbb",T(1.0)), - test_ab("a == (a != (a + '2') ? a : b)" ,"aaa","bbb",T(1.0)), - test_ab("'aaa1' == (a < b ? a + '1' : b)","aaa","bbb",T(1.0)), - test_ab("'bbb2' == (a > b ? a : b + '2')","aaa","bbb",T(1.0)), - test_ab("(a < b ? a[1:2] : b) == '23'" ,"1234","67890",T(1.0)), - test_ab("(a > b ? a : b[0:3]) == '6789'" ,"1234","67890",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x < y ? x : y) == x }}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x > y ? x : y) == y }}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x == (x + '1') ? x : y) == y }}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{((x + '2') != x ? x : y) == x }}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x < y ? x + '1' : y) == 'xxx1'}}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x > y ? x : y + '2') == 'yyy2'}}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{y == (x == (x + '1') ? x : y) }}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{x == (x != (x + '2') ? x : y) }}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{'xxx1' == (x < y ? x + '1' : y)}}","","",T(1.0)), - test_ab("~{var x := 'xxx'; var y := 'yyy';~{'yyy2' == (x > y ? x : y + '2')}}","","",T(1.0)), - test_ab("'01234567890123456789'[0:9] == '0123456789' ","","",T(1.0)), - test_ab("'01234567890123456789'[0:9] == '0123456789'[:] ","","",T(1.0)), - test_ab("'01234567890123456789'[0:9] == '0123456789'[0:]","","",T(1.0)), - test_ab("'01234567890123456789'[0:9] == '0123456789'[:9]","","",T(1.0)), - test_ab("'01234567890123456789'[:9] == '0123456789'[:9]","","",T(1.0)), - test_ab("'01234567890123456789'[10:] == '0123456789'[:] ","","",T(1.0)), - test_ab("'01234567890123456789'[0:9] != '123456789' ","","",T(1.0)), - test_ab("'01234567890123456789'[0:9] != '123456789'[:] ","","",T(1.0)), - test_ab("'01234567890123456789'[0:9] != '123456789'[0:] ","","",T(1.0)), - test_ab("'01234567890123456789'[0:9] != '123456789'[:8] ","","",T(1.0)), - test_ab("'01234567890123456789'[:9] != '123456789'[:8] ","","",T(1.0)), - test_ab("'01234567890123456789'[10:] != '123456789'[:] ","","",T(1.0)), - test_ab("'01234567890123456789'[2*6:10+6] == '23456' ","","",T(1.0)), - test_ab("'0123456789' == '01234567890123456789'[0:9]","","",T(1.0)), - test_ab("'0123456789'[:] == '01234567890123456789'[0:9]","","",T(1.0)), - test_ab("'0123456789'[0:] == '01234567890123456789'[0:9]","","",T(1.0)), - test_ab("'0123456789'[:9] == '01234567890123456789'[0:9]","","",T(1.0)), - test_ab("'0123456789'[:9] == '01234567890123456789'[:9] ","","",T(1.0)), - test_ab("'0123456789'[:] == '01234567890123456789'[10:]","","",T(1.0)), - test_ab("'0123456789'[3:3] == '3'[:] ","","",T(1.0)), - test_ab("'0123456789'[3:3] == '3'[0:0] ","","",T(1.0)), - test_ab("'123456789' != '01234567890123456789'[0:9]","","",T(1.0)), - test_ab("'123456789'[:] != '01234567890123456789'[0:9]","","",T(1.0)), - test_ab("'123456789'[0:] != '01234567890123456789'[0:9]","","",T(1.0)), - test_ab("'123456789'[:8] != '01234567890123456789'[0:9]","","",T(1.0)), - test_ab("'123456789'[:8] != '01234567890123456789'[:9] ","","",T(1.0)), - test_ab("'123456789'[:] != '01234567890123456789'[10:]","","",T(1.0)), - test_ab("'23456' == '01234567890123456789'[2*6:10+6] ","","",T(1.0)), - test_ab("'01234567890123456789'[r0: 6] == '23456' ","","",T(1.0)), - test_ab("'01234567890123456789'[2: r1] == '23456' ","","",T(1.0)), - test_ab("'01234567890123456789'[r0:3*2] == '23456' ","","",T(1.0)), - test_ab("'01234567890123456789'[1+1:r1] == '23456' ","","",T(1.0)), - test_ab("'01234567890123456789'[r0: ] == '234567890123456789' ","","",T(1.0)), - test_ab("'01234567890123456789'[: r1] == '0123456' ","","",T(1.0)), - test_ab("'01234567890123456789'[r0:r1] == '23456' ","","",T(1.0)), - test_ab("'01234567890123456789'[r0:r1+2] == '2345678' ","","",T(1.0)), - test_ab("'01234567890123456789'[r0+2:r1] == '456' ","","",T(1.0)), - test_ab("'01234567890123456789'[r1-r0:] == '4567890123456789' ","","",T(1.0)), - test_ab("'01234567890123456789'[:r1-r0] == '01234' ","","",T(1.0)), - test_ab("'23456' == '01234567890123456789'[r0: 6] ","","",T(1.0)), - test_ab("'23456' == '01234567890123456789'[2: r1] ","","",T(1.0)), - test_ab("'23456' == '01234567890123456789'[r0:3*2] ","","",T(1.0)), - test_ab("'23456' == '01234567890123456789'[1+1:r1] ","","",T(1.0)), - test_ab("'234567890123456789' == '01234567890123456789'[r0: ] ","","",T(1.0)), - test_ab("'0123456' == '01234567890123456789'[: r1] ","","",T(1.0)), - test_ab("'23456' == '01234567890123456789'[r0:r1] ","","",T(1.0)), - test_ab("'2345678' == '01234567890123456789'[r0:r1+2] ","","",T(1.0)), - test_ab("'456' == '01234567890123456789'[r0+2:r1] ","","",T(1.0)), - test_ab("'4567890123456789' == '01234567890123456789'[r1-r0:] ","","",T(1.0)), - test_ab("'01234' == '01234567890123456789'[:r1-r0] ","","",T(1.0)), - test_ab("a[r0: 6] == '23456' ","01234567890123456789","",T(1.0)), - test_ab("a[2: r1] == '23456' ","01234567890123456789","",T(1.0)), - test_ab("a[r0:3*2] == '23456' ","01234567890123456789","",T(1.0)), - test_ab("a[1+1:r1] == '23456' ","01234567890123456789","",T(1.0)), - test_ab("a[r0: ] == '234567890123456789' ","01234567890123456789","",T(1.0)), - test_ab("a[: r1] == '0123456' ","01234567890123456789","",T(1.0)), - test_ab("a[r0:r1] == '23456' ","01234567890123456789","",T(1.0)), - test_ab("a[r0:r1+2] == '2345678' ","01234567890123456789","",T(1.0)), - test_ab("a[r0+2:r1] == '456' ","01234567890123456789","",T(1.0)), - test_ab("a[r1-r0:] == '4567890123456789' ","01234567890123456789","",T(1.0)), - test_ab("a[:r1-r0] == '01234' ","01234567890123456789","",T(1.0)), - test_ab("'23456' == a[r0: 6] ","01234567890123456789","",T(1.0)), - test_ab("'23456' == a[2: r1] ","01234567890123456789","",T(1.0)), - test_ab("'23456' == a[r0:3*2] ","01234567890123456789","",T(1.0)), - test_ab("'23456' == a[1+1:r1] ","01234567890123456789","",T(1.0)), - test_ab("'234567890123456789' == a[r0: ] ","01234567890123456789","",T(1.0)), - test_ab("'0123456' == a[: r1] ","01234567890123456789","",T(1.0)), - test_ab("'23456' == a[r0:r1] ","01234567890123456789","",T(1.0)), - test_ab("'2345678' == a[r0:r1+2] ","01234567890123456789","",T(1.0)), - test_ab("'456' == a[r0+2:r1] ","01234567890123456789","",T(1.0)), - test_ab("'4567890123456789' == a[r1-r0:] ","01234567890123456789","",T(1.0)), - test_ab("'01234' == a[:r1-r0] ","01234567890123456789","",T(1.0)), - test_ab("a[r0: 6] == b ","01234567890123456789","23456",T(1.0)), - test_ab("a[2: r1] == b ","01234567890123456789","23456",T(1.0)), - test_ab("a[r0:3*2] == b ","01234567890123456789","23456",T(1.0)), - test_ab("a[1+1:r1] == b ","01234567890123456789","23456",T(1.0)), - test_ab("a[r0: ] == b ","01234567890123456789","234567890123456789",T(1.0)), - test_ab("a[: r1] == b ","01234567890123456789","0123456",T(1.0)), - test_ab("a[r0:r1] == b ","01234567890123456789","23456",T(1.0)), - test_ab("a[r0:r1+2] == b ","01234567890123456789","2345678",T(1.0)), - test_ab("a[r0+2:r1] == b ","01234567890123456789","456",T(1.0)), - test_ab("a[r1-r0:] == b ","01234567890123456789","4567890123456789",T(1.0)), - test_ab("a[:r1-r0] == b ","01234567890123456789","01234",T(1.0)), - test_ab("b == a[r0: 6] ","01234567890123456789","23456",T(1.0)), - test_ab("b == a[2: r1] ","01234567890123456789","23456",T(1.0)), - test_ab("b == a[r0:3*2] ","01234567890123456789","23456",T(1.0)), - test_ab("b == a[1+1:r1] ","01234567890123456789","23456",T(1.0)), - test_ab("b == a[r0: ] ","01234567890123456789","234567890123456789",T(1.0)), - test_ab("b == a[: r1] ","01234567890123456789","0123456",T(1.0)), - test_ab("b == a[r0:r1] ","01234567890123456789","23456",T(1.0)), - test_ab("b == a[r0:r1+2] ","01234567890123456789","2345678",T(1.0)), - test_ab("b == a[r0+2:r1] ","01234567890123456789","456",T(1.0)), - test_ab("b == a[r1-r0:] ","01234567890123456789","4567890123456789",T(1.0)), - test_ab("b == a[:r1-r0] ","01234567890123456789","01234",T(1.0)), - test_ab("'01234567890123456789'[0:9] == a ","0123456789","",T(1.0)), - test_ab("'01234567890123456789'[0:9] == a[:] ","0123456789","",T(1.0)), - test_ab("'01234567890123456789'[0:9] == a[0:] ","0123456789","",T(1.0)), - test_ab("'01234567890123456789'[0:9] == a[:9] ","0123456789","",T(1.0)), - test_ab("'01234567890123456789'[:9] == a[:9] ","0123456789","",T(1.0)), - test_ab("'01234567890123456789'[10:] == a[:] ","0123456789","",T(1.0)), - test_ab("'01234567890123456789'[0:9] != a ","123456789" ,"",T(1.0)), - test_ab("'01234567890123456789'[0:9] != a[:] ","123456789" ,"",T(1.0)), - test_ab("'01234567890123456789'[0:9] != a[0:] ","123456789" ,"",T(1.0)), - test_ab("'01234567890123456789'[0:9] != a[:8] ","123456789" ,"",T(1.0)), - test_ab("'01234567890123456789'[:9] != a[:8] ","123456789" ,"",T(1.0)), - test_ab("'01234567890123456789'[10:] != a[:] ","123456789" ,"",T(1.0)), - test_ab("'01234567890123456789'[2*6:10+6] == a","23456" ,"",T(1.0)), - test_ab("'23456' == a[:] ","23456" ,"",T(1.0)), - test_ab("a == '01234567890123456789'[0:9] ","0123456789","",T(1.0)), - test_ab("a[:] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)), - test_ab("a[0:] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)), - test_ab("a[:9] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)), - test_ab("a[:9] == '01234567890123456789'[:9] ","0123456789","",T(1.0)), - test_ab("a[:] == '01234567890123456789'[10:] ","0123456789","",T(1.0)), - test_ab("a != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)), - test_ab("a[:] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)), - test_ab("a[0:] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)), - test_ab("a[:8] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)), - test_ab("a[:8] != '01234567890123456789'[:9] ","123456789" ,"",T(1.0)), - test_ab("a[:] != '01234567890123456789'[10:] ","123456789" ,"",T(1.0)), - test_ab("a == '01234567890123456789'[2*6:10+6]","23456" ,"",T(1.0)), - test_ab("a[:] == '23456' ","23456" ,"",T(1.0)), - test_ab("a[0:9] == b ","01234567890123456789","0123456789",T(1.0)), - test_ab("a[0:9] == b[:] ","01234567890123456789","0123456789",T(1.0)), - test_ab("a[0:9] == b[0:] ","01234567890123456789","0123456789",T(1.0)), - test_ab("a[0:9] == b[:9] ","01234567890123456789","0123456789",T(1.0)), - test_ab("a[:9] == b[:9] ","01234567890123456789","0123456789",T(1.0)), - test_ab("a[10:] == b[:] ","01234567890123456789","0123456789",T(1.0)), - test_ab("a[0:9] != b ","01234567890123456789","123456789" ,T(1.0)), - test_ab("a[0:9] != b[:] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("a[0:9] != b[0:] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("a[0:9] != b[:8] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("a[:9] != b[:8] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("a[10:] != b[:] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("a[2*6:10+6] == b ","01234567890123456789","23456" ,T(1.0)), - test_ab("b == a[0:9] ","01234567890123456789","0123456789",T(1.0)), - test_ab("b[:] == a[0:9] ","01234567890123456789","0123456789",T(1.0)), - test_ab("b[0:] == a[0:9] ","01234567890123456789","0123456789",T(1.0)), - test_ab("b[:9] == a[0:9] ","01234567890123456789","0123456789",T(1.0)), - test_ab("b[:9] == a[:9] ","01234567890123456789","0123456789",T(1.0)), - test_ab("b[:] == a[10:] ","01234567890123456789","0123456789",T(1.0)), - test_ab("b != a[0:9] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("b[:] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("b[0:] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("b[:8] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("b[:8] != a[:9] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("b[:] != a[10:] ","01234567890123456789","123456789" ,T(1.0)), - test_ab("b == a[2*6:10+6] ","01234567890123456789","23456" ,T(1.0)), - test_ab("a[2:6] == b" ,"0123456789","23456" ,T(1.0)), - test_ab("a == b[2:6]" ,"23456","0123456789" ,T(1.0)), - test_ab("a[1+1:2*3] == b" ,"0123456789","23456" ,T(1.0)), - test_ab("a == b[4/2:sqrt(36)]","23456","0123456789" ,T(1.0)), - test_ab("a[0:6] == b" ,"0123456789","0123456",T(1.0)), - test_ab("a[:6] == b" ,"0123456789","0123456",T(1.0)), - test_ab("a[4/2-2:2+4] == b" ,"0123456789","0123456",T(1.0)), - test_ab("a[:12/2] == b" ,"0123456789","0123456",T(1.0)), - test_ab("a[0:] == b" ,"0123456","0123456" ,T(1.0)), - test_ab("a[:] == b" ,"0123456","0123456" ,T(1.0)), - test_ab("a == b[0:6]" ,"0123456","0123456789",T(1.0)), - test_ab("a == b[:6]" ,"0123456","0123456789",T(1.0)), - test_ab("a == b[4/2-2:2+4]" ,"0123456","0123456789",T(1.0)), - test_ab("a == b[:12/2]" ,"0123456","0123456789",T(1.0)), - test_ab("a == b[0:]" ,"0123456","0123456" ,T(1.0)), - test_ab("a == b[:]" ,"0123456","0123456" ,T(1.0)), - test_ab("a[:9] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)), - test_ab("a[0:9] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)), - test_ab("a[0:] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)), - test_ab("a[:] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)), - test_ab("a[:] == b[10:]" ,"0123456789","01234567890123456789",T(1.0)), - test_ab("'!@#$%^&*([{}])-=' != ')]}{[(*&^%$#@!'","","",T(1.0)), - test_ab("('!@#$%^&*([{}])-=') != (')]}{[(*&^%$#@!')","","",T(1.0)), - test_ab("{[('a')]} == [{('a')}]","","",T(1.0)), - test_ab("{[('!@#$%^&*([{}])-=')]} != [{(')]}{[(*&^%$#@!')}]","","",T(1.0)), - test_ab("'!@#$%^&*([{}])-=' == '!@#$%^&*([{}])-='","","",T(1.0)), - test_ab("('!@#$%^&*([{}])-=') == ('!@#$%^&*([{}])-=')","","",T(1.0)), - test_ab("{[('!@#$%^&*([{}])-=')]} == [{('!@#$%^&*([{}])-=')}]","","",T(1.0)), - test_ab("'1234\\\\abc\nxyz\r890\tqaz\\'567' == a","1234\\abc\nxyz\r890\tqaz'567","",T(1.0)), - test_ab("a == '1234\\\\abc\nxyz\r890\tqaz\\'567'","1234\\abc\nxyz\r890\tqaz'567","",T(1.0)), - test_ab("'123'[] == 3" ,"","" ,T(1.0)), - test_ab("3 == '123'[]" ,"","" ,T(1.0)), - test_ab("'123'[] + '1234'[] == 7" ,"","" ,T(1.0)), - test_ab("abs('123'[] - '1234'[]) == 1" ,"","" ,T(1.0)), - test_ab("'1234'[] == a[]" ,"1234","" ,T(1.0)), - test_ab("'123'[] + a[] == 7" ,"1234","" ,T(1.0)), - test_ab("abs(a[] - '12345'[]) == 1" ,"1234","" ,T(1.0)), - test_ab("'1234'[] + '12345'[] == a[] + b[]" ,"1234","12345" ,T(1.0)), - test_ab("abs('123'[] -'1234'[]) == abs(a[] - b[])" ,"1234","12345",T(1.0)), - test_ab("(a + b) == 'abc123' ","abc","123" ,T(1.0)), - test_ab("(a + '123') == 'abc123' ","abc","123" ,T(1.0)), - test_ab("('abc' + b) == 'abc123' ","abc","123" ,T(1.0)), - test_ab("(a + '1') == 'abc1' ","abc","123" ,T(1.0)), - test_ab("('a' + b) == 'a123' ","abc","123" ,T(1.0)), - test_ab("(a[2:7] + b) == 'cdefgh0123' ","abcdefghij","0123",T(1.0)), - test_ab("(a + b[2:7]) == 'abc234567' ","abc","0123456789" ,T(1.0)), - test_ab("(a[2:7] + '0123') == 'cdefgh0123' ","abcdefghij","0123",T(1.0)), - test_ab("('abc' + b[2:7]) == 'abc234567' ","abc","0123456789" ,T(1.0)), - test_ab("(a[2:2] + b[3:3]) == 'c3' ","abc","0123456789" ,T(1.0)), - test_ab("(a[3:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)), - test_ab("('abc' + b[:7]) == 'abc01234567' ","abc","0123456789" ,T(1.0)), - test_ab("a + '123' == 'abc'+ b ","abc" , "123" , T(1.0)), - test_ab("a[0:2] + '123' == 'abc' + b[0:2] ","abcXYZ", "123XYZ", T(1.0)), - test_ab("a[ :2] + '123' == 'abc' + b[ :2] ","abcXYZ", "123XYZ", T(1.0)), - test_ab("a[3: ] + '123' == 'abc' + b[3: ]","XYZabc", "XYZ123", T(1.0)), - test_ab("a[3:a[] - 1] + '123' == 'abc' + b[3:b[] - 1]","XYZabc", "XYZ123", T(1.0)), - test_ab("(a[r0:r2] + b) == 'cdefgh0123' ","abcdefghij","0123",T(1.0)), - test_ab("(a + b[r0:r2]) == 'abc234567' ","abc","0123456789" ,T(1.0)), - test_ab("(a[r0:r2] + '0123') == 'cdefgh0123' ","abcdefghij","0123",T(1.0)), - test_ab("('abc' + b[r0:r2]) == 'abc234567' ","abc","0123456789" ,T(1.0)), - test_ab("(a[r0:r0] + b[r3:r3]) == 'c3' ","abc","0123456789" ,T(1.0)), - test_ab("(a[r3:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)), - test_ab("('abc' + b[:r2]) == 'abc01234567' ","abc","0123456789" ,T(1.0)), - test_ab("a[0:r0] + '123' == 'abc' + b[0:r0] ","abcXYZ", "123XYZ", T(1.0)), - test_ab("a[ :r0] + '123' == 'abc' + b[ :r0] ","abcXYZ", "123XYZ", T(1.0)), - test_ab("a[r3: ] + '123' == 'abc' + b[r3: ]","XYZabc", "XYZ123", T(1.0)), - test_ab("a[r3:a[] - 1] + '123' == 'abc' + b[r3:b[] - 1]","XYZabc", "XYZ123", T(1.0)), - test_ab("(a[r0:r0] + b[r3:r0+1]) == 'c3' ","abc","0123456789" ,T(1.0)), - test_ab("(a[r0+1:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)), - test_ab("a[r0+1: ] + '123' == 'abc' + b[r0+1: ]","XYZabc", "XYZ123", T(1.0)), - test_ab("a[r0+1:a[] - 1] + '123' == 'abc' + b[r0+1:b[] - 1]","XYZabc", "XYZ123", T(1.0)), - test_ab("(a + b)[ :13] == 'abcdefghij0123' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a + b)[ 6: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a + b)[ 2:3r1-1] == 'cdefghij01234567' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a[2:7] + b[2:7]) == 'cdefgh234567' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a[2:7] + b[2:7])[3:8] == 'fgh234' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a + b)[r0 - 2: r1 + r2] == 'abcdefghij0123' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a + b)[r0*r3:] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a + b)[3r0: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a + b)[2r3: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a + b)[2:3r1 - 1] == 'cdefghij01234567' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a[r0:7] + b[r0:r2])== 'cdefgh234567' ", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a[r1 / r3:7] + b[r0:r2])[3:r2 + 1] == 'fgh234'", "abcdefghij", "0123456789" ,T(1.0)), - test_ab("(a += b) == 'abc123' ", "abc","123" ,T(1.0)), - test_ab("(a += '123') == 'abc123' ", "abc","123" ,T(1.0)), - test_ab("(a += b[3:5]) == 'abc123' ", "abc","XXX123XXX" ,T(1.0)), - test_ab("(a += 'XXX123XXX'[3:5]) == 'abc123' ", "abc","123" ,T(1.0)), - test_ab("(a += b)[:] == 'abc123' ", "abc","123" ,T(1.0)), - test_ab("(a += '123')[:] == 'abc123' ", "abc","123" ,T(1.0)), - test_ab("(a += b[3:5])[:] == 'abc123' ", "abc","XXX123XXX" ,T(1.0)), - test_ab("(a += 'XXX123XXX'[3:5])[:] == 'abc123' ", "abc","123" ,T(1.0)), - test_ab("(a += b[r1/2:r1-1]) == 'abc123' ", "abc","XXX123XXX" ,T(1.0)), - test_ab("(a += 'XXX123XXX'[r0+1:r1-1]) == 'abc123' ", "abc","123" ,T(1.0)), - test_ab("(a += b)[] == 6 ", "abc","123" ,T(1.0)), - test_ab("(a += '123')[] == 6 ", "abc","123" ,T(1.0)), - test_ab("(a += b[3:5])[] == 6 ", "abc","XXX123XXX" ,T(1.0)), - test_ab("(a += b[r0+1:r1-1])[] == 6 ", "abc","XXX123XXX" ,T(1.0)), - test_ab("(a + b)[:][] == 6 ","abc","123" ,T(1.0)), - test_ab("(a + b)[:][:][] == 6 ","abc","123" ,T(1.0)), - test_ab("(a + b)[:][:][:][] == 6 ","abc","123" ,T(1.0)), - test_ab("(a + b)[:][:][:][:][] == 6 ","abc","123" ,T(1.0)), - test_ab("(a + b)[:][:][:][:][:][] == 6 ","abc","123" ,T(1.0)), - test_ab("(a + b)[:][:][:][:][:][:][] == 6 ","abc","123" ,T(1.0)), - test_ab("(a + b)[:][:][:][:][:][:][:][]== 6 ","abc","123" ,T(1.0)), - test_ab("(a + b)[0:5] == 'abc123' ","abc","123" ,T(1.0)), - test_ab("(a + b)[0:5][1:4] == 'bc12' ","abc","123" ,T(1.0)), - test_ab("(a + b)[0:5][1:4][1:2] == 'c1' ","abc","123" ,T(1.0)), - test_ab("(a + b)[0:5][1:4][1:2][0:0] == 'c' ","abc","123" ,T(1.0)), - test_ab("(a + b)[0:5][] == 6 ","abc","123" ,T(1.0)), - test_ab("(a + b)[0:5][1:4][] == 4 ","abc","123" ,T(1.0)), - test_ab("(a + b)[0:5][1:4][1:2][] == 2 ","abc","123" ,T(1.0)), - test_ab("(a + b)[0:5][1:4][1:2][0:0][] == 1 ","abc","123" ,T(1.0)), - test_ab("(a[ : ] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[0: ] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[ :9] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[3:7] := b); (a == '012ABCDE89');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[2:8] := b); (a == '01ABCDEFG9');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[1:9] := b); (a == '0ABCDEFGHI');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[0:0] := b); (a == 'A123456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[1:1] := b); (a == '0A23456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[2:2] := b); (a == '01A3456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[3:3] := b); (a == '012A456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[4:4] := b); (a == '0123A56789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[5:5] := b); (a == '01234A6789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[6:6] := b); (a == '012345A789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[7:7] := b); (a == '0123456A89');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[8:8] := b); (a == '01234567A9');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[9:9] := b); (a == '012345678A');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[0:1] := b); (a == 'AB23456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[1:2] := b); (a == '0AB3456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[2:3] := b); (a == '01AB456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[3:4] := b); (a == '012AB56789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[4:5] := b); (a == '0123AB6789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[5:6] := b); (a == '01234AB789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[6:7] := b); (a == '012345AB89');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[7:8] := b); (a == '0123456AB9');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[8:9] := b); (a == '01234567AB');", "0123456789","ABCDEFGHIJ" ,T(1.0)), - test_ab("(a[ : ] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[0: ] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[ :9] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[3:7] := b[3:b[] - 3]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[2:8] := b[3:b[] - 3]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[1:9] := b[3:b[] - 3]); (a == '0ABCDEFGHI');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[0:0] := b[3:b[] - 3]); (a == 'A123456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[1:1] := b[3:b[] - 3]); (a == '0A23456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[2:2] := b[3:b[] - 3]); (a == '01A3456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[3:3] := b[3:b[] - 3]); (a == '012A456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[4:4] := b[3:b[] - 3]); (a == '0123A56789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[5:5] := b[3:b[] - 3]); (a == '01234A6789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[6:6] := b[3:b[] - 3]); (a == '012345A789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[7:7] := b[3:b[] - 3]); (a == '0123456A89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[8:8] := b[3:b[] - 3]); (a == '01234567A9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[9:9] := b[3:b[] - 3]); (a == '012345678A');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[0:1] := b[3:b[] - 3]); (a == 'AB23456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[1:2] := b[3:b[] - 3]); (a == '0AB3456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[2:3] := b[3:b[] - 3]); (a == '01AB456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[3:4] := b[3:b[] - 3]); (a == '012AB56789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[4:5] := b[3:b[] - 3]); (a == '0123AB6789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[5:6] := b[3:b[] - 3]); (a == '01234AB789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[6:7] := b[3:b[] - 3]); (a == '012345AB89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[7:8] := b[3:b[] - 3]); (a == '0123456AB9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[8:9] := b[3:b[] - 3]); (a == '01234567AB');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[0:9] := b); (a == 'A123456789');", "0123456789","A" ,T(1.0)), - test_ab("(a[0:9] := b); (a == 'AB23456789');", "0123456789","AB" ,T(1.0)), - test_ab("(a[0:9] := b); (a == 'ABC3456789');", "0123456789","ABC" ,T(1.0)), - test_ab("(a[0:9] := b); (a == 'ABCD456789');", "0123456789","ABCD" ,T(1.0)), - test_ab("(a[0:9] := b); (a == 'ABCDE56789');", "0123456789","ABCDE" ,T(1.0)), - test_ab("(a[0:9] := b); (a == 'ABCDEF6789');", "0123456789","ABCDEF" ,T(1.0)), - test_ab("(a[0:9] := b); (a == 'ABCDEFG789');", "0123456789","ABCDEFG" ,T(1.0)), - test_ab("(a[0:9] := b); (a == 'ABCDEFGH89');", "0123456789","ABCDEFGH" ,T(1.0)), - test_ab("(a[0:9] := b); (a == 'ABCDEFGHI9');", "0123456789","ABCDEFGHI" ,T(1.0)), - test_ab("(a[3:9] := b); (a == '012A456789');", "0123456789","A" ,T(1.0)), - test_ab("(a[3:9] := b); (a == '012AB56789');", "0123456789","AB" ,T(1.0)), - test_ab("(a[3:9] := b); (a == '012ABC6789');", "0123456789","ABC" ,T(1.0)), - test_ab("(a[3:9] := b); (a == '012ABCD789');", "0123456789","ABCD" ,T(1.0)), - test_ab("(a[3:9] := b); (a == '012ABCDE89');", "0123456789","ABCDE" ,T(1.0)), - test_ab("(a[3:9] := b); (a == '012ABCDEF9');", "0123456789","ABCDEF" ,T(1.0)), - test_ab("(a[r1 / r0:r2] := b[3:b[] - r3]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("(a[r0:r2 + 1] := b[r3:b[] - r3]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), - test_ab("'\\0x30\\0x31\\0x32\\0x33\\0x34\\0x35\\0x36\\0x37\\0x38\\0x39' == '0123456789'","","",T(1.0)), - test_ab("'abc\\0x30\\0x31\\0x32\\0x33xyz' == 'abc0123xyz'" ,"","",T(1.0)), - test_ab("'\\0x30\\n\\0x31\\n\\0x32\\n\\0x33' == '0\\n1\\n2\\n3'" ,"","",T(1.0)), - test_ab("('\\0x30' + '') == '0'" ,"","",T(1.0)), - test_ab("('\\0x30' + '\\0x31\\0x32') == '012'" ,"","",T(1.0)), - test_ab("('\\0x30' + '\\0x31\\0x32' + '\\0x33\\0x34\\0x35') == '012345'" ,"","",T(1.0)), - test_ab("'a\\'\\\\b' == a" ,"a'\\b","",T(1.0)), - test_ab("'a\\\\\\'b' == a" ,"a\\'b","",T(1.0)), - test_ab("'a\\'\\\\\\\\b' == a" ,"a'\\\\b","",T(1.0)), - test_ab("'a\\0x30\\'\\0x31\\\\\\0x32b' == a" ,"a0'1\\2b","",T(1.0)), - - test_ab("var x := 3; x > 2 and 'abc' like '*bc'" ,"","",T(1.0)), - test_ab("var x := 3; x > 2 and 'abc' ilike '*Bc'" ,"","",T(1.0)), - test_ab("var x := 3; x > 2 and 'abc' in '123abc123'","","",T(1.0)), - - test_ab("var x := 3; var s := 'abc'; x > 2 and s like '*bc'" ,"","",T(1.0)), - test_ab("var x := 3; var s := 'abc'; x > 2 and s ilike '*Bc'" ,"","",T(1.0)), - test_ab("var x := 3; var s := 'abc'; x > 2 and s in '123abc123'","","",T(1.0)), - - test_ab("var x := 3; var s := 'abc'; var t := '*bc'; x > 2 and s like t" ,"","",T(1.0)), - test_ab("var x := 3; var s := 'abc'; var t := '*Bc'; x > 2 and s ilike t" ,"","",T(1.0)), - test_ab("var x := 3; var s := 'abc'; var t := '123abc123'; x > 2 and s in t","","",T(1.0)), - - test_ab("var x := 3; x > 2 and a like '*bc'" ,"abc","",T(1.0)), - test_ab("var x := 3; x > 2 and a ilike '*Bc'" ,"abc","",T(1.0)), - test_ab("var x := 3; x > 2 and a in '123abc123'","abc","",T(1.0)), - - test_ab("var x := 3; x > 2 and a like b ","abc","*bc",T(1.0)), - test_ab("var x := 3; x > 2 and a ilike b","abc","*Bc",T(1.0)), - test_ab("var x := 3; x > 2 and a in b ","abc","123abc123",T(1.0)), - - test_ab("a[] > 2 and a like '*bc'" ,"abc","",T(1.0)), - test_ab("a[] > 2 and a ilike '*Bc'" ,"abc","",T(1.0)), - test_ab("a[] > 2 and a in '123abc123'","abc","",T(1.0)), - - test_ab("a[] > 2 and a like b ","abc","*bc",T(1.0)), - test_ab("a[] > 2 and a ilike b","abc","*Bc",T(1.0)), - test_ab("a[] > 2 and a in b ","abc","123abc123",T(1.0)), - - test_ab("a[0:0] := b[ :]; a == '0XXXX'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:1] := b[ :]; a == '01XXX'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:2] := b[ :]; a == '012XX'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:3] := b[ :]; a == '0123X'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:4] := b[ :]; a == '01234'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:0] := b[6:]; a == '6XXXX'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:1] := b[6:]; a == '67XXX'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:2] := b[6:]; a == '678XX'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:3] := b[6:]; a == '6789X'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:4] := b[6:]; a == '67890'", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:0] <=> b[ :]; (a == '0XXXX') and (b == 'X1234567890')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:1] <=> b[ :]; (a == '01XXX') and (b == 'XX234567890')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:2] <=> b[ :]; (a == '012XX') and (b == 'XXX34567890')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:3] <=> b[ :]; (a == '0123X') and (b == 'XXXX4567890')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:4] <=> b[ :]; (a == '01234') and (b == 'XXXXX567890')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:0] <=> b[6:]; (a == '6XXXX') and (b == '012345X7890')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:1] <=> b[6:]; (a == '67XXX') and (b == '012345XX890')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:2] <=> b[6:]; (a == '678XX') and (b == '012345XXX90')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:3] <=> b[6:]; (a == '6789X') and (b == '012345XXXX0')", "XXXXX","01234567890",T(1.0)), - test_ab("a[0:4] <=> b[6:]; (a == '67890') and (b == '012345XXXXX')", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+0] := b[:]; a == '0XXXX'", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+1] := b[:]; a == '01XXX'", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+2] := b[:]; a == '012XX'", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+3] := b[:]; a == '0123X'", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+4] := b[:]; a == '01234'", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+0] <=> b[:]; (a == '0XXXX') and (b == 'X1234567890')", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+1] <=> b[:]; (a == '01XXX') and (b == 'XX234567890')", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+2] <=> b[:]; (a == '012XX') and (b == 'XXX34567890')", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+3] <=> b[:]; (a == '0123X') and (b == 'XXXX4567890')", "XXXXX","01234567890",T(1.0)), - test_ab("var i := 0; a[0:i+4] <=> b[:]; (a == '01234') and (b == 'XXXXX567890')", "XXXXX","01234567890",T(1.0)), - - test_ab("var y:= 2; '01234567890'[y:] == a ", "234567890","" ,T(1.0)), - test_ab("var y:= 2; '01234567890'[y:][y:] == a ", "4567890" ,"" ,T(1.0)), - test_ab("var y:= 2; '01234567890'[y:][y:][y:] == a ", "67890" ,"" ,T(1.0)), - test_ab("var y:= 2; '01234567890'[y:][y:][y:][y:] == a ", "890" ,"" ,T(1.0)), - test_ab("var y:= 2; '01234567890'[y:][y:][y:][y:][y:] == a", "0" ,"" ,T(1.0)), - test_ab("var y:= 2; '0123456789'[y:] == a ", "23456789" ,"" ,T(1.0)), - test_ab("var y:= 2; '0123456789'[y:][y:] == a ", "456789" ,"" ,T(1.0)), - test_ab("var y:= 2; '0123456789'[y:][y:][y:] == a ", "6789" ,"" ,T(1.0)), - test_ab("var y:= 2; '0123456789'[y:][y:][y:][y:] == a ", "89" ,"" ,T(1.0)), - test_ab("var y:= 2; '0123456789'[y:][y:][y:][y:][y:] == a ", "" ,"" ,T(1.0)), - - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:0] := y[:]; x == '0XXXX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:1] := y[:]; x == '01XXX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:2] := y[:]; x == '012XX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:3] := y[:]; x == '0123X'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:4] := y[:]; x == '01234'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:0] := y[6:]; x == '6XXXX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:1] := y[6:]; x == '67XXX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:2] := y[6:]; x == '678XX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:3] := y[6:]; x == '6789X'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:4] := y[6:]; x == '67890'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:0] <=> y[:]; (x == '0XXXX') and (y == 'X1234567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:1] <=> y[:]; (x == '01XXX') and (y == 'XX234567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:2] <=> y[:]; (x == '012XX') and (y == 'XXX34567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:3] <=> y[:]; (x == '0123X') and (y == 'XXXX4567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:4] <=> y[:]; (x == '01234') and (y == 'XXXXX567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:0] <=> y[6:]; (x == '6XXXX') and (y == '012345X7890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:1] <=> y[6:]; (x == '67XXX') and (y == '012345XX890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:2] <=> y[6:]; (x == '678XX') and (y == '012345XXX90')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:3] <=> y[6:]; (x == '6789X') and (y == '012345XXXX0')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:4] <=> y[6:]; (x == '67890') and (y == '012345XXXXX')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+0] := y[:]; x == '0XXXX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+1] := y[:]; x == '01XXX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+2] := y[:]; x == '012XX'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+3] := y[:]; x == '0123X'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+4] := y[:]; x == '01234'", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+0] <=> y[:]; (x == '0XXXX') and (y == 'X1234567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+1] <=> y[:]; (x == '01XXX') and (y == 'XX234567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+2] <=> y[:]; (x == '012XX') and (y == 'XXX34567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+3] <=> y[:]; (x == '0123X') and (y == 'XXXX4567890')", "","",T(1.0)), - test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+4] <=> y[:]; (x == '01234') and (y == 'XXXXX567890')", "","",T(1.0)), - - test_ab("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("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("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("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("a like b", "abcd", "abcd*", T(1.0)), - test_ab("a like b", "abcd", "abcd" , T(1.0)), - test_ab("a like b", "abcd", "abc*" , T(1.0)), - test_ab("a like b", "abcd", "*bcd" , T(1.0)), - test_ab("a like b", "abcd", "abc?" , T(1.0)), - test_ab("a like b", "abcd", "?bcd" , T(1.0)), - test_ab("a like b", "abcd", "ab?d" , T(1.0)), - test_ab("a like b", "abcd", "ab*d" , T(1.0)), - test_ab("a like b", "abcd", "a?cd" , T(1.0)), - test_ab("a like b", "abcd", "a*cd" , T(1.0)), - test_ab("a like b", "abcd", "a??d" , T(1.0)), - test_ab("a like b", "abcd", "a*?d" , T(1.0)), - test_ab("a like b", "abcd", "*bc*" , T(1.0)), - test_ab("a like b", "abcd", "?bc?" , T(1.0)), - test_ab("a like b", "abcd", "????" , T(1.0)), - test_ab("a like b", "abcd", "a???" , T(1.0)), - test_ab("a like b", "abcd", "ab??" , T(1.0)), - test_ab("a like b", "abcd", "abc?" , T(1.0)), - test_ab("a like b", "abcd", "???d" , T(1.0)), - test_ab("a like b", "abcd", "??cd" , T(1.0)), - test_ab("a like b", "abcd", "?bcd" , T(1.0)), - test_ab("a like b", "abcd", "?b?d" , T(1.0)), - test_ab("a like b", "abcd", "a?c?" , T(1.0)), - test_ab("a like b", "abcd", "a??d" , T(1.0)), - test_ab("a like b", "abcd", "?bc?" , T(1.0)), - test_ab("a like b", "abcd", "ab**" , T(1.0)), - test_ab("a like b", "abcd", "ab*?" , T(1.0)), - test_ab("a like b", "abcd", "a***" , T(1.0)), - test_ab("a like b", "abcd", "**cd" , T(1.0)), - test_ab("a like b", "abcd", "*?cd" , T(1.0)), - test_ab("a like b", "abcd", "***d" , T(1.0)), - test_ab("a like b", "abcd", "*bc*" , T(1.0)), - test_ab("a like b", "abcd", "*bc?" , T(1.0)), - test_ab("a like b", "abcd", "*b??" , T(1.0)), - test_ab("a like b", "abcd", "?bc*" , T(1.0)), - test_ab("a like b", "abcd", "??c*" , T(1.0)), - test_ab("a like b", "abcd", "*b?*" , T(1.0)), - test_ab("a like b", "ab" , "a*" , T(1.0)), - test_ab("a like b", "ab" , "a?" , T(1.0)), - - test_ab("a ilike b", "aBcD", "abcd*", T(1.0)), - test_ab("a ilike b", "aBcD", "abcd" , T(1.0)), - test_ab("a ilike b", "aBcD", "abc*" , T(1.0)), - test_ab("a ilike b", "aBcD", "*bcd" , T(1.0)), - test_ab("a ilike b", "aBcD", "abc?" , T(1.0)), - test_ab("a ilike b", "aBcD", "?bcd" , T(1.0)), - test_ab("a ilike b", "aBcD", "ab?d" , T(1.0)), - test_ab("a ilike b", "aBcD", "ab*d" , T(1.0)), - test_ab("a ilike b", "aBcD", "a?cd" , T(1.0)), - test_ab("a ilike b", "aBcD", "a*cd" , T(1.0)), - test_ab("a ilike b", "aBcD", "a??d" , T(1.0)), - test_ab("a ilike b", "aBcD", "a*?d" , T(1.0)), - test_ab("a ilike b", "aBcD", "*bc*" , T(1.0)), - test_ab("a ilike b", "aBcD", "?bc?" , T(1.0)), - test_ab("a ilike b", "aBcD", "????" , T(1.0)), - test_ab("a ilike b", "aBcD", "a???" , T(1.0)), - test_ab("a ilike b", "aBcD", "ab??" , T(1.0)), - test_ab("a ilike b", "aBcD", "abc?" , T(1.0)), - test_ab("a ilike b", "aBcD", "???d" , T(1.0)), - test_ab("a ilike b", "aBcD", "??cd" , T(1.0)), - test_ab("a ilike b", "aBcD", "?bcd" , T(1.0)), - test_ab("a ilike b", "aBcD", "?b?d" , T(1.0)), - test_ab("a ilike b", "aBcD", "a?c?" , T(1.0)), - test_ab("a ilike b", "aBcD", "a??d" , T(1.0)), - test_ab("a ilike b", "aBcD", "?bc?" , T(1.0)), - test_ab("a ilike b", "aBcD", "ab**" , T(1.0)), - test_ab("a ilike b", "aBcD", "ab*?" , T(1.0)), - test_ab("a ilike b", "aBcD", "a***" , T(1.0)), - test_ab("a ilike b", "aBcD", "**cd" , T(1.0)), - test_ab("a ilike b", "aBcD", "*?cd" , T(1.0)), - test_ab("a ilike b", "aBcD", "***d" , T(1.0)), - test_ab("a ilike b", "aBcD", "*bc*" , T(1.0)), - test_ab("a ilike b", "aBcD", "*bc?" , T(1.0)), - test_ab("a ilike b", "aBcD", "*b??" , T(1.0)), - test_ab("a ilike b", "aBcD", "?bc*" , T(1.0)), - test_ab("a ilike b", "aBcD", "??c*" , T(1.0)), - test_ab("a ilike b", "aBcD", "*b?*" , T(1.0)), - test_ab("a ilike b", "aB" , "a*" , T(1.0)), - test_ab("a ilike b", "aB" , "a?" , T(1.0)) - }; + { + test_ab("'aaa' == 'aaa'" ,"","",T(1.0)), + test_ab("'aaa' < 'bbb'" ,"","",T(1.0)), + test_ab("'aaa' <= 'bbb'" ,"","",T(1.0)), + test_ab("'bbb' > 'aaa'" ,"","",T(1.0)), + test_ab("'bbb' >= 'aaa'" ,"","",T(1.0)), + test_ab("'aaa' != 'aaa'" ,"","",T(0.0)), + test_ab("'aaa' != 'bbb'" ,"","",T(1.0)), + test_ab("'aaa' + '123' == 'aaa123'" ,"","",T(1.0)), + test_ab("'aaa123' == 'aaa' + '123'" ,"","",T(1.0)), + test_ab("('aaa' + '123') == 'aaa123'" ,"","",T(1.0)), + test_ab("'aaa123' == ('aaa' + '123')" ,"","",T(1.0)), + test_ab("'aaa' in 'aaa123'" ,"","",T(1.0)), + test_ab("'123' in 'aaa123'" ,"","",T(1.0)), + test_ab("'a123b' like '*123*'" ,"","",T(1.0)), + test_ab("'a123b' like '*123?'" ,"","",T(1.0)), + test_ab("'1XYZ2' ilike '*xyz*'" ,"","",T(1.0)), + test_ab("'1XYZ2' ilike '*xyz?'" ,"","",T(1.0)), + test_ab("inrange('aaa','bbb','ccc')" ,"","",T(1.0)), + test_ab("a == b" ,"aaa","aaa",T(1.0)), + test_ab("a != b" ,"aaa","bbb",T(1.0)), + test_ab("a < b" ,"aaa","bbb",T(1.0)), + test_ab("a <= b" ,"aaa","bbb",T(1.0)), + test_ab("b > a" ,"aaa","bbb",T(1.0)), + test_ab("b >= a" ,"aaa","bbb",T(1.0)), + test_ab("a in b" ,"aaa","aaa123",T(1.0)), + test_ab("a in b" ,"123","aaa123",T(1.0)), + test_ab("a == 'aaa'" ,"aaa","aaa",T(1.0)), + test_ab("'aaa' == a" ,"aaa","aaa",T(1.0)), + test_ab("a != 'bbb'" ,"aaa","bbb",T(1.0)), + test_ab("'bbb' != a" ,"aaa","bbb",T(1.0)), + test_ab("a < 'bbb'" ,"aaa","bbb",T(1.0)), + test_ab("a <= 'bbb'" ,"aaa","bbb",T(1.0)), + test_ab("'bbb' > a" ,"aaa","bbb",T(1.0)), + test_ab("'bbb' >= a" ,"aaa","bbb",T(1.0)), + test_ab("a in 'aaa123'" ,"aaa","aaa123",T(1.0)), + test_ab("a in 'aaa123'" ,"123","aaa123",T(1.0)), + test_ab("'aaa' in b" ,"aaa","aaa123",T(1.0)), + test_ab("'123' in b" ,"aaa","aaa123",T(1.0)), + test_ab("(a < b) or (a == b)" ,"aaa","bbb",T(1.0)), + test_ab("(a == b) or (a < b)" ,"aaa","bbb",T(1.0)), + test_ab("(b > a) or (b == a)" ,"aaa","bbb",T(1.0)), + test_ab("(b == a) or (b > a)" ,"aaa","bbb",T(1.0)), + test_ab("(a < b) and (b > a)" ,"aaa","bbb",T(1.0)), + test_ab("a like '*123*'" ,"a123b","",T(1.0)), + test_ab("a like '*123?'" ,"a123b","",T(1.0)), + test_ab("'a123b' like b" ,"a123b","*123*",T(1.0)), + test_ab("'a123b' like b" ,"a123b","*123?",T(1.0)), + test_ab("a ilike '*xyz*'" ,"1XYZ2","",T(1.0)), + test_ab("a ilike '*xyz?'" ,"1XYZ2","",T(1.0)), + test_ab("'1XYZ2' ilike b" ,"","*xyz*",T(1.0)), + test_ab("'1XYZ2' ilike b" ,"","*xyz?",T(1.0)), + test_ab("inrange(a,'bbb',c)" ,"aaa","bbb",T(1.0)), + test_ab("inrange('aaa',b,'ccc')" ,"aaa","bbb",T(1.0)), + test_ab("inrange(a,b,c)" ,"aaa","bbb",T(1.0)), + test_ab("inrange(a,b,'ccc')" ,"aaa","bbb",T(1.0)), + test_ab("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)), + test_ab("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)), + test_ab("(a < b ? a : b) == a" ,"aaa","bbb",T(1.0)), + test_ab("(a > b ? a : b) == b" ,"aaa","bbb",T(1.0)), + test_ab("(a == (a + '1') ? a : b) == b" ,"aaa","bbb",T(1.0)), + test_ab("((a + '2') != a ? a : b) == a" ,"aaa","bbb",T(1.0)), + test_ab("(a < b ? a + '1' : b) == 'aaa1'","aaa","bbb",T(1.0)), + test_ab("(a > b ? a : b + '2') == 'bbb2'","aaa","bbb",T(1.0)), + test_ab("b == (a == (a + '1') ? a : b)" ,"aaa","bbb",T(1.0)), + test_ab("a == (a != (a + '2') ? a : b)" ,"aaa","bbb",T(1.0)), + test_ab("'aaa1' == (a < b ? a + '1' : b)","aaa","bbb",T(1.0)), + test_ab("'bbb2' == (a > b ? a : b + '2')","aaa","bbb",T(1.0)), + test_ab("(a < b ? a[1:3] : b) == '23'" ,"1234","67890",T(1.0)), + test_ab("(a > b ? a : b[0:4]) == '6789'" ,"1234","67890",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x < y ? x : y) == x }}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x > y ? x : y) == y }}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x == (x + '1') ? x : y) == y }}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{((x + '2') != x ? x : y) == x }}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x < y ? x + '1' : y) == 'xxx1'}}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{(x > y ? x : y + '2') == 'yyy2'}}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{y == (x == (x + '1') ? x : y) }}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{x == (x != (x + '2') ? x : y) }}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{'xxx1' == (x < y ? x + '1' : y)}}","","",T(1.0)), + test_ab("~{var x := 'xxx'; var y := 'yyy';~{'yyy2' == (x > y ? x : y + '2')}}","","",T(1.0)), + test_ab("'01234567890123456789'[0:9] == '0123456789' ","","",T(1.0)), + test_ab("'01234567890123456789'[0:9] == '0123456789'[:] ","","",T(1.0)), + test_ab("'01234567890123456789'[0:9] == '0123456789'[0:]","","",T(1.0)), + test_ab("'01234567890123456789'[0:9] == '0123456789'[:9]","","",T(1.0)), + test_ab("'01234567890123456789'[:9] == '0123456789'[:9]","","",T(1.0)), + test_ab("'01234567890123456789'[10:] == '0123456789'[:] ","","",T(1.0)), + test_ab("'01234567890123456789'[0:9] != '123456789' ","","",T(1.0)), + test_ab("'01234567890123456789'[0:9] != '123456789'[:] ","","",T(1.0)), + test_ab("'01234567890123456789'[0:9] != '123456789'[0:] ","","",T(1.0)), + test_ab("'01234567890123456789'[0:9] != '123456789'[:8] ","","",T(1.0)), + test_ab("'01234567890123456789'[:9] != '123456789'[:8] ","","",T(1.0)), + test_ab("'01234567890123456789'[10:] != '123456789'[:] ","","",T(1.0)), + test_ab("'01234567890123456789'[2*6:10+6] == '23456' ","","",T(1.0)), + test_ab("'0123456789' == '01234567890123456789'[0:9]","","",T(1.0)), + test_ab("'0123456789'[:] == '01234567890123456789'[0:9]","","",T(1.0)), + test_ab("'0123456789'[0:] == '01234567890123456789'[0:9]","","",T(1.0)), + test_ab("'0123456789'[:9] == '01234567890123456789'[0:9]","","",T(1.0)), + test_ab("'0123456789'[:9] == '01234567890123456789'[:9] ","","",T(1.0)), + test_ab("'0123456789'[:] == '01234567890123456789'[10:]","","",T(1.0)), + test_ab("'0123456789'[3:3] == '3'[:] ","","",T(1.0)), + test_ab("'0123456789'[3:3] == '3'[0:0] ","","",T(1.0)), + test_ab("'123456789' != '01234567890123456789'[0:9]","","",T(1.0)), + test_ab("'123456789'[:] != '01234567890123456789'[0:9]","","",T(1.0)), + test_ab("'123456789'[0:] != '01234567890123456789'[0:9]","","",T(1.0)), + test_ab("'123456789'[:8] != '01234567890123456789'[0:9]","","",T(1.0)), + test_ab("'123456789'[:8] != '01234567890123456789'[:9] ","","",T(1.0)), + test_ab("'123456789'[:] != '01234567890123456789'[10:]","","",T(1.0)), + test_ab("'23456' == '01234567890123456789'[2*6:10+6] ","","",T(1.0)), + test_ab("'01234567890123456789'[r0: 6] == '23456' ","","",T(1.0)), + test_ab("'01234567890123456789'[2: r1] == '23456' ","","",T(1.0)), + test_ab("'01234567890123456789'[r0:3*2] == '23456' ","","",T(1.0)), + test_ab("'01234567890123456789'[1+1:r1] == '23456' ","","",T(1.0)), + test_ab("'01234567890123456789'[r0: ] == '234567890123456789' ","","",T(1.0)), + test_ab("'01234567890123456789'[: r1] == '0123456' ","","",T(1.0)), + test_ab("'01234567890123456789'[r0:r1] == '23456' ","","",T(1.0)), + test_ab("'01234567890123456789'[r0:r1+2] == '2345678' ","","",T(1.0)), + test_ab("'01234567890123456789'[r0+2:r1] == '456' ","","",T(1.0)), + test_ab("'01234567890123456789'[r1-r0:] == '4567890123456789' ","","",T(1.0)), + test_ab("'01234567890123456789'[:r1-r0] == '01234' ","","",T(1.0)), + test_ab("'23456' == '01234567890123456789'[r0: 6] ","","",T(1.0)), + test_ab("'23456' == '01234567890123456789'[2: r1] ","","",T(1.0)), + test_ab("'23456' == '01234567890123456789'[r0:3*2] ","","",T(1.0)), + test_ab("'23456' == '01234567890123456789'[1+1:r1] ","","",T(1.0)), + test_ab("'234567890123456789' == '01234567890123456789'[r0: ] ","","",T(1.0)), + test_ab("'0123456' == '01234567890123456789'[: r1] ","","",T(1.0)), + test_ab("'23456' == '01234567890123456789'[r0:r1] ","","",T(1.0)), + test_ab("'2345678' == '01234567890123456789'[r0:r1+2] ","","",T(1.0)), + test_ab("'456' == '01234567890123456789'[r0+2:r1] ","","",T(1.0)), + test_ab("'4567890123456789' == '01234567890123456789'[r1-r0:] ","","",T(1.0)), + test_ab("'01234' == '01234567890123456789'[:r1-r0] ","","",T(1.0)), + test_ab("a[r0: 6] == '23456' ","01234567890123456789","",T(1.0)), + test_ab("a[2: r1] == '23456' ","01234567890123456789","",T(1.0)), + test_ab("a[r0:3*2] == '23456' ","01234567890123456789","",T(1.0)), + test_ab("a[1+1:r1] == '23456' ","01234567890123456789","",T(1.0)), + test_ab("a[r0: ] == '234567890123456789' ","01234567890123456789","",T(1.0)), + test_ab("a[: r1] == '0123456' ","01234567890123456789","",T(1.0)), + test_ab("a[r0:r1] == '23456' ","01234567890123456789","",T(1.0)), + test_ab("a[r0:r1+2] == '2345678' ","01234567890123456789","",T(1.0)), + test_ab("a[r0+2:r1] == '456' ","01234567890123456789","",T(1.0)), + test_ab("a[r1-r0:] == '4567890123456789' ","01234567890123456789","",T(1.0)), + test_ab("a[:r1-r0] == '01234' ","01234567890123456789","",T(1.0)), + test_ab("'23456' == a[r0: 6] ","01234567890123456789","",T(1.0)), + test_ab("'23456' == a[2: r1] ","01234567890123456789","",T(1.0)), + test_ab("'23456' == a[r0:3*2] ","01234567890123456789","",T(1.0)), + test_ab("'23456' == a[1+1:r1] ","01234567890123456789","",T(1.0)), + test_ab("'234567890123456789' == a[r0: ] ","01234567890123456789","",T(1.0)), + test_ab("'0123456' == a[: r1] ","01234567890123456789","",T(1.0)), + test_ab("'23456' == a[r0:r1] ","01234567890123456789","",T(1.0)), + test_ab("'2345678' == a[r0:r1+2] ","01234567890123456789","",T(1.0)), + test_ab("'456' == a[r0+2:r1] ","01234567890123456789","",T(1.0)), + test_ab("'4567890123456789' == a[r1-r0:] ","01234567890123456789","",T(1.0)), + test_ab("'01234' == a[:r1-r0] ","01234567890123456789","",T(1.0)), + test_ab("a[r0: 6] == b ","01234567890123456789","23456",T(1.0)), + test_ab("a[2: r1] == b ","01234567890123456789","23456",T(1.0)), + test_ab("a[r0:3*2] == b ","01234567890123456789","23456",T(1.0)), + test_ab("a[1+1:r1] == b ","01234567890123456789","23456",T(1.0)), + test_ab("a[r0: ] == b ","01234567890123456789","234567890123456789",T(1.0)), + test_ab("a[: r1] == b ","01234567890123456789","0123456",T(1.0)), + test_ab("a[r0:r1] == b ","01234567890123456789","23456",T(1.0)), + test_ab("a[r0:r1+2] == b ","01234567890123456789","2345678",T(1.0)), + test_ab("a[r0+2:r1] == b ","01234567890123456789","456",T(1.0)), + test_ab("a[r1-r0:] == b ","01234567890123456789","4567890123456789",T(1.0)), + test_ab("a[:r1-r0] == b ","01234567890123456789","01234",T(1.0)), + test_ab("b == a[r0: 6] ","01234567890123456789","23456",T(1.0)), + test_ab("b == a[2: r1] ","01234567890123456789","23456",T(1.0)), + test_ab("b == a[r0:3*2] ","01234567890123456789","23456",T(1.0)), + test_ab("b == a[1+1:r1] ","01234567890123456789","23456",T(1.0)), + test_ab("b == a[r0: ] ","01234567890123456789","234567890123456789",T(1.0)), + test_ab("b == a[: r1] ","01234567890123456789","0123456",T(1.0)), + test_ab("b == a[r0:r1] ","01234567890123456789","23456",T(1.0)), + test_ab("b == a[r0:r1+2] ","01234567890123456789","2345678",T(1.0)), + test_ab("b == a[r0+2:r1] ","01234567890123456789","456",T(1.0)), + test_ab("b == a[r1-r0:] ","01234567890123456789","4567890123456789",T(1.0)), + test_ab("b == a[:r1-r0] ","01234567890123456789","01234",T(1.0)), + test_ab("'01234567890123456789'[0:9] == a ","0123456789","",T(1.0)), + test_ab("'01234567890123456789'[0:9] == a[:] ","0123456789","",T(1.0)), + test_ab("'01234567890123456789'[0:9] == a[0:] ","0123456789","",T(1.0)), + test_ab("'01234567890123456789'[0:9] == a[:9] ","0123456789","",T(1.0)), + test_ab("'01234567890123456789'[:9] == a[:9] ","0123456789","",T(1.0)), + test_ab("'01234567890123456789'[10:] == a[:] ","0123456789","",T(1.0)), + test_ab("'01234567890123456789'[0:9] != a ","123456789" ,"",T(1.0)), + test_ab("'01234567890123456789'[0:9] != a[:] ","123456789" ,"",T(1.0)), + test_ab("'01234567890123456789'[0:9] != a[0:] ","123456789" ,"",T(1.0)), + test_ab("'01234567890123456789'[0:9] != a[:8] ","123456789" ,"",T(1.0)), + test_ab("'01234567890123456789'[:9] != a[:8] ","123456789" ,"",T(1.0)), + test_ab("'01234567890123456789'[10:] != a[:] ","123456789" ,"",T(1.0)), + test_ab("'01234567890123456789'[2*6:10+6] == a","23456" ,"",T(1.0)), + test_ab("'23456' == a[:] ","23456" ,"",T(1.0)), + test_ab("a == '01234567890123456789'[0:9] ","0123456789","",T(1.0)), + test_ab("a[:] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)), + test_ab("a[0:] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)), + test_ab("a[:9] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)), + test_ab("a[:9] == '01234567890123456789'[:9] ","0123456789","",T(1.0)), + test_ab("a[:] == '01234567890123456789'[10:] ","0123456789","",T(1.0)), + test_ab("a != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)), + test_ab("a[:] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)), + test_ab("a[0:] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)), + test_ab("a[:8] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)), + test_ab("a[:8] != '01234567890123456789'[:9] ","123456789" ,"",T(1.0)), + test_ab("a[:] != '01234567890123456789'[10:] ","123456789" ,"",T(1.0)), + test_ab("a == '01234567890123456789'[2*6:10+6]","23456" ,"",T(1.0)), + test_ab("a[:] == '23456' ","23456" ,"",T(1.0)), + test_ab("a[0:9] == b ","01234567890123456789","0123456789",T(1.0)), + test_ab("a[0:9] == b[:] ","01234567890123456789","0123456789",T(1.0)), + test_ab("a[0:9] == b[0:] ","01234567890123456789","0123456789",T(1.0)), + test_ab("a[0:9] == b[:9] ","01234567890123456789","0123456789",T(1.0)), + test_ab("a[:9] == b[:9] ","01234567890123456789","0123456789",T(1.0)), + test_ab("a[10:] == b[:] ","01234567890123456789","0123456789",T(1.0)), + test_ab("a[0:9] != b ","01234567890123456789","123456789" ,T(1.0)), + test_ab("a[0:9] != b[:] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("a[0:9] != b[0:] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("a[0:9] != b[:8] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("a[:9] != b[:8] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("a[10:] != b[:] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("a[2*6:10+6] == b ","01234567890123456789","23456" ,T(1.0)), + test_ab("b == a[0:9] ","01234567890123456789","0123456789",T(1.0)), + test_ab("b[:] == a[0:9] ","01234567890123456789","0123456789",T(1.0)), + test_ab("b[0:] == a[0:9] ","01234567890123456789","0123456789",T(1.0)), + test_ab("b[:9] == a[0:9] ","01234567890123456789","0123456789",T(1.0)), + test_ab("b[:9] == a[:9] ","01234567890123456789","0123456789",T(1.0)), + test_ab("b[:] == a[10:] ","01234567890123456789","0123456789",T(1.0)), + test_ab("b != a[0:9] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("b[:] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("b[0:] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("b[:8] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("b[:8] != a[:9] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("b[:] != a[10:] ","01234567890123456789","123456789" ,T(1.0)), + test_ab("b == a[2*6:10+6] ","01234567890123456789","23456" ,T(1.0)), + test_ab("a[2:6] == b" ,"0123456789","23456" ,T(1.0)), + test_ab("a == b[2:6]" ,"23456","0123456789" ,T(1.0)), + test_ab("a[1+1:2*3] == b" ,"0123456789","23456" ,T(1.0)), + test_ab("a == b[4/2:sqrt(36)]","23456","0123456789" ,T(1.0)), + test_ab("a[0:6] == b" ,"0123456789","0123456",T(1.0)), + test_ab("a[:6] == b" ,"0123456789","0123456",T(1.0)), + test_ab("a[4/2-2:2+4] == b" ,"0123456789","0123456",T(1.0)), + test_ab("a[:12/2] == b" ,"0123456789","0123456",T(1.0)), + test_ab("a[0:] == b" ,"0123456","0123456" ,T(1.0)), + test_ab("a[:] == b" ,"0123456","0123456" ,T(1.0)), + test_ab("a == b[0:6]" ,"0123456","0123456789",T(1.0)), + test_ab("a == b[:6]" ,"0123456","0123456789",T(1.0)), + test_ab("a == b[4/2-2:2+4]" ,"0123456","0123456789",T(1.0)), + test_ab("a == b[:12/2]" ,"0123456","0123456789",T(1.0)), + test_ab("a == b[0:]" ,"0123456","0123456" ,T(1.0)), + test_ab("a == b[:]" ,"0123456","0123456" ,T(1.0)), + test_ab("a[:9] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)), + test_ab("a[0:9] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)), + test_ab("a[0:] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)), + test_ab("a[:] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)), + test_ab("a[:] == b[10:]" ,"0123456789","01234567890123456789",T(1.0)), + test_ab("'!@#$%^&*([{}])-=' != ')]}{[(*&^%$#@!'","","",T(1.0)), + test_ab("('!@#$%^&*([{}])-=') != (')]}{[(*&^%$#@!')","","",T(1.0)), + test_ab("{[('a')]} == [{('a')}]","","",T(1.0)), + test_ab("{[('!@#$%^&*([{}])-=')]} != [{(')]}{[(*&^%$#@!')}]","","",T(1.0)), + test_ab("'!@#$%^&*([{}])-=' == '!@#$%^&*([{}])-='","","",T(1.0)), + test_ab("('!@#$%^&*([{}])-=') == ('!@#$%^&*([{}])-=')","","",T(1.0)), + test_ab("{[('!@#$%^&*([{}])-=')]} == [{('!@#$%^&*([{}])-=')}]","","",T(1.0)), + test_ab("'1234\\\\abc\nxyz\r890\tqaz\\'567' == a","1234\\abc\nxyz\r890\tqaz'567","",T(1.0)), + test_ab("a == '1234\\\\abc\nxyz\r890\tqaz\\'567'","1234\\abc\nxyz\r890\tqaz'567","",T(1.0)), + test_ab("'123'[] == 3" ,"","" ,T(1.0)), + test_ab("3 == '123'[]" ,"","" ,T(1.0)), + test_ab("'123'[] + '1234'[] == 7" ,"","" ,T(1.0)), + test_ab("abs('123'[] - '1234'[]) == 1" ,"","" ,T(1.0)), + test_ab("'1234'[] == a[]" ,"1234","" ,T(1.0)), + test_ab("'123'[] + a[] == 7" ,"1234","" ,T(1.0)), + test_ab("abs(a[] - '12345'[]) == 1" ,"1234","" ,T(1.0)), + test_ab("'1234'[] + '12345'[] == a[] + b[]" ,"1234","12345" ,T(1.0)), + test_ab("abs('123'[] -'1234'[]) == abs(a[] - b[])" ,"1234","12345",T(1.0)), + test_ab("(a + b) == 'abc123' ","abc","123" ,T(1.0)), + test_ab("(a + '123') == 'abc123' ","abc","123" ,T(1.0)), + test_ab("('abc' + b) == 'abc123' ","abc","123" ,T(1.0)), + test_ab("(a + '1') == 'abc1' ","abc","123" ,T(1.0)), + test_ab("('a' + b) == 'a123' ","abc","123" ,T(1.0)), + test_ab("(a[2:8] + b) == 'cdefgh0123' ","abcdefghij","0123",T(1.0)), + test_ab("(a + b[2:8]) == 'abc234567' ","abc","0123456789" ,T(1.0)), + test_ab("(a[2:8] + '0123') == 'cdefgh0123' ","abcdefghij","0123",T(1.0)), + test_ab("('abc' + b[2:8]) == 'abc234567' ","abc","0123456789" ,T(1.0)), + test_ab("(a[2:3] + b[3:4]) == 'c3' ","abc","0123456789" ,T(1.0)), + test_ab("(a[3:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)), + test_ab("('abc' + b[:8]) == 'abc01234567' ","abc","0123456789" ,T(1.0)), + test_ab("a + '123' == 'abc'+ b ","abc" , "123" , T(1.0)), + test_ab("a[0:3] + '123' == 'abc' + b[0:3] ","abcXYZ", "123XYZ", T(1.0)), + test_ab("a[ :3] + '123' == 'abc' + b[ :3] ","abcXYZ", "123XYZ", T(1.0)), + test_ab("a[3: ] + '123' == 'abc' + b[3: ]","XYZabc", "XYZ123", T(1.0)), + test_ab("a[3:a[]] + '123' == 'abc' + b[3:b[]]","XYZabc", "XYZ123", T(1.0)), + test_ab("(a[r0:r2] + b) == 'cdefg0123' ","abcdefghij","0123",T(1.0)), + test_ab("(a + b[r0:r2]) == 'abc23456' ","abc","0123456789" ,T(1.0)), + test_ab("(a[r0:r2] + '0123') == 'cdefg0123' ","abcdefghij","0123",T(1.0)), + test_ab("('abc' + b[r0:r2]) == 'abc23456' ","abc","0123456789" ,T(1.0)), + test_ab("(a[r0:r0+1] + b[r3:r3+1]) == 'c3' ","abc","0123456789" ,T(1.0)), + test_ab("(a[r3:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)), + test_ab("('abc' + b[:r2]) == 'abc0123456' ","abc","0123456789" ,T(1.0)), + test_ab("a[0:r0] + '123' == 'ab'+ b[0:r0+1] ","abcXYZ", "123XYZ", T(1.0)), + test_ab("a[ :r0] + '123' == 'ab' +b[ :r0+1] ","abcXYZ", "123XYZ", T(1.0)), + test_ab("a[r3: ] + '123' == 'abc' + b[r3: ]","XYZabc", "XYZ123", T(1.0)), + test_ab("a[r3:a[]] + '123' == 'abc' + b[r3:b[]] ","XYZabc", "XYZ123", T(1.0)), + test_ab("(a[r0:r0+1] + b[r3:r0+2]) == 'c3' ","abc","0123456789" ,T(1.0)), + test_ab("(a[r0+1:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)), + test_ab("a[r0+1: ] + '123' == 'abc' + b[r0+1: ]", "XYZabc" ,"XYZ123" ,T(1.0)), + test_ab("a[r0+1:a[]] + '123' == 'abc' + b[r0+1:b[]] ", "XYZabc" ,"XYZ123" ,T(1.0)), + test_ab("(a + b)[ :14] == 'abcdefghij0123' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a + b)[ 6: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a + b)[ 2:3r1] == 'cdefghij01234567' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a[2:8] + b[2:8]) == 'cdefgh234567' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a[2:8] + b[2:8])[3:9] == 'fgh234' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a + b)[r0 - 2: r1 + r2 +1] == 'abcdefghij0123'", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a + b)[r0*r3:] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a + b)[3r0: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a + b)[2r3: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a + b)[2:3r1] == 'cdefghij01234567' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a[r0:8] + b[r0:r2+1])== 'cdefgh234567' ", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a[r1 / r3:8] + b[r0:r2+1])[3:r2 + 2] == 'fgh234'", "abcdefghij", "0123456789" ,T(1.0)), + test_ab("(a += b) == 'abc123' ", "abc","123" ,T(1.0)), + test_ab("(a += '123') == 'abc123' ", "abc","123" ,T(1.0)), + test_ab("(a += b[3:6]) == 'abc123' ", "abc","XXX123XXX" ,T(1.0)), + test_ab("(a += 'XXX123XXX'[3:6]) == 'abc123' ", "abc","123" ,T(1.0)), + test_ab("(a += b)[:] == 'abc123' ", "abc","123" ,T(1.0)), + test_ab("(a += '123')[:] == 'abc123' ", "abc","123" ,T(1.0)), + test_ab("(a += b[3:6])[:] == 'abc123' ", "abc","XXX123XXX" ,T(1.0)), + test_ab("(a += 'XXX123XXX'[3:6])[:] == 'abc123' ", "abc","123" ,T(1.0)), + test_ab("(a += b[r1/2:r1]) == 'abc123' ", "abc","XXX123XXX" ,T(1.0)), + test_ab("(a += 'XXX123XXX'[r0+1:r1]) == 'abc123' ", "abc","123" ,T(1.0)), + test_ab("(a += b)[] == 6 ", "abc","123" ,T(1.0)), + test_ab("(a += '123')[] == 6 ", "abc","123" ,T(1.0)), + test_ab("(a += b[3:6])[] == 6 ", "abc","XXX123XXX" ,T(1.0)), + test_ab("(a += b[r0+1:r1])[] == 6 ", "abc","XXX123XXX" ,T(1.0)), + test_ab("(a + b)[:][] == 6 ","abc","123" ,T(1.0)), + test_ab("(a + b)[:][:][] == 6 ","abc","123" ,T(1.0)), + test_ab("(a + b)[:][:][:][] == 6 ","abc","123" ,T(1.0)), + test_ab("(a + b)[:][:][:][:][] == 6 ","abc","123" ,T(1.0)), + test_ab("(a + b)[:][:][:][:][:][] == 6 ","abc","123" ,T(1.0)), + test_ab("(a + b)[:][:][:][:][:][:][] == 6 ","abc","123" ,T(1.0)), + test_ab("(a + b)[:][:][:][:][:][:][:][]== 6 ","abc","123" ,T(1.0)), + test_ab("(a + b)[0:6] == 'abc123' ","abc","123" ,T(1.0)), + test_ab("(a + b)[0:6][1:5] == 'bc12' ","abc","123" ,T(1.0)), + test_ab("(a + b)[0:6][1:5][1:3] == 'c1' ","abc","123" ,T(1.0)), + test_ab("(a + b)[0:6][1:5][1:3][0:1] == 'c' ","abc","123" ,T(1.0)), + test_ab("(a + b)[0:6][] == 6 ","abc","123" ,T(1.0)), + test_ab("(a + b)[0:6][1:5][] == 4 ","abc","123" ,T(1.0)), + test_ab("(a + b)[0:6][1:5][1:3][] == 2 ","abc","123" ,T(1.0)), + test_ab("(a + b)[0:6][1:5][1:4][0:1][] == 1 ","abc","123" ,T(1.0)), + test_ab("(a[ : ] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[0: ] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[ :10]:= b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[3: 8]:= b); (a == '012ABCDE89');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[2: 9]:= b); (a == '01ABCDEFG9');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[1:10]:= b); (a == '0ABCDEFGHI');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[0:1] := b); (a == 'A123456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[1:2] := b); (a == '0A23456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[2:3] := b); (a == '01A3456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[3:4] := b); (a == '012A456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[4:5] := b); (a == '0123A56789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[5:6] := b); (a == '01234A6789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[6:7] := b); (a == '012345A789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[7:8] := b); (a == '0123456A89');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[8:9] := b); (a == '01234567A9');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[9:10]:= b); (a == '012345678A');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[0:2] := b); (a == 'AB23456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[1:3] := b); (a == '0AB3456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[2:4] := b); (a == '01AB456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[3:5] := b); (a == '012AB56789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[4:6] := b); (a == '0123AB6789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[5:7] := b); (a == '01234AB789');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[6:8] := b); (a == '012345AB89');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[7:9] := b); (a == '0123456AB9');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[8:10]:= b); (a == '01234567AB');", "0123456789","ABCDEFGHIJ" ,T(1.0)), + test_ab("(a[ : ] := b[3:b[] - 2]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[0: ] := b[3:b[] - 2]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[ :10] := b[3:b[] - 2]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[3:8] := b[3:b[] - 2]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[2:9] := b[3:b[] - 2]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[1:10] := b[3:b[] - 2]); (a == '0ABCDEFGHI');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[0:1] := b[3:b[] - 2]); (a == 'A123456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[1:2] := b[3:b[] - 2]); (a == '0A23456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[2:3] := b[3:b[] - 2]); (a == '01A3456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[3:4] := b[3:b[] - 2]); (a == '012A456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[4:5] := b[3:b[] - 2]); (a == '0123A56789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[5:6] := b[3:b[] - 2]); (a == '01234A6789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[6:7] := b[3:b[] - 2]); (a == '012345A789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[7:8] := b[3:b[] - 2]); (a == '0123456A89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[8:9] := b[3:b[] - 2]); (a == '01234567A9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[9:10] := b[3:b[] - 2]); (a == '012345678A');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[0:2] := b[3:b[] - 2]); (a == 'AB23456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[1:3] := b[3:b[] - 2]); (a == '0AB3456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[2:4] := b[3:b[] - 2]); (a == '01AB456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[3:5] := b[3:b[] - 2]); (a == '012AB56789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[4:6] := b[3:b[] - 2]); (a == '0123AB6789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[5:7] := b[3:b[] - 2]); (a == '01234AB789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[6:8] := b[3:b[] - 2]); (a == '012345AB89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[7:9] := b[3:b[] - 2]); (a == '0123456AB9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[8:10] := b[3:b[] - 2]); (a == '01234567AB');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[0:10] := b); (a == 'A123456789');", "0123456789","A" ,T(1.0)), + test_ab("(a[0:10] := b); (a == 'AB23456789');", "0123456789","AB" ,T(1.0)), + test_ab("(a[0:10] := b); (a == 'ABC3456789');", "0123456789","ABC" ,T(1.0)), + test_ab("(a[0:10] := b); (a == 'ABCD456789');", "0123456789","ABCD" ,T(1.0)), + test_ab("(a[0:10] := b); (a == 'ABCDE56789');", "0123456789","ABCDE" ,T(1.0)), + test_ab("(a[0:10] := b); (a == 'ABCDEF6789');", "0123456789","ABCDEF" ,T(1.0)), + test_ab("(a[0:10] := b); (a == 'ABCDEFG789');", "0123456789","ABCDEFG" ,T(1.0)), + test_ab("(a[0:10] := b); (a == 'ABCDEFGH89');", "0123456789","ABCDEFGH" ,T(1.0)), + test_ab("(a[0:10] := b); (a == 'ABCDEFGHI9');", "0123456789","ABCDEFGHI" ,T(1.0)), + test_ab("(a[3:10] := b); (a == '012A456789');", "0123456789","A" ,T(1.0)), + test_ab("(a[3:10] := b); (a == '012AB56789');", "0123456789","AB" ,T(1.0)), + test_ab("(a[3:10] := b); (a == '012ABC6789');", "0123456789","ABC" ,T(1.0)), + test_ab("(a[3:10] := b); (a == '012ABCD789');", "0123456789","ABCD" ,T(1.0)), + test_ab("(a[3:10] := b); (a == '012ABCDE89');", "0123456789","ABCDE" ,T(1.0)), + test_ab("(a[3:10] := b); (a == '012ABCDEF9');", "0123456789","ABCDEF" ,T(1.0)), + test_ab("(a[r1 / r0:r2 + 1] := b[3:b[] - r3 + 1]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("(a[r0:r2 + 2] := b[r3:b[] - r3 + 1]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)), + test_ab("'\\0x30\\0x31\\0x32\\0x33\\0x34\\0x35\\0x36\\0x37\\0x38\\0x39' == '0123456789'","","",T(1.0)), + test_ab("'abc\\0x30\\0x31\\0x32\\0x33xyz' == 'abc0123xyz'" ,"","",T(1.0)), + test_ab("'\\0x30\\n\\0x31\\n\\0x32\\n\\0x33' == '0\\n1\\n2\\n3'" ,"","",T(1.0)), + test_ab("('\\0x30' + '') == '0'" ,"","",T(1.0)), + test_ab("('\\0x30' + '') == '0' + ''" ,"","",T(1.0)), + test_ab("('\\0x30' + '') == ''+ '0'" ,"","",T(1.0)), + test_ab("('' + '\\0x30') == '0'" ,"","",T(1.0)), + test_ab("('' + '\\0x30') == '0' + ''" ,"","",T(1.0)), + test_ab("('' + '\\0x30') == ''+ '0'" ,"","",T(1.0)), + test_ab("('' + '\\0x30' + '') == '0'" ,"","",T(1.0)), + test_ab("('' + '\\0x30' + '') == '0' + ''" ,"","",T(1.0)), + test_ab("('' + '\\0x30' + '') == ''+ '0'" ,"","",T(1.0)), + test_ab("('' + '\\0x30' + '') == '0'" ,"","",T(1.0)), + test_ab("('' + '\\0x30' + '') == '0' + ''" ,"","",T(1.0)), + test_ab("('' + '\\0x30' + '') == ''+ '0'" ,"","",T(1.0)), + test_ab("('\\0x30' + '\\0x31\\0x32') == '012'" ,"","",T(1.0)), + test_ab("('\\0x30' + '\\0x31\\0x32' + '\\0x33\\0x34\\0x35') == '012345'" ,"","",T(1.0)), + test_ab("'a\\'\\\\b' == a" ,"a'\\b","",T(1.0)), + test_ab("'a\\\\\\'b' == a" ,"a\\'b","",T(1.0)), + test_ab("'a\\'\\\\\\\\b' == a" ,"a'\\\\b","",T(1.0)), + test_ab("'a\\0x30\\'\\0x31\\\\\\0x32b' == a" ,"a0'1\\2b","",T(1.0)), + + test_ab("var x := 3; x > 2 and 'abc' like '*bc'" ,"","",T(1.0)), + test_ab("var x := 3; x > 2 and 'abc' ilike '*Bc'" ,"","",T(1.0)), + test_ab("var x := 3; x > 2 and 'abc' in '123abc123'","","",T(1.0)), + + test_ab("var x := 3; var s := 'abc'; x > 2 and s like '*bc'" ,"","",T(1.0)), + test_ab("var x := 3; var s := 'abc'; x > 2 and s ilike '*Bc'" ,"","",T(1.0)), + test_ab("var x := 3; var s := 'abc'; x > 2 and s in '123abc123'","","",T(1.0)), + + test_ab("var x := 3; var s := 'abc'; var t := '*bc'; x > 2 and s like t" ,"","",T(1.0)), + test_ab("var x := 3; var s := 'abc'; var t := '*Bc'; x > 2 and s ilike t" ,"","",T(1.0)), + test_ab("var x := 3; var s := 'abc'; var t := '123abc123'; x > 2 and s in t","","",T(1.0)), + + test_ab("var x := 3; x > 2 and a like '*bc'" ,"abc","",T(1.0)), + test_ab("var x := 3; x > 2 and a ilike '*Bc'" ,"abc","",T(1.0)), + test_ab("var x := 3; x > 2 and a in '123abc123'","abc","",T(1.0)), + + test_ab("var x := 3; x > 2 and a like b ","abc","*bc",T(1.0)), + test_ab("var x := 3; x > 2 and a ilike b","abc","*Bc",T(1.0)), + test_ab("var x := 3; x > 2 and a in b ","abc","123abc123",T(1.0)), + + test_ab("a[] > 2 and a like '*bc'" ,"abc","",T(1.0)), + test_ab("a[] > 2 and a ilike '*Bc'" ,"abc","",T(1.0)), + test_ab("a[] > 2 and a in '123abc123'","abc","",T(1.0)), + + test_ab("a[] > 2 and a like b ","abc","*bc",T(1.0)), + test_ab("a[] > 2 and a ilike b","abc","*Bc",T(1.0)), + test_ab("a[] > 2 and a in b ","abc","123abc123",T(1.0)), + + test_ab("a[0:1] := b[ :]; a == '0XXXX'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:2] := b[ :]; a == '01XXX'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:3] := b[ :]; a == '012XX'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:4] := b[ :]; a == '0123X'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:5] := b[ :]; a == '01234'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:1] := b[6:]; a == '6XXXX'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:2] := b[6:]; a == '67XXX'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:3] := b[6:]; a == '678XX'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:4] := b[6:]; a == '6789X'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:5] := b[6:]; a == '67890'", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:1] <=> b[ :]; (a == '0XXXX') and (b == 'X1234567890')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:2] <=> b[ :]; (a == '01XXX') and (b == 'XX234567890')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:3] <=> b[ :]; (a == '012XX') and (b == 'XXX34567890')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:4] <=> b[ :]; (a == '0123X') and (b == 'XXXX4567890')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:5] <=> b[ :]; (a == '01234') and (b == 'XXXXX567890')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:1] <=> b[6:]; (a == '6XXXX') and (b == '012345X7890')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:2] <=> b[6:]; (a == '67XXX') and (b == '012345XX890')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:3] <=> b[6:]; (a == '678XX') and (b == '012345XXX90')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:4] <=> b[6:]; (a == '6789X') and (b == '012345XXXX0')", "XXXXX","01234567890",T(1.0)), + test_ab("a[0:5] <=> b[6:]; (a == '67890') and (b == '012345XXXXX')", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+1] := b[:]; a == '0XXXX'", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+2] := b[:]; a == '01XXX'", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+3] := b[:]; a == '012XX'", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+4] := b[:]; a == '0123X'", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+5] := b[:]; a == '01234'", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+1] <=> b[:]; (a == '0XXXX') and (b == 'X1234567890')", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+2] <=> b[:]; (a == '01XXX') and (b == 'XX234567890')", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+3] <=> b[:]; (a == '012XX') and (b == 'XXX34567890')", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+4] <=> b[:]; (a == '0123X') and (b == 'XXXX4567890')", "XXXXX","01234567890",T(1.0)), + test_ab("var i := 0; a[0:i+5] <=> b[:]; (a == '01234') and (b == 'XXXXX567890')", "XXXXX","01234567890",T(1.0)), + + test_ab("var y:= 2; '01234567890'[y:] == a ", "234567890","" ,T(1.0)), + test_ab("var y:= 2; '01234567890'[y:][y:] == a ", "4567890" ,"" ,T(1.0)), + test_ab("var y:= 2; '01234567890'[y:][y:][y:] == a ", "67890" ,"" ,T(1.0)), + test_ab("var y:= 2; '01234567890'[y:][y:][y:][y:] == a ", "890" ,"" ,T(1.0)), + test_ab("var y:= 2; '01234567890'[y:][y:][y:][y:][y:] == a", "0" ,"" ,T(1.0)), + test_ab("var y:= 2; '0123456789'[y:] == a ", "23456789" ,"" ,T(1.0)), + test_ab("var y:= 2; '0123456789'[y:][y:] == a ", "456789" ,"" ,T(1.0)), + test_ab("var y:= 2; '0123456789'[y:][y:][y:] == a ", "6789" ,"" ,T(1.0)), + test_ab("var y:= 2; '0123456789'[y:][y:][y:][y:] == a ", "89" ,"" ,T(1.0)), + test_ab("var y:= 2; '0123456789'[y:][y:][y:][y:][y:] == a ", "" ,"" ,T(1.0)), + + test_ab("var s:= ''; s := ''; s == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s := ''; '' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s := ''; s[:] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s := ''; '' == s[:] ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s := ''; s[:s[]] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s := ''; '' == s[:s[]] ", "" ,"" ,T(1.0)), + + test_ab("var s:= ''; s := '' + ''; s == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s := '' + ''; '' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s += ''; s == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s += ''; '' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s := '' + ''; s == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s := '' + ''; '' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s := '' + ''; s == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s := '' + ''; '' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s := '' + ''; s == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s := '' + ''; '' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s += ''; s == '1' ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s += ''; '1' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s += ''; s == '12' ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s += ''; '12' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s += ''; s == '123' ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s += ''; '123' == s ", "" ,"" ,T(1.0)), + + test_ab("var s:= ''; s := '' + ''; s[:] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s := '' + ''; '' == s[:] ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s += ''; s[:] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s += ''; '' == s[:] ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s := '' + ''; s[:] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s := '' + ''; '' == s[:] ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s := '' + ''; s[:] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s := '' + ''; '' == s[:] ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s := '' + ''; s[:] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s := '' + ''; '' == s[:] ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s += ''; s[:] == '1' ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s += ''; '1' == s[:] ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s += ''; s[:] == '12' ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s += ''; '12' == s[:] ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s += ''; s[:] == '123' ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s += ''; '123' == s[:] ", "" ,"" ,T(1.0)), + + test_ab("var s:= ''; s := '' + ''; s[:s[]] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s := '' + ''; '' == s[:s[]] ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s += ''; s[:s[]] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; s += ''; '' == s[:s[]] ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s := '' + ''; s[:s[]] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s := '' + ''; '' == s[:s[]] ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s := '' + ''; s[:s[]] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s := '' + ''; '' == s[:s[]] ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s := '' + ''; s[:s[]] == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s := '' + ''; '' == s[:s[]] ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s += ''; s[:s[]] == '1' ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; s += ''; '1' == s[:s[]] ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s += ''; s[:s[]] == '12' ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; s += ''; '12' == s[:s[]] ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s += ''; s[:s[]] == '123' ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; s += ''; '123' == s[:s[]] ", "" ,"" ,T(1.0)), + + test_ab("var s:= ''; for(var i:=0; i < 10; i+=1) {s += '';}; s == '' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 10; i+=1) {s += '';}; '' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; for(var i:=0; i < 10; i+=1) {s += '';}; s == '1' ", "" ,"" ,T(1.0)), + test_ab("var s:= '1'; for(var i:=0; i < 10; i+=1) {s += '';}; '1' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; for(var i:=0; i < 10; i+=1) {s += '';}; s == '12' ", "" ,"" ,T(1.0)), + test_ab("var s:= '12'; for(var i:=0; i < 10; i+=1) {s += '';}; '12' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; for(var i:=0; i < 10; i+=1) {s += '';}; s == '123' ", "" ,"" ,T(1.0)), + test_ab("var s:= '123'; for(var i:=0; i < 10; i+=1) {s += '';}; '123' == s ", "" ,"" ,T(1.0)), + + test_ab("var s:= ''; for(var i:=0; i < 4; i+=1) {s += '1';}; s == '1111' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 4; i+=1) {s += '1';}; '1111' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s += '22';}; s == '2222' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s += '22';}; '2222' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s += '333';}; s == '333333' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s += '333';}; '333333' == s ", "" ,"" ,T(1.0)), + + test_ab("var s:= ''; for(var i:=0; i < 4; i+=1) {s := s + '1';}; s == '1111' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 4; i+=1) {s := s + '1';}; '1111' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s := s + '22';}; s == '2222' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s := s + '22';}; '2222' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s := s + '333';}; s == '333333'", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s := s + '333';}; '333333' == s", "" ,"" ,T(1.0)), + + test_ab("var s:= ''; for(var i:=0; i < 4; i+=1) {s := '1' + s;}; s == '1111' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 4; i+=1) {s := '1' + s;}; '1111' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s := '22' + s;}; s == '2222' ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s := '22' + s;}; '2222' == s ", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s := '333' + s;}; s == '333333'", "" ,"" ,T(1.0)), + test_ab("var s:= ''; for(var i:=0; i < 2; i+=1) {s := '333' + s;}; '333333' == s", "" ,"" ,T(1.0)), + + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:1] := y[:]; x == '0XXXX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:2] := y[:]; x == '01XXX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:3] := y[:]; x == '012XX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:4] := y[:]; x == '0123X'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:5] := y[:]; x == '01234'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:1] := y[6:]; x == '6XXXX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:2] := y[6:]; x == '67XXX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:3] := y[6:]; x == '678XX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:4] := y[6:]; x == '6789X'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:5] := y[6:]; x == '67890'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:1] <=> y[:]; (x == '0XXXX') and (y == 'X1234567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:2] <=> y[:]; (x == '01XXX') and (y == 'XX234567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:3] <=> y[:]; (x == '012XX') and (y == 'XXX34567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:4] <=> y[:]; (x == '0123X') and (y == 'XXXX4567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:5] <=> y[:]; (x == '01234') and (y == 'XXXXX567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:1] <=> y[6:]; (x == '6XXXX') and (y == '012345X7890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:2] <=> y[6:]; (x == '67XXX') and (y == '012345XX890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:3] <=> y[6:]; (x == '678XX') and (y == '012345XXX90')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:4] <=> y[6:]; (x == '6789X') and (y == '012345XXXX0')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; x[0:5] <=> y[6:]; (x == '67890') and (y == '012345XXXXX')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+1] := y[:]; x == '0XXXX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+2] := y[:]; x == '01XXX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+3] := y[:]; x == '012XX'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+4] := y[:]; x == '0123X'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+5] := y[:]; x == '01234'", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+1] <=> y[:]; (x == '0XXXX') and (y == 'X1234567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+2] <=> y[:]; (x == '01XXX') and (y == 'XX234567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+3] <=> y[:]; (x == '012XX') and (y == 'XXX34567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+4] <=> y[:]; (x == '0123X') and (y == 'XXXX4567890')", "","",T(1.0)), + test_ab("var x := 'XXXXX'; var y := '01234567890'; var i := 0; x[0:i+5] <=> y[:]; (x == '01234') and (y == 'XXXXX567890')", "","",T(1.0)), + + test_ab("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("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("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("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("a like b", "abcd", "abcd*", T(1.0)), + test_ab("a like b", "abcd", "abcd" , T(1.0)), + test_ab("a like b", "abcd", "abc*" , T(1.0)), + test_ab("a like b", "abcd", "*bcd" , T(1.0)), + test_ab("a like b", "abcd", "abc?" , T(1.0)), + test_ab("a like b", "abcd", "?bcd" , T(1.0)), + test_ab("a like b", "abcd", "ab?d" , T(1.0)), + test_ab("a like b", "abcd", "ab*d" , T(1.0)), + test_ab("a like b", "abcd", "a?cd" , T(1.0)), + test_ab("a like b", "abcd", "a*cd" , T(1.0)), + test_ab("a like b", "abcd", "a??d" , T(1.0)), + test_ab("a like b", "abcd", "a*?d" , T(1.0)), + test_ab("a like b", "abcd", "*bc*" , T(1.0)), + test_ab("a like b", "abcd", "?bc?" , T(1.0)), + test_ab("a like b", "abcd", "????" , T(1.0)), + test_ab("a like b", "abcd", "a???" , T(1.0)), + test_ab("a like b", "abcd", "ab??" , T(1.0)), + test_ab("a like b", "abcd", "abc?" , T(1.0)), + test_ab("a like b", "abcd", "???d" , T(1.0)), + test_ab("a like b", "abcd", "??cd" , T(1.0)), + test_ab("a like b", "abcd", "?bcd" , T(1.0)), + test_ab("a like b", "abcd", "?b?d" , T(1.0)), + test_ab("a like b", "abcd", "a?c?" , T(1.0)), + test_ab("a like b", "abcd", "a??d" , T(1.0)), + test_ab("a like b", "abcd", "?bc?" , T(1.0)), + test_ab("a like b", "abcd", "ab**" , T(1.0)), + test_ab("a like b", "abcd", "ab*?" , T(1.0)), + test_ab("a like b", "abcd", "a***" , T(1.0)), + test_ab("a like b", "abcd", "**cd" , T(1.0)), + test_ab("a like b", "abcd", "*?cd" , T(1.0)), + test_ab("a like b", "abcd", "***d" , T(1.0)), + test_ab("a like b", "abcd", "*bc*" , T(1.0)), + test_ab("a like b", "abcd", "*bc?" , T(1.0)), + test_ab("a like b", "abcd", "*b??" , T(1.0)), + test_ab("a like b", "abcd", "?bc*" , T(1.0)), + test_ab("a like b", "abcd", "??c*" , T(1.0)), + test_ab("a like b", "abcd", "*b?*" , T(1.0)), + test_ab("a like b", "ab" , "a*" , T(1.0)), + test_ab("a like b", "ab" , "a?" , T(1.0)), + + test_ab("a ilike b", "aBcD", "abcd*", T(1.0)), + test_ab("a ilike b", "aBcD", "abcd" , T(1.0)), + test_ab("a ilike b", "aBcD", "abc*" , T(1.0)), + test_ab("a ilike b", "aBcD", "*bcd" , T(1.0)), + test_ab("a ilike b", "aBcD", "abc?" , T(1.0)), + test_ab("a ilike b", "aBcD", "?bcd" , T(1.0)), + test_ab("a ilike b", "aBcD", "ab?d" , T(1.0)), + test_ab("a ilike b", "aBcD", "ab*d" , T(1.0)), + test_ab("a ilike b", "aBcD", "a?cd" , T(1.0)), + test_ab("a ilike b", "aBcD", "a*cd" , T(1.0)), + test_ab("a ilike b", "aBcD", "a??d" , T(1.0)), + test_ab("a ilike b", "aBcD", "a*?d" , T(1.0)), + test_ab("a ilike b", "aBcD", "*bc*" , T(1.0)), + test_ab("a ilike b", "aBcD", "?bc?" , T(1.0)), + test_ab("a ilike b", "aBcD", "????" , T(1.0)), + test_ab("a ilike b", "aBcD", "a???" , T(1.0)), + test_ab("a ilike b", "aBcD", "ab??" , T(1.0)), + test_ab("a ilike b", "aBcD", "abc?" , T(1.0)), + test_ab("a ilike b", "aBcD", "???d" , T(1.0)), + test_ab("a ilike b", "aBcD", "??cd" , T(1.0)), + test_ab("a ilike b", "aBcD", "?bcd" , T(1.0)), + test_ab("a ilike b", "aBcD", "?b?d" , T(1.0)), + test_ab("a ilike b", "aBcD", "a?c?" , T(1.0)), + test_ab("a ilike b", "aBcD", "a??d" , T(1.0)), + test_ab("a ilike b", "aBcD", "?bc?" , T(1.0)), + test_ab("a ilike b", "aBcD", "ab**" , T(1.0)), + test_ab("a ilike b", "aBcD", "ab*?" , T(1.0)), + test_ab("a ilike b", "aBcD", "a***" , T(1.0)), + test_ab("a ilike b", "aBcD", "**cd" , T(1.0)), + test_ab("a ilike b", "aBcD", "*?cd" , T(1.0)), + test_ab("a ilike b", "aBcD", "***d" , T(1.0)), + test_ab("a ilike b", "aBcD", "*bc*" , T(1.0)), + test_ab("a ilike b", "aBcD", "*bc?" , T(1.0)), + test_ab("a ilike b", "aBcD", "*b??" , T(1.0)), + test_ab("a ilike b", "aBcD", "?bc*" , T(1.0)), + test_ab("a ilike b", "aBcD", "??c*" , T(1.0)), + test_ab("a ilike b", "aBcD", "*b?*" , T(1.0)), + test_ab("a ilike b", "aB" , "a*" , T(1.0)), + test_ab("a ilike b", "aB" , "a?" , T(1.0)) + }; static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab); @@ -2796,10 +2907,10 @@ inline bool run_test02() std::string s1; const std::string expression_str = - " s0 := 'abc'; " - " s0 := (s1 := '0123456789'[2:7]); " - " s1 := 'xyz'; " - " s0 < s1; "; + " s0 := 'abc'; " + " s0 := (s1 := '0123456789'[2:8]); " + " s1 := 'xyz'; " + " s0 < s1; "; exprtk::symbol_table symbol_table; symbol_table.add_stringvar("s0" ,s0); @@ -2848,42 +2959,43 @@ inline bool run_test02() } template -inline bool run_test03() +bool run_test03() { typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; typedef exprtk::parser 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+" - "g+G6+Gg+Gg6+H+H7+hH+hH7+G+G6+GG+GG6+H+H7+HH+HH7+g+g6+gg+gg6+h+h7+hh+hh7+" - "I+I8+iI+Ii8+j+J9+Jj+jJ9+I+I8+II+II8+J+J9+JJ+JJ9+i+i8+ii+ii8+j+j9+jj+jj9+" - "k+K0+Kk+Kk0+L+L1+lL+lL1+K+K0+KK+KK0+L+L1+LL+LL1+k+k0+kk+kk0+l+l1+ll+ll1+" - "M+M2+mM+Mm2+n+N3+Nn+nN3+M+M2+MM+MM2+N+N3+NN+NN3+m+m2+mm+mm2+n+n3+nn+nn3+" - "o+O4+Oo+Oo4+P+P5+pP+pP5+O+O4+OO+OO4+P+P5+PP+PP5+o+o4+oo+oo4+p+p5+pp+pp5+" - "Q+Q6+qQ+Qq6+r+R7+Rr+rR7+Q+Q6+QQ+QQ6+R+R7+RR+RR7+q+q6+qq+qq6+r+r7+rr+rr7+" - "s+S8+Ss+Ss8+T+T9+tT+tT9+S+S8+SS+SS8+T+T9+TT+TT9+s+s8+ss+ss8+t+t9+tt+tt9+" - "U+U0+uU+Uu0+v+V1+Vv+vV1+U+U0+UU+UU0+V+V1+VV+VV1+u+u0+uu+uu0+v+v1+vv+vv1+" - "w+W2+Ww+Ww2+X+X3+xX+xX3+W+W2+WW+WW2+X+X3+XX+XX3+w+w2+ww+ww2+x+x3+xx+xx3+" - "Y+Y4+yY+Yy4+z+Z5+Zz+zZ5+Y+Y4+YY+YY4+Z+Z5+ZZ+ZZ5+y+y4+yy+yy4+z+z5+zz+zz5 "; + const 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+" + "g+G6+Gg+Gg6+H+H7+hH+hH7+G+G6+GG+GG6+H+H7+HH+HH7+g+g6+gg+gg6+h+h7+hh+hh7+" + "I+I8+iI+Ii8+j+J9+Jj+jJ9+I+I8+II+II8+J+J9+JJ+JJ9+i+i8+ii+ii8+j+j9+jj+jj9+" + "k+K0+Kk+Kk0+L+L1+lL+lL1+K+K0+KK+KK0+L+L1+LL+LL1+k+k0+kk+kk0+l+l1+ll+ll1+" + "M+M2+mM+Mm2+n+N3+Nn+nN3+M+M2+MM+MM2+N+N3+NN+NN3+m+m2+mm+mm2+n+n3+nn+nn3+" + "o+O4+Oo+Oo4+P+P5+pP+pP5+O+O4+OO+OO4+P+P5+PP+PP5+o+o4+oo+oo4+p+p5+pp+pp5+" + "Q+Q6+qQ+Qq6+r+R7+Rr+rR7+Q+Q6+QQ+QQ6+R+R7+RR+RR7+q+q6+qq+qq6+r+r7+rr+rr7+" + "s+S8+Ss+Ss8+T+T9+tT+tT9+S+S8+SS+SS8+T+T9+TT+TT9+s+s8+ss+ss8+t+t9+tt+tt9+" + "U+U0+uU+Uu0+v+V1+Vv+vV1+U+U0+UU+UU0+V+V1+VV+VV1+u+u0+uu+uu0+v+v1+vv+vv1+" + "w+W2+Ww+Ww2+X+X3+xX+xX3+W+W2+WW+WW2+X+X3+XX+XX3+w+w2+ww+ww2+x+x3+xx+xx3+" + "Y+Y4+yY+Yy4+z+Z5+Zz+zZ5+Y+Y4+YY+YY4+Z+Z5+ZZ+ZZ5+y+y4+yy+yy4+z+z5+zz+zz5 "; static const std::string variable_list[] = - { - "A", "A0", "aA", "Aa0", "b", "B1", "Bb", "bB1", - "c", "C2", "Cc", "Cc2", "D", "D3", "dD", "dD3", - "E", "E4", "eE", "Ee4", "f", "F5", "Ff", "fF5", - "g", "G6", "Gg", "Gg6", "H", "H7", "hH", "hH7", - "I", "I8", "iI", "Ii8", "j", "J9", "Jj", "jJ9", - "k", "K0", "Kk", "Kk0", "L", "L1", "lL", "lL1", - "M", "M2", "mM", "Mm2", "n", "N3", "Nn", "nN3", - "o", "O4", "Oo", "Oo4", "P", "P5", "pP", "pP5", - "Q", "Q6", "qQ", "Qq6", "r", "R7", "Rr", "rR7", - "s", "S8", "Ss", "Ss8", "T", "T9", "tT", "tT9", - "U", "U0", "uU", "Uu0", "v", "V1", "Vv", "vV1", - "w", "W2", "Ww", "Ww2", "X", "X3", "xX", "xX3", - "Y", "Y4", "yY", "Yy4", "z", "Z5", "Zz", "zZ5" - }; + { + "A", "A0", "aA", "Aa0", "b", "B1", "Bb", "bB1", + "c", "C2", "Cc", "Cc2", "D", "D3", "dD", "dD3", + "E", "E4", "eE", "Ee4", "f", "F5", "Ff", "fF5", + "g", "G6", "Gg", "Gg6", "H", "H7", "hH", "hH7", + "I", "I8", "iI", "Ii8", "j", "J9", "Jj", "jJ9", + "k", "K0", "Kk", "Kk0", "L", "L1", "lL", "lL1", + "M", "M2", "mM", "Mm2", "n", "N3", "Nn", "nN3", + "o", "O4", "Oo", "Oo4", "P", "P5", "pP", "pP5", + "Q", "Q6", "qQ", "Qq6", "r", "R7", "Rr", "rR7", + "s", "S8", "Ss", "Ss8", "T", "T9", "tT", "tT9", + "U", "U0", "uU", "Uu0", "v", "V1", "Vv", "vV1", + "w", "W2", "Ww", "Ww2", "X", "X3", "xX", "xX3", + "Y", "Y4", "yY", "Yy4", "z", "Z5", "Zz", "zZ5" + }; static const std::size_t variable_list_size = sizeof(variable_list) / sizeof(std::string); @@ -2942,88 +3054,92 @@ inline bool run_test03() { static const std::string invalid_expr[] = - { - "x y", - "x y z", - "x y z w", - "x 1", - "x 1 2", - "x 1 2 3", - "x 'abc'", - "x 1 'abc'", - "x 'abc' 1", - "1 2", - "1 2 3", - "1 2 3 4", - "'abc' 'xyz'", - "'abc' 1", - "1 'abc'", - "x sin(1)", - "s 'abc'", - "s x", - "s y", - "s 1", - "s 1 x", - "s 1 y", - "s x 1", - "s y 1", - "x s ", - "y s ", - "1 s ", - "1 s x", - "1 s y", - "x s 1", - "y s 1", - "v 'abc'", - "v x ", - "v y ", - "v s ", - "v 1 ", - "v 1 x", - "v 1 y", - "v 1 s", - "v x 1", - "v y 1", - "v s 1", - "x v ", - "y v ", - "1 v ", - "1 v x", - "1 v y", - "x 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" - }; + { + "x y", + "x y z", + "x y z w", + "x 1", + "x 1 2", + "x 1 2 3", + "x 'abc'", + "x 1 'abc'", + "x 'abc' 1", + "1 2", + "1 2 3", + "1 2 3 4", + "'abc' 'xyz'", + "'abc' 1", + "1 'abc'", + "x sin(1)", + "s 'abc'", + "s x", + "s y", + "s 1", + "s 1 x", + "s 1 y", + "s x 1", + "s y 1", + "x s ", + "y s ", + "1 s ", + "1 s x", + "1 s y", + "x s 1", + "y s 1", + "v 'abc'", + "v x ", + "v y ", + "v s ", + "v 1 ", + "v 1 x", + "v 1 y", + "v 1 s", + "v x 1", + "v y 1", + "v s 1", + "x v ", + "y v ", + "1 v ", + "1 v x", + "1 v y", + "x v 1", + "y v 1", + + "(x == 'a string' )", + "(x == 'a string'[1:3] )", + "(x == 'a string' + 'b string' )", + "(x == ('a string' + 'b string')[3:6])", + "('a string' == x )", + "('a string'[1:3] == x )", + "('a string' + 'b string' == x )", + "(('a string' + 'b string')[3:6] == 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", + + "var vv[4] := [0]; v[k]", + "var vv[4] := [0]; v[k + 1]", + "var vv[4] := [0]; v[1 + k]" + }; const std::size_t invalid_expr_size = sizeof(invalid_expr) / sizeof(std::string); @@ -3044,7 +3160,7 @@ inline bool run_test03() 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 successfully. Expression: %s\n", invalid_expr[i].c_str()); return false; @@ -3070,7 +3186,7 @@ inline bool run_test03() if (parser.compile(invalid_expr[i],expression)) { - printf("run_test03() - Error: [2] Invalid expression compiled successfuly. Expression: %s\n", + printf("run_test03() - Error: [2] Invalid expression compiled successfully. Expression: %s\n", invalid_expr[i].c_str()); return false; @@ -3080,11 +3196,11 @@ 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)"; + "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"; + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789^+-/*,;:<>=%?[]{}() #&'\"\\\t\r\n"; symbol_table_t symbol_table; expression_t expression; @@ -3147,9 +3263,9 @@ inline T clamp(const T& l, const T& v, const T& u) } template -inline bool run_test04() +bool run_test04() { - std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(y / 2 * pi),+1.0)"; + const std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(y / 2 * pi),+1.0)"; exprtk::symbol_table symbol_table; exprtk::expression expression; @@ -3204,12 +3320,13 @@ inline bool run_test04() } template -inline bool run_test05() +bool run_test05() { typedef exprtk::expression expression_t; - std::string expression_string = "clamp(-1.0,sin(2 * pi * x_var123) + cos(y_var123 / 2 * pi),+1.0)"; - exprtk::symbol_table symbol_table; + const std::string expression_string = "clamp(-1.0,sin(2 * pi * x_var123) + cos(y_var123 / 2 * pi),+1.0)"; + + exprtk::symbol_table symbol_table; std::deque expression_list; T x = T(-1000); @@ -3276,10 +3393,11 @@ inline bool run_test05() } template -inline bool run_test06() +bool run_test06() { typedef exprtk::expression expression_t; - std::string expression_string = "sqrt(1 - (x^2))"; + + const std::string expression_string = "sqrt(1 - (x^2))"; T x = T(0); @@ -3325,10 +3443,11 @@ inline bool run_test06() } template -inline bool run_test07() +bool run_test07() { typedef exprtk::expression expression_t; - std::string expression_string = "sin(2x + 1 / 3)"; + + const std::string expression_string = "sin(2x + 1 / 3)"; T x = T(0); @@ -3424,147 +3543,148 @@ inline bool run_test07() } template -inline bool run_test08() +bool run_test08() { static const std::string expr_str[] = - { - "x", "y", "z", "w", "u", - "x + y + z + w + u", - "x + y / z * w ^ u", - "x:=1.1", "y:=2.2", "z:=3.3", "w:=4.4", "u:=5.5", - "x:=x+1.1", "y:=y+2.2", "z:=z+3.3", "w:=w+4.4", "u:=u+5.5", - "x:=1.1+x", "y:=2.2+y", "z:=3.3+z", "w:=4.4+w", "u:=5.5+u", - "x:=(x <= 1.1)", - "y:=(2.2 >= y)", - "z:=(3.3 and z)", - "w:=(4.4 or w)", - "u:=(u xor 5.5)", - "min(x,y) + min(x,y,z) + min(x,y,z,w) + min(x,y,z,w,y)", - "max(x,y) + max(x,y,z) + max(x,y,z,w) + max(x,y,z,w,y)", - "avg(x,y)", - "avg(x,y,z)", - "avg(x,y,z,w)", - "avg(x,y,z,w,u)", - "(u := u := min(x:=1,y:=2,z:=3)) == 1", - "(2x+3y+4z+5w)==(2*x+3*y+4*z+5*w)", - "(3(x+y)/2+1)==(3*(x+y)/2+1)", - "((x+y)3+1/4)==((x+y)*3+1/4)", - "((x+y)z+1/2)==((x+y)*z+1/2)", - "(x+y^3/z) == (x+(y*y*y)/z)", - "(z-x^3+y^2*7) == (z-(x*x*x)+(y*y)*7)", - "(3min(x,y))==(3*min(x,y))", - "(sin(x)y)==(sin(x)*y)", - "(sin(x)cos(y)+1)==(sin(x)*cos(y)+1)", - "(sgn(sin(x))cos(sgn(y))+1)==(sgn(sin(x))*cos(sgn(y))+1)", - "equal($f00(x,y,z),(x+y)/z)", - "equal($f01(x,y,z),(x+y)*z)", - "equal($f02(x,y,z),(x+y)-z)", - "equal($f03(x,y,z),(x+y)+z)", - "equal($f04(x,y,z),(x-y)+z)", - "equal($f05(x,y,z),(x-y)/z)", - "equal($f06(x,y,z),(x-y)*z)", - "equal($f07(x,y,z),(x*y)+z)", - "equal($f08(x,y,z),(x*y)-z)", - "equal($f09(x,y,z),(x*y)/z)", - "equal($f10(x,y,z),(x*y)*z)", - "equal($f11(x,y,z),(x/y)+z)", - "equal($f12(x,y,z),(x/y)-z)", - "equal($f13(x,y,z),(x/y)/z)", - "equal($f14(x,y,z),(x/y)*z)", - "equal($f15(x,y,z),x/(y+z))", - "equal($f16(x,y,z),x/(y-z))", - "equal($f17(x,y,z),x/(y*z))", - "equal($f18(x,y,z),x/(y/z))", - "equal($f19(x,y,z),x*(y+z))", - "equal($f20(x,y,z),x*(y-z))", - "equal($f21(x,y,z),x*(y*z))", - "equal($f22(x,y,z),x*(y/z))", - "equal($f23(x,y,z),x-(y+z))", - "equal($f24(x,y,z),x-(y-z))", - "equal($f25(x,y,z),x-(y/z))", - "equal($f26(x,y,z),x-(y*z))", - "equal($f27(x,y,z),x+(y*z))", - "equal($f28(x,y,z),x+(y/z))", - "equal($f29(x,y,z),x+(y+z))", - "equal($f30(x,y,z),x+(y-z))", - "equal($f31(x,y,z),x*y^2+z)", - "equal($f32(x,y,z),x*y^3+z)", - "equal($f33(x,y,z),x*y^4+z)", - "equal($f34(x,y,z),x*y^5+z)", - "equal($f35(x,y,z),x*y^6+z)", - "equal($f36(x,y,z),x*y^7+z)", - "equal($f37(x,y,z),x*y^8+z)", - "equal($f38(x,y,z),x*y^9+z)", - "equal($f39(x,y,z),x*log(y)+z)", - "equal($f40(x,y,z),x*log(y)-z)", - "equal($f41(x,y,z),x*log10(y)+z)", - "equal($f42(x,y,z),x*log10(y)-z)", - "equal($f43(x,y,z),x*sin(y)+z)", - "equal($f44(x,y,z),x*sin(y)-z)", - "equal($f45(x,y,z),x*cos(y)+z)", - "equal($f46(x,y,z),x*cos(y)-z)", - "equal($f47(x,y,z),if(0!=x,y,z))", - "equal($f48(x,y,z,w),x+((y+z)/w))", - "equal($f49(x,y,z,w),x+((y+z)*w))", - "equal($f50(x,y,z,w),x+((y-z)/w))", - "equal($f51(x,y,z,w),x+((y-z)*w))", - "equal($f52(x,y,z,w),x+((y*z)/w))", - "equal($f53(x,y,z,w),x+((y*z)*w))", - "equal($f54(x,y,z,w),x+((y/z)+w))", - "equal($f55(x,y,z,w),x+((y/z)/w))", - "equal($f56(x,y,z,w),x+((y/z)*w))", - "equal($f57(x,y,z,w),x-((y+z)/w))", - "equal($f58(x,y,z,w),x-((y+z)*w))", - "equal($f59(x,y,z,w),x-((y-z)/w))", - "equal($f60(x,y,z,w),x-((y-z)*w))", - "equal($f61(x,y,z,w),x-((y*z)/w))", - "equal($f62(x,y,z,w),x-((y*z)*w))", - "equal($f63(x,y,z,w),x-((y/z)/w))", - "equal($f64(x,y,z,w),x-((y/z)*w))", - "equal($f65(x,y,z,w),((x+y)*z)-w)", - "equal($f66(x,y,z,w),((x-y)*z)-w)", - "equal($f67(x,y,z,w),((x*y)*z)-w)", - "equal($f68(x,y,z,w),((x/y)*z)-w)", - "equal($f69(x,y,z,w),((x+y)/z)-w)", - "equal($f70(x,y,z,w),((x-y)/z)-w)", - "equal($f71(x,y,z,w),((x*y)/z)-w)", - "equal($f72(x,y,z,w),((x/y)/z)-w)", - "equal($f73(x,y,z,w),(x*y)+(z*w))", - "equal($f74(x,y,z,w),(x*y)-(z*w))", - "equal($f75(x,y,z,w),(x*y)+(z/w))", - "equal($f76(x,y,z,w),(x*y)-(z/w))", - "equal($f77(x,y,z,w),(x/y)+(z/w))", - "equal($f78(x,y,z,w),(x/y)-(z/w))", - "equal($f79(x,y,z,w),(x/y)-(z*w))", - "equal($f80(x,y,z,w),x/(y+(z*w)))", - "equal($f81(x,y,z,w),x/(y-(z*w)))", - "equal($f82(x,y,z,w),x*(y+(z*w)))", - "equal($f83(x,y,z,w),x*(y-(z*w)))", - "equal($f84(x,y,z,w),x*y^2+z*w^2)", - "equal($f85(x,y,z,w),x*y^3+z*w^3)", - "equal($f86(x,y,z,w),x*y^4+z*w^4)", - "equal($f87(x,y,z,w),x*y^5+z*w^5)", - "equal($f88(x,y,z,w),x*y^6+z*w^6)", - "equal($f89(x,y,z,w),x*y^7+z*w^7)", - "equal($f90(x,y,z,w),x*y^8+z*w^8)", - "equal($f91(x,y,z,w),x*y^9+z*w^9)", - "equal($f92(x,y,z,w),if(x and y,z,w))", - "equal($f93(x,y,z,w),if(x or y,z,w))", - "equal($f94(x,y,z,w),if(x < y,z,w))", - "equal($f95(x,y,z,w),if(x <= y,z,w))", - "equal($f96(x,y,z,w),if(x > y,z,w))", - "equal($f97(x,y,z,w),if(x >= y,z,w))", - "equal($f98(x,y,z,w),if(equal(x,y),z,w))", - "equal($f92(x,y,z,w),x and y ? z : w)", - "equal($f93(x,y,z,w),x or y ? z : w)", - "equal($f94(x,y,z,w),x < y ? z : w)", - "equal($f95(x,y,z,w),x <= y ? z : w)", - "equal($f96(x,y,z,w),x > y ? z : w)", - "equal($f97(x,y,z,w),x >= y ? z : w)", - "equal($f98(x,y,z,w),equal(x,y) ? z : w)", - "equal($f99(x,y,z,w),x*sin(y)+z*cos(w))" - }; + { + "x", "y", "z", "w", "u", + "x + y + z + w + u", + "x + y / z * w ^ u", + "x:=1.1", "y:=2.2", "z:=3.3", "w:=4.4", "u:=5.5", + "x:=x+1.1", "y:=y+2.2", "z:=z+3.3", "w:=w+4.4", "u:=u+5.5", + "x:=1.1+x", "y:=2.2+y", "z:=3.3+z", "w:=4.4+w", "u:=5.5+u", + "x:=(x <= 1.1)", + "y:=(2.2 >= y)", + "z:=(3.3 and z)", + "w:=(4.4 or w)", + "u:=(u xor 5.5)", + "min(x,y) + min(x,y,z) + min(x,y,z,w) + min(x,y,z,w,y)", + "max(x,y) + max(x,y,z) + max(x,y,z,w) + max(x,y,z,w,y)", + "avg(x,y)", + "avg(x,y,z)", + "avg(x,y,z,w)", + "avg(x,y,z,w,u)", + "(u := u := min(x:=1,y:=2,z:=3)) == 1", + "(2x+3y+4z+5w)==(2*x+3*y+4*z+5*w)", + "(3(x+y)/2+1)==(3*(x+y)/2+1)", + "((x+y)3+1/4)==((x+y)*3+1/4)", + "((x+y)z+1/2)==((x+y)*z+1/2)", + "(x+y^3/z) == (x+(y*y*y)/z)", + "(z-x^3+y^2*7) == (z-(x*x*x)+(y*y)*7)", + "(3min(x,y))==(3*min(x,y))", + "(sin(x)y)==(sin(x)*y)", + "(sin(x)cos(y)+1)==(sin(x)*cos(y)+1)", + "(sgn(sin(x))cos(sgn(y))+1)==(sgn(sin(x))*cos(sgn(y))+1)", + "equal($f00(x,y,z),(x+y)/z)", + "equal($f01(x,y,z),(x+y)*z)", + "equal($f02(x,y,z),(x+y)-z)", + "equal($f03(x,y,z),(x+y)+z)", + "equal($f04(x,y,z),(x-y)+z)", + "equal($f05(x,y,z),(x-y)/z)", + "equal($f06(x,y,z),(x-y)*z)", + "equal($f07(x,y,z),(x*y)+z)", + "equal($f08(x,y,z),(x*y)-z)", + "equal($f09(x,y,z),(x*y)/z)", + "equal($f10(x,y,z),(x*y)*z)", + "equal($f11(x,y,z),(x/y)+z)", + "equal($f12(x,y,z),(x/y)-z)", + "equal($f13(x,y,z),(x/y)/z)", + "equal($f14(x,y,z),(x/y)*z)", + "equal($f15(x,y,z),x/(y+z))", + "equal($f16(x,y,z),x/(y-z))", + "equal($f17(x,y,z),x/(y*z))", + "equal($f18(x,y,z),x/(y/z))", + "equal($f19(x,y,z),x*(y+z))", + "equal($f20(x,y,z),x*(y-z))", + "equal($f21(x,y,z),x*(y*z))", + "equal($f22(x,y,z),x*(y/z))", + "equal($f23(x,y,z),x-(y+z))", + "equal($f24(x,y,z),x-(y-z))", + "equal($f25(x,y,z),x-(y/z))", + "equal($f26(x,y,z),x-(y*z))", + "equal($f27(x,y,z),x+(y*z))", + "equal($f28(x,y,z),x+(y/z))", + "equal($f29(x,y,z),x+(y+z))", + "equal($f30(x,y,z),x+(y-z))", + "equal($f31(x,y,z),x*y^2+z)", + "equal($f32(x,y,z),x*y^3+z)", + "equal($f33(x,y,z),x*y^4+z)", + "equal($f34(x,y,z),x*y^5+z)", + "equal($f35(x,y,z),x*y^6+z)", + "equal($f36(x,y,z),x*y^7+z)", + "equal($f37(x,y,z),x*y^8+z)", + "equal($f38(x,y,z),x*y^9+z)", + "equal($f39(x,y,z),x*log(y)+z)", + "equal($f40(x,y,z),x*log(y)-z)", + "equal($f41(x,y,z),x*log10(y)+z)", + "equal($f42(x,y,z),x*log10(y)-z)", + "equal($f43(x,y,z),x*sin(y)+z)", + "equal($f44(x,y,z),x*sin(y)-z)", + "equal($f45(x,y,z),x*cos(y)+z)", + "equal($f46(x,y,z),x*cos(y)-z)", + "equal($f47(x,y,z),if(0!=x,y,z))", + "equal($f48(x,y,z,w),x+((y+z)/w))", + "equal($f49(x,y,z,w),x+((y+z)*w))", + "equal($f50(x,y,z,w),x+((y-z)/w))", + "equal($f51(x,y,z,w),x+((y-z)*w))", + "equal($f52(x,y,z,w),x+((y*z)/w))", + "equal($f53(x,y,z,w),x+((y*z)*w))", + "equal($f54(x,y,z,w),x+((y/z)+w))", + "equal($f55(x,y,z,w),x+((y/z)/w))", + "equal($f56(x,y,z,w),x+((y/z)*w))", + "equal($f57(x,y,z,w),x-((y+z)/w))", + "equal($f58(x,y,z,w),x-((y+z)*w))", + "equal($f59(x,y,z,w),x-((y-z)/w))", + "equal($f60(x,y,z,w),x-((y-z)*w))", + "equal($f61(x,y,z,w),x-((y*z)/w))", + "equal($f62(x,y,z,w),x-((y*z)*w))", + "equal($f63(x,y,z,w),x-((y/z)/w))", + "equal($f64(x,y,z,w),x-((y/z)*w))", + "equal($f65(x,y,z,w),((x+y)*z)-w)", + "equal($f66(x,y,z,w),((x-y)*z)-w)", + "equal($f67(x,y,z,w),((x*y)*z)-w)", + "equal($f68(x,y,z,w),((x/y)*z)-w)", + "equal($f69(x,y,z,w),((x+y)/z)-w)", + "equal($f70(x,y,z,w),((x-y)/z)-w)", + "equal($f71(x,y,z,w),((x*y)/z)-w)", + "equal($f72(x,y,z,w),((x/y)/z)-w)", + "equal($f73(x,y,z,w),(x*y)+(z*w))", + "equal($f74(x,y,z,w),(x*y)-(z*w))", + "equal($f75(x,y,z,w),(x*y)+(z/w))", + "equal($f76(x,y,z,w),(x*y)-(z/w))", + "equal($f77(x,y,z,w),(x/y)+(z/w))", + "equal($f78(x,y,z,w),(x/y)-(z/w))", + "equal($f79(x,y,z,w),(x/y)-(z*w))", + "equal($f80(x,y,z,w),x/(y+(z*w)))", + "equal($f81(x,y,z,w),x/(y-(z*w)))", + "equal($f82(x,y,z,w),x*(y+(z*w)))", + "equal($f83(x,y,z,w),x*(y-(z*w)))", + "equal($f84(x,y,z,w),x*y^2+z*w^2)", + "equal($f85(x,y,z,w),x*y^3+z*w^3)", + "equal($f86(x,y,z,w),x*y^4+z*w^4)", + "equal($f87(x,y,z,w),x*y^5+z*w^5)", + "equal($f88(x,y,z,w),x*y^6+z*w^6)", + "equal($f89(x,y,z,w),x*y^7+z*w^7)", + "equal($f90(x,y,z,w),x*y^8+z*w^8)", + "equal($f91(x,y,z,w),x*y^9+z*w^9)", + "equal($f92(x,y,z,w),if(x and y,z,w))", + "equal($f93(x,y,z,w),if(x or y,z,w))", + "equal($f94(x,y,z,w),if(x < y,z,w))", + "equal($f95(x,y,z,w),if(x <= y,z,w))", + "equal($f96(x,y,z,w),if(x > y,z,w))", + "equal($f97(x,y,z,w),if(x >= y,z,w))", + "equal($f98(x,y,z,w),if(equal(x,y),z,w))", + "equal($f92(x,y,z,w),x and y ? z : w)", + "equal($f93(x,y,z,w),x or y ? z : w)", + "equal($f94(x,y,z,w),x < y ? z : w)", + "equal($f95(x,y,z,w),x <= y ? z : w)", + "equal($f96(x,y,z,w),x > y ? z : w)", + "equal($f97(x,y,z,w),x >= y ? z : w)", + "equal($f98(x,y,z,w),equal(x,y) ? z : w)", + "equal($f99(x,y,z,w),x*sin(y)+z*cos(w))" + }; + static const std::size_t expr_str_size = sizeof(expr_str) / sizeof(std::string); static const std::size_t rounds = 25; @@ -3612,7 +3732,7 @@ inline bool run_test08() } template -struct myfunc : public exprtk::ifunction +struct myfunc exprtk_test_final : public exprtk::ifunction { using exprtk::ifunction::operator(); @@ -3624,45 +3744,47 @@ struct myfunc : public exprtk::ifunction } }; -#define define_free_functions(N,Type) \ -Type N##1(Type v0) { return v0; } \ -Type N##2(Type v0, Type v1) { return v0 + v1; } \ -Type N##3(Type v0, Type v1, Type v2) { return v0 + v1 + v2; } \ -Type N##4(Type v0, Type v1, Type v2, Type v3) { return v0 + v1 + v2 + v3; } \ -Type N##5(Type v0, Type v1, Type v2, Type v3, Type v4) { return v0 + v1 + v2 + v3 + v4; } \ -Type N##6(Type v0, Type v1, Type v2, Type v3, Type v4, Type v5) { return v0 + v1 + v2 + v3 + v4 + v5; } \ +#define define_free_functions(N,Type) \ +inline Type N##1(Type v0) { return v0; } \ +inline Type N##2(Type v0, Type v1) { return v0 + v1; } \ +inline Type N##3(Type v0, Type v1, Type v2) { return v0 + v1 + v2; } \ +inline Type N##4(Type v0, Type v1, Type v2, Type v3) { return v0 + v1 + v2 + v3; } \ +inline Type N##5(Type v0, Type v1, Type v2, Type v3, Type v4) { return v0 + v1 + v2 + v3 + v4; } \ +inline Type N##6(Type v0, Type v1, Type v2, Type v3, Type v4, Type v5) { return v0 + v1 + v2 + v3 + v4 + v5; } \ define_free_functions(foo,numeric_type) #undef define_free_functions template -inline bool run_test09() +bool run_test09() { { static const std::size_t rounds = 1000; + for (std::size_t i = 0; i < rounds; ++i) { typedef exprtk::expression expression_t; - std::string expression_string = "myfunc0(sin(x * pi),y / 2) + myfunc1(sin(x * pi),y / 2)+" - "myfunc2(sin(x * pi),y / 2) + myfunc3(sin(x * pi),y / 2)+" - "myfunc4(sin(x * pi),y / 2) + myfunc5(sin(x * pi),y / 2)+" - "myfunc6(sin(x * pi),y / 2) + myfunc7(sin(x * pi),y / 2)+" - "myfunc8(sin(x * pi),y / 2) + myfunc9(sin(x * pi),y / 2)+" - "myfunc0(sin(x * pi),y / 2) + myfunc1(sin(x * pi),y / 2)+" - "myfunc2(sin(x * pi),y / 2) + myfunc3(sin(x * pi),y / 2)+" - "myfunc4(sin(x * pi),y / 2) + myfunc5(sin(x * pi),y / 2)+" - "myfunc6(sin(x * pi),y / 2) + myfunc7(sin(x * pi),y / 2)+" - "myfunc8(sin(x * pi),y / 2) + myfunc9(sin(x * pi),y / 2)+" - "myfunc0(sin(x * pi),y / 2) + myfunc1(sin(x * pi),y / 2)+" - "myfunc2(sin(x * pi),y / 2) + myfunc3(sin(x * pi),y / 2)+" - "myfunc4(sin(x * pi),y / 2) + myfunc5(sin(x * pi),y / 2)+" - "myfunc6(sin(x * pi),y / 2) + myfunc7(sin(x * pi),y / 2)+" - "myfunc8(sin(x * pi),y / 2) + myfunc9(sin(x * pi),y / 2)+" - "myfunc0(sin(x * pi),y / 2) + myfunc1(sin(x * pi),y / 2)+" - "myfunc2(sin(x * pi),y / 2) + myfunc3(sin(x * pi),y / 2)+" - "myfunc4(sin(x * pi),y / 2) + myfunc5(sin(x * pi),y / 2)+" - "myfunc6(sin(x * pi),y / 2) + myfunc7(sin(x * pi),y / 2)+" - "myfunc8(sin(x * pi),y / 2) + myfunc9(sin(x * pi),y / 2)"; + const std::string expression_string = + "myfunc0(sin(x * pi),y / 2) + myfunc1(sin(x * pi),y / 2)+" + "myfunc2(sin(x * pi),y / 2) + myfunc3(sin(x * pi),y / 2)+" + "myfunc4(sin(x * pi),y / 2) + myfunc5(sin(x * pi),y / 2)+" + "myfunc6(sin(x * pi),y / 2) + myfunc7(sin(x * pi),y / 2)+" + "myfunc8(sin(x * pi),y / 2) + myfunc9(sin(x * pi),y / 2)+" + "myfunc0(sin(x * pi),y / 2) + myfunc1(sin(x * pi),y / 2)+" + "myfunc2(sin(x * pi),y / 2) + myfunc3(sin(x * pi),y / 2)+" + "myfunc4(sin(x * pi),y / 2) + myfunc5(sin(x * pi),y / 2)+" + "myfunc6(sin(x * pi),y / 2) + myfunc7(sin(x * pi),y / 2)+" + "myfunc8(sin(x * pi),y / 2) + myfunc9(sin(x * pi),y / 2)+" + "myfunc0(sin(x * pi),y / 2) + myfunc1(sin(x * pi),y / 2)+" + "myfunc2(sin(x * pi),y / 2) + myfunc3(sin(x * pi),y / 2)+" + "myfunc4(sin(x * pi),y / 2) + myfunc5(sin(x * pi),y / 2)+" + "myfunc6(sin(x * pi),y / 2) + myfunc7(sin(x * pi),y / 2)+" + "myfunc8(sin(x * pi),y / 2) + myfunc9(sin(x * pi),y / 2)+" + "myfunc0(sin(x * pi),y / 2) + myfunc1(sin(x * pi),y / 2)+" + "myfunc2(sin(x * pi),y / 2) + myfunc3(sin(x * pi),y / 2)+" + "myfunc4(sin(x * pi),y / 2) + myfunc5(sin(x * pi),y / 2)+" + "myfunc6(sin(x * pi),y / 2) + myfunc7(sin(x * pi),y / 2)+" + "myfunc8(sin(x * pi),y / 2) + myfunc9(sin(x * pi),y / 2)"; T x = T(1) + (i / T(10000)); T y = T(2) + (i / T(10000)); @@ -3703,19 +3825,20 @@ inline bool run_test09() const T result = expression.value(); - const T expected = T(4) * - ( - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) + - mf(sin(x*pi),y / T(2)) - ); + const T expected = + T(4) * + ( + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + + mf(sin(x * pi), y / T(2)) + ); if (not_equal(result,expected,T(0.0000001))) { @@ -3735,14 +3858,14 @@ inline bool run_test09() bool result = true; const std::string expression_list[] = - { - "foo1(1) == 1", - "foo2(1,2) == (1 + 2)", - "foo3(1,2,3) == (1 + 2 + 3)", - "foo4(1,2,3,4) == (1 + 2 + 3 + 4)", - "foo5(1,2,3,4,5) == (1 + 2 + 3 + 4 + 5)", - "foo6(1,2,3,4,5,6) == (1 + 2 + 3 + 4 + 5 + 6)" - }; + { + "foo1(1) == 1", + "foo2(1,2) == (1 + 2)", + "foo3(1,2,3) == (1 + 2 + 3)", + "foo4(1,2,3,4) == (1 + 2 + 3 + 4)", + "foo5(1,2,3,4,5) == (1 + 2 + 3 + 4 + 5)", + "foo6(1,2,3,4,5,6) == (1 + 2 + 3 + 4 + 5 + 6)" + }; const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); @@ -3780,7 +3903,7 @@ inline bool run_test09() } template -inline bool run_test10() +bool run_test10() { typedef exprtk::expression expression_t; @@ -3824,8 +3947,8 @@ inline bool run_test10() for (std::size_t r = 0; r < rounds; ++r) { - symbol_table.add_variable("x", x); - symbol_table.add_variable("y", y); + symbol_table.add_variable("x" , x ); + symbol_table.add_variable("y" , y ); symbol_table.add_variable("xx", xx); symbol_table.add_variable("yy", yy); @@ -3994,15 +4117,15 @@ inline bool run_test10() for (std::size_t r = 0; r < rounds; ++r) { - symbol_table.add_variable("x", x); - symbol_table.add_variable("y", y); + symbol_table.add_variable("x" , x ); + symbol_table.add_variable("y" , y ); symbol_table.add_variable("xx", xx); symbol_table.add_variable("yy", yy); std::vector expected_var_list; - expected_var_list.push_back("x"); - expected_var_list.push_back("y"); + expected_var_list.push_back("x" ); + expected_var_list.push_back("y" ); expected_var_list.push_back("xx"); expected_var_list.push_back("yy"); @@ -4039,15 +4162,15 @@ inline bool run_test10() for (std::size_t r = 0; r < rounds; ++r) { - symbol_table.add_variable("x", x); - symbol_table.add_variable("y", y); + symbol_table.add_variable("x" , x ); + symbol_table.add_variable("y" , y ); symbol_table.add_variable("xx", xx); symbol_table.add_variable("yy", yy); std::vector expected_var_list; - expected_var_list.push_back("x"); - expected_var_list.push_back("y"); + expected_var_list.push_back("x" ); + expected_var_list.push_back("y" ); expected_var_list.push_back("xx"); expected_var_list.push_back("yy"); @@ -4084,15 +4207,15 @@ inline bool run_test10() for (std::size_t r = 0; r < rounds; ++r) { - symbol_table.add_stringvar("i", i_s); - symbol_table.add_stringvar("j", j_s); + symbol_table.add_stringvar("i" , i_s ); + symbol_table.add_stringvar("j" , j_s ); symbol_table.add_stringvar("ii", ii_s); symbol_table.add_stringvar("jj", jj_s); std::vector expected_var_list; - expected_var_list.push_back("i"); - expected_var_list.push_back("j"); + expected_var_list.push_back("i" ); + expected_var_list.push_back("j" ); expected_var_list.push_back("ii"); expected_var_list.push_back("jj"); @@ -4129,15 +4252,15 @@ inline bool run_test10() for (std::size_t r = 0; r < rounds; ++r) { - symbol_table.add_stringvar("i", i_s); - symbol_table.add_stringvar("j", j_s); + symbol_table.add_stringvar("i" , i_s ); + symbol_table.add_stringvar("j" , j_s ); symbol_table.add_stringvar("ii", ii_s); symbol_table.add_stringvar("jj", jj_s); std::vector expected_var_list; - expected_var_list.push_back("i"); - expected_var_list.push_back("j"); + expected_var_list.push_back("i" ); + expected_var_list.push_back("j" ); expected_var_list.push_back("ii"); expected_var_list.push_back("jj"); @@ -4324,10 +4447,11 @@ inline bool run_test10() expression_t expression; expression.register_symbol_table(symbol_table); - std::string expression_string = "a := b + c; " - "b := c + d; " - "c := d + 1; " - "e := e + 'abc'; "; + const std::string expression_string = + "a := b + c; " + "b := c + d; " + "c := d + 1; " + "e := e + 'abc'; "; typedef exprtk::parser parser_t; typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; @@ -4427,8 +4551,8 @@ 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]); }"; + "for (var i := 0; i < min(x[],y[],z[]); i += 1)" + "{ z[i] := 3sin(x[i]) + 2log(y[i]); }"; std::vector var_symbol_list; std::vector func_symbol_list; @@ -4466,7 +4590,7 @@ inline bool run_test10() expected_var_symbol_list.begin()); if (!var_result) { - printf("run_test10() - Failed collected variable comparison between recieved and expected variables\n"); + printf("run_test10() - Failed collected variable comparison between received and expected variables\n"); return false; } @@ -4476,437 +4600,544 @@ inline bool run_test10() expected_func_symbol_list.begin()); if (!func_result) { - printf("run_test10() - Failed collected fuctions comparison between recieved and expected functions\n"); + printf("run_test10() - Failed collected functions comparison between received and expected functions\n"); return false; } } { - std::string expression_list[] = - { - "var x; 1", - "var x := 1; x", - "var x:= 1; x - -1 == 2", - "var x:= 1; x --1 == 2", - "var x:= 1; x-- 1 == 2", - "var x:= 1; x--1 == 2", - "var x:= 1; x -- -1== 0", - "var x:= 1; x + -1 == 0", - "var x:= 1; x +-1 == 0", - "var x:= 1; x+- 1 == 0", - "var x:= 1; x+-1 == 0", - "var x:= 1; x +- -1== 2", - "var x:= 1; x + +1 == 2", - "var x:= 1; x ++1 == 2", - "var x:= 1; 1 - -x == 2", - "var x:= 1; 1 --x == 2", - "var x:= 1; 1-- x == 2", - "var x:= 1; 1--x == 2", - "var x:= 1; 1 -- -x== 0", - "var x:= 1; 1 + -x == 0", - "var x:= 1; 1 +-x == 0", - "var x:= 1; 1+- x == 0", - "var x:= 1; 1+-x == 0", - "var x:= 1; 1 +- -x== 2", - "var x:= 1; 1 + +x == 2", - "var x:= 1; 1 ++x == 2", - "var x:= 1; (x - -1 + 1) == 3", - "var x:= 1; (x --1 + 1) == 3", - "var x:= 1; (x-- 1 + 1) == 3", - "var x:= 1; (x--1 + 1) == 3", - "var x:= 1; (x -- -1 + 1) == 1", - "var x:= 1; (x + -1 + 1) == 1", - "var x:= 1; (x +-1 + 1) == 1", - "var x:= 1; (x+- 1 + 1) == 1", - "var x:= 1; (x+-1 + 1) == 1", - "var x:= 1; (x +- -1 + 1) == 3", - "var x:= 1; (x + +1 + 1) == 3", - "var x:= 1; (x ++1 + 1) == 3", - "var x:= 1; (1 - -x + 1) == 3", - "var x:= 1; (1 --x + 1) == 3", - "var x:= 1; (1-- x + 1) == 3", - "var x:= 1; (1--x + 1) == 3", - "var x:= 1; (1 -- -x + 1) == 1", - "var x:= 1; (1 + -x + 1) == 1", - "var x:= 1; (1 +-x + 1) == 1", - "var x:= 1; (1+- x + 1) == 1", - "var x:= 1; (1+-x + 1) == 1", - "var x:= 1; (1 +- -x + 1) == 3", - "var x:= 1; (1 + +x + 1) == 3", - "var x:= 1; (1 ++x + 1) == 3", - "var x:= 1; (x - -1 - 1) == 1", - "var x:= 1; (x --1 - 1) == 1", - "var x:= 1; (x-- 1 - 1) == 1", - "var x:= 1; (x--1 - 1) == 1", - "var x:= 1; (x -- -1 - 1) == -1", - "var x:= 1; (x + -1 - 1) == -1", - "var x:= 1; (x +-1 - 1) == -1", - "var x:= 1; (x+- 1 - 1) == -1", - "var x:= 1; (x+-1 - 1) == -1", - "var x:= 1; (x +- -1 - 1) == 1", - "var x:= 1; (x + +1 - 1) == 1", - "var x:= 1; (x ++1 - 1) == 1", - "var x:= 1; (1 - -x - 1) == 1", - "var x:= 1; (1 --x - 1) == 1", - "var x:= 1; (1-- x - 1) == 1", - "var x:= 1; (1--x - 1) == 1", - "var x:= 1; (1 -- -x - 1) == -1", - "var x:= 1; (1 + -x - 1) == -1", - "var x:= 1; (1 +-x - 1) == -1", - "var x:= 1; (1+- x - 1) == -1", - "var x:= 1; (1+-x - 1) == -1", - "var x:= 1; (1 +- -x - 1) == 1", - "var x:= 1; (1 + +x - 1) == 1", - "var x:= 1; (1 ++x - 1) == 1", - "var x := 1; var y := 2; 1", - "var x := 1; var y := 2; x", - "var x:=6; var y:=4; x + -3 == 3", - "var x:=6; var y:=4; x - -3 == 9", - "var x:=6; var y:=4; x * -3 == -18", - "var x:=6; var y:=4; x / -3 == -2", - "var x:=6; var y:=4; -x + -3 == -9", - "var x:=6; var y:=4; -x - -3 == -3", - "var x:=6; var y:=4; -x * -3 == 18", - "var x:=6; var y:=4; -x / -3 == 2", - "var x:=6; var y:=4; -3 + -x == -9", - "var x:=6; var y:=4; -3 - -x == 3", - "var x:=6; var y:=4; -3 * -x == 18", - "var x:=6; var y:=4; -3 / -x == 0.5", - "var x:=6; var y:=4; 3 + -x == -3", - "var x:=6; var y:=4; 3 - -x == 9", - "var x:=6; var y:=4; 3 * -x == -18", - "var x:=6; var y:=4; 3 / -x == -0.5", - "var x := 3; var y := 6; x + -y == -3", - "var x := 3; var y := 6; x - -y == 9", - "var x := 3; var y := 6; -x + -y == -9", - "var x := 3; var y := 6; -x - -y == 3", - "var x := 3; var y := 6; -x * -y == 18", - "var x := 6; var y := 3; -x / -y == 2", - "var x := 3; var y := 6; -(-x * -y) == -18", - "var x := 6; var y := 3; -(-x / -y) == -2", - "var x:=1; 2+(3+abs(x)) == 6 ", - "var x:=1; (3+abs(x))+2 == 6 ", - "var x:=1; 2+(abs(x)+3) == 6 ", - "var x:=1; (abs(x)+3)+2 == 6 ", - "var x:=1; 2+(3-abs(x)) == 4 ", - "var x:=1; (3-abs(x))+2 == 4 ", - "var x:=1; 2+(abs(x)-3) == 0 ", - "var x:=1; (abs(x)-3)+2 == 0 ", - "var x:=1; 2-(3+abs(x)) == -2 ", - "var x:=1; (3+abs(x))-2 == 2 ", - "var x:=1; 2-(abs(x)+3) == -2 ", - "var x:=1; (abs(x)+3)-2 == 2 ", - "var x:=1; 2*(3*abs(x)) == 6 ", - "var x:=1; (3*abs(x))*2 == 6 ", - "var x:=1; 2*(abs(x)*3) == 6 ", - "var x:=1; (abs(x)*3)*2 == 6 ", - "var x:=1; 2*(3/abs(x)) == 6 ", - "var x:=1; (3/abs(x))*2 == 6 ", - "var x:=1; 2*(abs(x)/3) == (2/3)", - "var x:=1; (abs(x)/3)*2 == (2/3)", - "var x:=1; 2/(3*abs(x)) == (2/3)", - "var x:=1; (3*abs(x))/2 == (3/2)", - "var x:=1; 2/(abs(x)*3) == (2/3)", - "var x:=1; (abs(x)*3)/2 == (3/2)", - "var x:=1; 2/(3/abs(x)) == (2/3)", - "var x:=1; (3/abs(x))/2 == (3/2)", - "var x:=1; 2/(abs(x)/3) == 6 ", - "var x:=1; (abs(x)/3)/2 == (1/6)", - "var x:=3; var y:=6; -(-x)*-(-y) == 18", - "var x:=3; var y:=6; -(-x)*-(-(-y)) == -18", - "var x:=3; var y:=6; -(-(-x))*-(-y) == -18", - "var x:=3; var y:=6; -(-(-x))*-(-(-y)) == 18", - "var x:=3; var y:=6; -(-(x+y))*-(-(y+x)) == 81", - "var x:=3; var y:=6; -(-(-(x+y)))*-(-(y+x)) == -81", - "var x:=3; var y:=6; -(-(x+y))*-(-(-(y+x))) == -81", - "var x:=3; var y:=6; -(-(-(x+y)))*-(-(-(y+x))) == 81", - "var x:= 2; var y := 3; (-abs(x)+-abs(y)) == -5 ", - "var x:= 2; var y := 3; (-abs(x)--abs(y)) == 1 ", - "var x:= 2; var y := 3; (-abs(x)*-abs(y)) == 6 ", - "var x:= 2; var y := 3; (-abs(x)/-abs(y)) == (2/3) ", - "var x:= 2; var y := 3; (-abs(x)+abs(y)) == 1 ", - "var x:= 2; var y := 3; (-abs(x)-abs(y)) == -5 ", - "var x:= 2; var y := 3; (-abs(x)*abs(y)) == -6 ", - "var x:= 2; var y := 3; (-abs(x)/abs(y)) == -(2/3) ", - "var x:= 2; var y := 3; (abs(x)+-abs(y)) == -1 ", - "var x:= 2; var y := 3; (abs(x)--abs(y)) == 5 ", - "var x:= 2; var y := 3; (abs(x)*-abs(y)) == -6 ", - "var x:= 2; var y := 3; (abs(x)/-abs(y)) == -(2/3) ", - "var x:= 2; var y := 3; (-abs(x + 0)+-abs(y - 0)) == -5 ", - "var x:= 2; var y := 3; (-abs(x + 0)--abs(y - 0)) == 1 ", - "var x:= 2; var y := 3; (-abs(x + 0)*-abs(y - 0)) == 6 ", - "var x:= 2; var y := 3; (-abs(x + 0)/-abs(y - 0)) == (2/3) ", - "var x:= 2; var y := 3; (-abs(x + 0)+abs(y - 0)) == 1 ", - "var x:= 2; var y := 3; (-abs(x + 0)-abs(y - 0)) == -5 ", - "var x:= 2; var y := 3; (-abs(x + 0)*abs(y - 0)) == -6 ", - "var x:= 2; var y := 3; (-abs(x + 0)/abs(y - 0)) == -(2/3) ", - "var x:= 2; var y := 3; (abs(x + 0)+-abs(y - 0)) == -1 ", - "var x:= 2; var y := 3; (abs(x + 0)--abs(y - 0)) == 5 ", - "var x:= 2; var y := 3; (abs(x + 0)*-abs(y - 0)) == -6 ", - "var x:= 2; var y := 3; (abs(x + 0)/-abs(y - 0)) == -(2/3) ", - "var x := 1; var y := 2; swap(x,y); (x == 2) and (y == 1)", - "var x := 1; var y := 2; x <=> y ; (x == 2) and (y == 1)", - "var x := 'abc'; x == 'abc' ", - "var x := 'abc'; var y := '123'; x != y ", - "var x := 'abc'; var y := x + '123'; y == 'abc123' ", - "var x := 'abc'; var y := '123' + x; y == '123abc' ", - "~{var x := '123'; x[]} + ~{var x := '1234'; x[]} == 7", - "~{var x := '123'; x[]} + ~{~{var x := '1234'; x[]}} == 7", - "~{~{var x := '123'; x[]}} + ~{var x := '1234'; x[]} == 7", - "~{var x := '123'; x[]} + ~{var x := 4} == 7", - "~{var x := 3} + ~{var x := '1234'; x[]} == 7", - "~{var x := '123'; x[]} + ~{~{var x := 4}} == 7", - "~{~{var x := 3}} + ~{var x := '1234'; x[]} == 7", - "var v[2] := {1,2}; swap(v[0],v[1]); (v[0] == 2) and (v[1] == 1)", - "var v[2] := {1,2}; v[0] <=> v[1] ; (v[0] == 2) and (v[1] == 1)", - "var x := 1; var y := 2; ~(swap(x,y),(x == 2) and (y == 1))", - "var x := 1; var y := 2; ~(x <=> y , (x == 2) and (y == 1))", - "var v[2] := {1,2}; ~(swap(v[0],v[1]), (v[0] == 2) and (v[1] == 1))", - "var v[2] := {1,2}; ~(v[0] <=> v[1] , (v[0] == 2) and (v[1] == 1))", - "var v[2] := {1,2}; swap(v[zero],v[one]); (v[zero] == 2) and (v[one] == 1)", - "var v[2] := {1,2}; v[zero] <=> v[one] ; (v[zero] == 2) and (v[one] == 1)", - "var v[2] := {1,2}; ~(swap(v[zero],v[one]), (v[zero] == 2) and (v[one] == 1))", - "var v[2] := {1,2}; ~(v[zero] <=> v[one] , (v[zero] == 2) and (v[one] == 1))", - "var v[2] := {1,2}; swap(v[2 * zero],v[(2 * one) / (1 + 1)]); (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1)", - "var v[2] := {1,2}; v[2 * zero] <=> v[(2*one)/(1+1)] ; (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1)", - "var v[2] := {1,2}; ~(swap(v[2 * zero],v[(2 * one) / (1 + 1)]), (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1))", - "var v[2] := {1,2}; ~(v[2 * zero] <=> v[(2 * one) / (1 + 1)] , (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1))", - "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[0]); swap(v[1],y); (x == 3) and (y == 4)", - "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[0]; v[1] <=> y; (x == 3) and (y == 4)", - "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[zero]); swap(v[one],y); (x == 3) and (y == 4)", - "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[zero]; v[one] <=> y; (x == 3) and (y == 4)", - "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[2 * zero]); swap(v[(2 * one) / (1 + 1)],y); (x == 3) and (y == 4)", - "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[zero / 3]; v[(2 * one)/(1 + 1)] <=> y; (x == 3) and (y == 4)", - "~{ var x := 1 } + ~{ var x := 2 } == 3", - "(~{ var x := 1 } + ~{ var x := 2 }) == (~{ var x := 2 } + ~{ var x := 1 })", - "(~{ var x := 1 } + ~{ var x := 2 } + ~{~{ var x := 1 } + ~{ var x := 2 }}) == 6", - "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6", - "(~{ var x := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6", - "(~{ var x[1] := [1] } + ~{ var x := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6", - "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x := [1] } + ~{ var x[1] := [2] }}) == 6", - "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x := [2] }}) == 6", - "(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6", - "(~{~{ var x := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6", - "(~{~{ var x[1] := [1] } + ~{ var x := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6", - "(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x := [1] } + ~{ var x[1] := [2] }) == 6", - "(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x := [2] }) == 6", - "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6", - "(~{~{ var x := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6", - "(~{~{ var x[1] := [1] }} + ~{ var x := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6", - "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x := [2] } + ~{{ var x[1] := [2] }}) == 6", - "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x := [2] }}) == 6", - "(~{~{~{var x[1] := [1]}}} + ~{~{var x[1] := [2]}} + ~{var x[1] := [3]}) == 6", - "(~{var x[1] := [1]} + ~{~{var x[1] := [2]}} + ~{~{~{var x[1] := [3]}}}) == 6", - "(~{ var x[3] := [1] } + ~{ var x[6] := {6,5,4,3,2,1}}) == 7", - "(~{ var x[6] := {6,5,4,3,2,1} } + ~{ var x := 1 }) == 7", - "(~{ var x := 1 } + ~{ var x[6] := {6,5,4,3,2,1} }) == 7", - "var x[3] := {}; (x[0] == 0) and (x[1] == 0) and (x[2] == 0)", - "var x[3] := {1,2}; (x[0] == 1) and (x[1] == 2) and (x[2] == 0)", - "var x[3] := {1,2,3}; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", - "var x[3] := [1]; (x[0] == 1) and (x[1] == 1) and (x[2] == 1)", - "var v[3] := [1]; v += 1; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 2)", - "var v[3] := [1]; v -= 1; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 0)", - "var v[3] := [1]; v *= 2; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 2)", - "var v[3] := [3]; v /= 3; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 1)", - "var v[3] := {1,2, 3}; v += 1; (v[0] == 2) and (v[1] == 3) and (v[2] == 4)", - "var v[3] := {1,2, 3}; v -= 1; (v[0] == 0) and (v[1] == 1) and (v[2] == 2)", - "var v[3] := {1,2, 3}; v *= 2; (v[0] == 2) and (v[1] == 4) and (v[2] == 6)", - "var v[3] := {3,9,15}; v /= 3; (v[0] == 1) and (v[1] == 3) and (v[2] == 5)", - "var v0[3] := [1]; var v1[3] := [1]; v0 += v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 2)", - "var v0[3] := [1]; var v1[3] := [1]; v0 -= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 0)", - "var v0[3] := [1]; var v1[3] := [2]; v0 *= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 2)", - "var v0[3] := [3]; var v1[3] := [3]; v0 /= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 1)", - "var v0[3] := {1,2, 3}; var v1[3] := {1,1,1}; v0 += v1; (v0[0] == 2) and (v0[1] == 3) and (v0[2] == 4)", - "var v0[3] := {1,2, 3}; var v1[3] := {1,1,1}; v0 -= v1; (v0[0] == 0) and (v0[1] == 1) and (v0[2] == 2)", - "var v0[3] := {1,2, 3}; var v1[3] := {2,2,2}; v0 *= v1; (v0[0] == 2) and (v0[1] == 4) and (v0[2] == 6)", - "var v0[3] := {3,9,15}; var v1[3] := {3,3,3}; v0 /= v1; (v0[0] == 1) and (v0[1] == 3) and (v0[2] == 5)", - "var x[3] := {}; var y[4] := {1,2,3,4}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", - "var x[3] := {}; var y[3] := {1,2,3}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", - "var x[3] := {}; var y[2] := {1,2}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == 0)", - "var x[3] := {}; var y[1] := {1}; x := y; (x[0] == y[0]) and (x[1] == 0) and (x[2] == 0)", - "var x[3] := {}; var y[4] := {1,2,3,4}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", - "var x[3] := {}; var y[3] := {1,2,3}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", - "var x[3] := {}; var y[2] := {1,2}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == 0)", - "var x[3] := {}; var y[1] := {1}; x := (y+=1); (x[0] == y[0]) and (x[1] == 0) and (x[2] == 0)", - "var x[3] := {}; var y[4] := {1,2,3,4}; x += (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", - "var x[3] := {}; var y[3] := {1,2,3}; x += (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", - "var x[3] := {}; var y[2] := {1,2}; x += (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == 0)", - "var x[3] := {}; var y[1] := {1}; x += (y+=1); (x[0] == y[0]) and (x[1] == 0) and (x[2] == 0)", - "var x[3] := [9]; var y[4] := {1,2,3,4}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", - "var x[3] := [9]; var y[3] := {1,2,3}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", - "var x[3] := [9]; var y[2] := {1,2}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 9)", - "var x[3] := [9]; var y[1] := {1}; x <=> y; (x[0] == 1) and (x[1] == 9) and (x[2] == 9)", - "var x[3] := [9]; var y[4] := {1,2,3,4}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)", - "var x[3] := [9]; var y[3] := {1,2,3}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)", - "var x[3] := [9]; var y[2] := {1,2}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 9)", - "var x[3] := [9]; var y[1] := {1}; x <=> (y += 1); (x[0] == 2) and (x[1] == 9) and (x[2] == 9)", - "var x[3] := [8]; var y[4] := {1,2,3,4}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", - "var x[3] := [8]; var y[3] := {1,2,3}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", - "var x[3] := [8]; var y[2] := {1,2}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 9)", - "var x[3] := [8]; var y[1] := {1}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 9) and (x[2] == 9)", - "var x[3] := [8]; var y[4] := {1,2,3,4}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)", - "var x[3] := [8]; var y[3] := {1,2,3}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)", - "var x[3] := [8]; var y[2] := {1,2}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 9)", - "var x[3] := [8]; var y[1] := {1}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 9) and (x[2] == 9)", - "var x[3] := [0]; var y[4] := {1,2,3,4}; X < y", - "var x[3] := [0]; var y[3] := {1,2,3}; x < Y", - "var x[3] := [0]; var y[2] := {1,2}; X < y", - "var x[3] := [0]; var y[1] := {1}; x < Y", - "var x[3] := [0]; var y[4] := {1,2,3,4}; x <= y", - "var x[3] := [0]; var y[3] := {1,2,3}; x <= y", - "var x[3] := [0]; var y[2] := {1,2}; x <= y", - "var x[3] := [0]; var y[1] := {1}; x <= y", - "var x[3] := [5]; var y[4] := {1,2,3,4}; x > y", - "var x[3] := [5]; var y[3] := {1,2,3}; x > y", - "var x[3] := [5]; var y[2] := {1,2}; x > y", - "var x[3] := [5]; var y[1] := {1}; x > y", - "var x[3] := [5]; var y[4] := {1,2,3,4}; x >= y", - "var x[3] := [5]; var y[3] := {1,2,3}; x >= y", - "var x[3] := [5]; var y[2] := {1,2}; x >= y", - "var x[3] := [5]; var y[1] := {1}; x >= y", - "var x[3] := [1]; var y[4] := [1]; x == y", - "var x[3] := [1]; var y[3] := [1]; x == y", - "var x[3] := [1]; var y[2] := [1]; x == y", - "var x[3] := [1]; var y[1] := [1]; x == y", - "var x[3] := [1]; var y[4] := [2]; x != y", - "var x[3] := [1]; var y[3] := [2]; x != y", - "var x[3] := [1]; var y[2] := [2]; x != y", - "var x[3] := [1]; var y[1] := [2]; x != y", - "var x[3] := [0]; var y[4] := {5,6,7,8}; (x += 1) < y", - "var x[3] := [0]; var y[3] := {5,6,7}; (x += 1) < y", - "var x[3] := [0]; var y[2] := {5,6}; (x += 1) < y", - "var x[3] := [0]; var y[1] := {5}; (x += 1) < y", - "var x[3] := [0]; var y[4] := {1,2,3,4}; x < (y += 1)", - "var x[3] := [0]; var y[3] := {1,2,3}; x < (y += 1)", - "var x[3] := [0]; var y[2] := {1,2}; x < (y += 1)", - "var x[3] := [0]; var y[1] := {1}; x < (y += 1)", - "var x[3] := [0]; var y[4] := {5,6,7,8}; (x += 1) < (y += 1)", - "var x[3] := [0]; var y[3] := {5,6,7}; (x += 1) < (y += 1)", - "var x[3] := [0]; var y[2] := {5,6}; (x += 1) < (y += 1)", - "var x[3] := [0]; var y[1] := {5}; (x += 1) < (y += 1)", - "var x[3] := {1,2,3}; var y := 5; x < y ", - "var x[3] := {1,2,3}; var y := 3; x < y + 1 ", - "var x[3] := {1,2,3}; var y := 5; x <= y ", - "var x[3] := {1,2,3}; var y := 3; x <= y + 1", - "var x[3] := {1,1,1}; var y := 1; x == y ", - "var x[3] := {1,1,1}; var y := 2; x == y - 1", - "var x[3] := {1,2,3}; var y := 5; y > x ", - "var x[3] := {1,2,3}; var y := 3; y >= x ", - "var x[3] := {1,2,3}; var y := 5; y + 1 > x ", - "var x[3] := {1,1,1}; var y := 1; y == x ", - "var x[3] := {1,1,1}; var y := 2; y - 1 == x", - "var x[3] := {1,2,3}; var y := 5; equal(true,(x += 1) < y) ", - "var x[3] := {1,2,3}; var y := 3; equal(true,(x -= 1) < y + 1)", - "var x[3] := {1,2,3}; var y := 5; equal(true,(x -= 1) <= y) ", - "var x[3] := {2,2,2}; var y := 1; (x -= 1) == y ", - "var x[3] := {1,2,3}; var y := 5; y > (x += 1) ", - "var x[3] := {1,2,3}; var y := 5; y + 1 > (x += 1) ", - "var x[3] := {2,2,2}; var y := 1; y == (x -= 1) ", - "var x[3] := {2,2,2}; var y := 0; y + 1 == (x -= 1)", - "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := (x + y); z == (x + y)", - "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := (x - y); z == (x - y)", - "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := (x / y); z == (x / y)", - "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := (x * y); z == (x * y)", - "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := 2(x + y); z == (x + y)2", - "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := 2(x - y); z == (x - y)2", - "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := 2(x / y); z == (x / y)2", - "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := 2(x * y); z == (x * y)2", - "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := 2(x + y)/3; z == 2(x + y)/3", - "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := 2(x - y)/3; z == 2(x - y)/3", - "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := 2(x / y)/3; z == 2(x / y)/3", - "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := 2(x * y)/3; z == 2(x * y)/3", - "var x[6] := {1,2,3,4,5,6}; equal(sqrt(sum([x - avg(x)]^2) / x[]),1.7078251277)", - "var x[3] := {-1,-2,-3}; sum(abs(x) ) == 6", - "var x[3] := {0.1,0.2,0.3}; sum(trunc(x)) == 0", - - "var x[10^6]:=[2];var y[10^6]:=[3]; var s:=0;equal(for(var i:=0; i<10;i+=1){s+= sum(5 *(2x-y/3)) + i;},150000045.0)", - - "var x := 2; (~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; " - "j += 1) { var y := 3; if ((i + j + y + x) < 6) { y += x; continue; } else " - "break[i + j]; } } } + ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; " - "j <= i; j += 1) { var y := 3; if ((i + j + y + x) < 6) { y += x; continue; } " - " else break[i + j]; } } }) == 18 ", - - "var x := 2; var v0[3] := {1,2,3}; ( ~{ for (var i := 0; i < 10; i += 1) { " - "for (var j := 0; j <= i; j += 1) { var y := 3; var v2[3] := {1,2,3}; if ( " - "(i + j + y + x + abs(v0[i % v0[]] - v2[j % v2[]])) < 6) { var v3[3] := " - "{1,2,3}; y += x / v3[j % v3[]]; continue; } else break[i + j]; } } } " - "+ ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; j += 1) " - " { var y := 3; var v2[3] := {1,2,3}; if ((i + j + y + x + abs(v0[i % v0[]] - " - "v2[j % v2[]])) < 6) { var v3[3] := {1,2,3}; y += x / v3[j % v3[]]; " - "continue; } else break[i + j]; } } } ) == 18 ", - - "12 == (if (1 > 2) { var x:= 2; } else { var x[3] := {7,2,3}; sum(x); })", - "12 == (if (1 < 2) { var x[3] := {7,2,3}; sum(x); } else { var x:= 2; })", - "12 == (if (1 > 2) { var x:= 2; } else { var x[3] := {7,2,3}; sum(x); })", - "12 == (if (1 < 2) { var x[3] := {7,2,3}; sum(x); } else { var x:= 2; })", - - "21 == (for (var i := 0; i < 10; i += 1) { if (i > 2) { break [i * 7]; i += 1;" - "i += 2; i += 3; }; })", - - "21 == (for (var i := 0; i < 10; i += 1) { if (i > 2) { break [i * 7]; return " - "[i * 8]; i += 1; i += 2; i += 3; }; })", - - "2 == for (var i := 0; i < 10; i += 1) { if (i > 2) { continue; i += 1; i += 2;" - "i += 3; } else i; }", - - "2 == for (var i := 0; i < 10; i += 1) { if (i > 2) { continue; return [i * 8];" - "i += 1; i += 2; i += 3; } else i; }", - - "var x[10] := [-1]; var y[10] := [-1]; for (var i := 0; i < 10; i += 1) { x[i] := i; " - "y[i] := 2 * x[i]; }; (sum(x) == 45) and (sum(y) == (2 * sum(x)));" - - "7 == (for (var i := 0; i < 10; i += 1) { ~{break[7]; continue; i += i} })", - "0 == (for (var i := 0; i < 10; i += 1) { ~{break[i]; continue; i += i} })", - "0 == (for (var i := 0; i < 10; i += 1) { ~{continue; break[7]; i += i} })", - "1 == (for (var i := 0; i < 10; i += 1) { ~{break[i += 1]; continue; i += i} })", - - "var s := 'abc'; s == ~{'abc' } ", - "var s := 'abc'; s == ~{s } ", - "var s := 'abc'; s == ~{'ab' + 'c'} ", - "var s := 'abc'; ~{'abc' } == s ", - "var s := 'abc'; ~{s } == s ", - "var s := 'abc'; ~{'ab' + 'c'} == s ", - "var s := 'abc'; ~{1 + 2; 'abc' + s; s} == s ", - "var s := 'abc'; ~{1 + 2; var x := 'ab'; x + 'c'} == s ", - - "var x[10^6] := null; var y[10^7] := null; 0 * (min(x) + min(y)) + x[] + y[] == 10^7 + 10^6", - - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; if (1 < 2, v0, v1) == v0", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; if (1 > 2, v0, v1) == v1", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; if (1 < 2, v0 - v1, v1 - v0) == (v0 - v1)", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; if (1 > 2, v0 - v1, v1 - v0) == (v1 - v0)", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; if (x < y, v0, v1) == v0", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; if (x > y, v0, v1) == v1", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; if (x < y, v0 - v1, v1 - v0) == (v0 - v1)", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; if (x > y, v0 - v1, v1 - v0) == (v1 - v0)", - - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; if (1 < 2, v0, v1) == v0", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; if (1 > 2, v0, v1) == v1", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; if (1 < 2, v0 - v1, v1 - v0) == (v0 - v1)", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; if (1 > 2, v0 - v1, v1 - v0) == (v1 - v0)", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; if (x < y, v0, v1) == v0", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; if (x > y, v0, v1) == v1", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; if (x < y, v0 - v1, v1 - v0) == (v0 - v1)", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; if (x > y, v0 - v1, v1 - v0) == (v1 - v0)", - - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; (if (1 < 2) v0; else v1;) == v0", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; (if (1 > 2) v0; else v1;) == v1", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; (if (1 < 2) v0 - v1; else v1 - v0;) == (v0 - v1)", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; (if (1 > 2) v0 - v1; else v1 - v0;) == (v1 - v0)", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; (if (x < y) v0; else v1;) == v0", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; (if (x > y) v0; else v1;) == v1", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; (if (x < y) v0 - v1; else v1 - v0;) == (v0 - v1)", - "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; (if (x > y) v0 - v1; else v1 - v0;) == (v1 - v0)", - - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; (if (1 < 2) v0; else v1;) == v0", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; (if (1 > 2) v0; else v1;) == v1", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; (if (1 < 2) v0 - v1; else v1 - v0;) == (v0 - v1)", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; (if (1 > 2) v0 - v1; else v1 - v0;) == (v1 - v0)", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; (if (x < y) v0; else v1;) == v0", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; (if (x > y) v0; else v1;) == v1", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; (if (x < y) v0 - v1; else v1 - v0;) == (v0 - v1)", - "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; (if (x > y) v0 - v1; else v1 - v0;) == (v1 - v0)", + const std::string expression_list[] = + { + "var x; 1", + "var x := 1; x", + "var x:= 1; x - -1 == 2", + "var x:= 1; x --1 == 2", + "var x:= 1; x-- 1 == 2", + "var x:= 1; x--1 == 2", + "var x:= 1; x -- -1== 0", + "var x:= 1; x + -1 == 0", + "var x:= 1; x +-1 == 0", + "var x:= 1; x+- 1 == 0", + "var x:= 1; x+-1 == 0", + "var x:= 1; x +- -1== 2", + "var x:= 1; x + +1 == 2", + "var x:= 1; x ++1 == 2", + "var x:= 1; 1 - -x == 2", + "var x:= 1; 1 --x == 2", + "var x:= 1; 1-- x == 2", + "var x:= 1; 1--x == 2", + "var x:= 1; 1 -- -x== 0", + "var x:= 1; 1 + -x == 0", + "var x:= 1; 1 +-x == 0", + "var x:= 1; 1+- x == 0", + "var x:= 1; 1+-x == 0", + "var x:= 1; 1 +- -x== 2", + "var x:= 1; 1 + +x == 2", + "var x:= 1; 1 ++x == 2", + "var x:= 1; (x - -1 + 1) == 3", + "var x:= 1; (x --1 + 1) == 3", + "var x:= 1; (x-- 1 + 1) == 3", + "var x:= 1; (x--1 + 1) == 3", + "var x:= 1; (x -- -1 + 1) == 1", + "var x:= 1; (x + -1 + 1) == 1", + "var x:= 1; (x +-1 + 1) == 1", + "var x:= 1; (x+- 1 + 1) == 1", + "var x:= 1; (x+-1 + 1) == 1", + "var x:= 1; (x +- -1 + 1) == 3", + "var x:= 1; (x + +1 + 1) == 3", + "var x:= 1; (x ++1 + 1) == 3", + "var x:= 1; (1 - -x + 1) == 3", + "var x:= 1; (1 --x + 1) == 3", + "var x:= 1; (1-- x + 1) == 3", + "var x:= 1; (1--x + 1) == 3", + "var x:= 1; (1 -- -x + 1) == 1", + "var x:= 1; (1 + -x + 1) == 1", + "var x:= 1; (1 +-x + 1) == 1", + "var x:= 1; (1+- x + 1) == 1", + "var x:= 1; (1+-x + 1) == 1", + "var x:= 1; (1 +- -x + 1) == 3", + "var x:= 1; (1 + +x + 1) == 3", + "var x:= 1; (1 ++x + 1) == 3", + "var x:= 1; (x - -1 - 1) == 1", + "var x:= 1; (x --1 - 1) == 1", + "var x:= 1; (x-- 1 - 1) == 1", + "var x:= 1; (x--1 - 1) == 1", + "var x:= 1; (x -- -1 - 1) == -1", + "var x:= 1; (x + -1 - 1) == -1", + "var x:= 1; (x +-1 - 1) == -1", + "var x:= 1; (x+- 1 - 1) == -1", + "var x:= 1; (x+-1 - 1) == -1", + "var x:= 1; (x +- -1 - 1) == 1", + "var x:= 1; (x + +1 - 1) == 1", + "var x:= 1; (x ++1 - 1) == 1", + "var x:= 1; (1 - -x - 1) == 1", + "var x:= 1; (1 --x - 1) == 1", + "var x:= 1; (1-- x - 1) == 1", + "var x:= 1; (1--x - 1) == 1", + "var x:= 1; (1 -- -x - 1) == -1", + "var x:= 1; (1 + -x - 1) == -1", + "var x:= 1; (1 +-x - 1) == -1", + "var x:= 1; (1+- x - 1) == -1", + "var x:= 1; (1+-x - 1) == -1", + "var x:= 1; (1 +- -x - 1) == 1", + "var x:= 1; (1 + +x - 1) == 1", + "var x:= 1; (1 ++x - 1) == 1", + "var x := 1; var y := 2; 1", + "var x := 1; var y := 2; x", + "var x:=6; var y:=4; x + -3 == 3", + "var x:=6; var y:=4; x - -3 == 9", + "var x:=6; var y:=4; x * -3 == -18", + "var x:=6; var y:=4; x / -3 == -2", + "var x:=6; var y:=4; -x + -3 == -9", + "var x:=6; var y:=4; -x - -3 == -3", + "var x:=6; var y:=4; -x * -3 == 18", + "var x:=6; var y:=4; -x / -3 == 2", + "var x:=6; var y:=4; -3 + -x == -9", + "var x:=6; var y:=4; -3 - -x == 3", + "var x:=6; var y:=4; -3 * -x == 18", + "var x:=6; var y:=4; -3 / -x == 0.5", + "var x:=6; var y:=4; 3 + -x == -3", + "var x:=6; var y:=4; 3 - -x == 9", + "var x:=6; var y:=4; 3 * -x == -18", + "var x:=6; var y:=4; 3 / -x == -0.5", + "var x := 3; var y := 6; x + -y == -3", + "var x := 3; var y := 6; x - -y == 9", + "var x := 3; var y := 6; -x + -y == -9", + "var x := 3; var y := 6; -x - -y == 3", + "var x := 3; var y := 6; -x * -y == 18", + "var x := 6; var y := 3; -x / -y == 2", + "var x := 3; var y := 6; -(-x * -y) == -18", + "var x := 6; var y := 3; -(-x / -y) == -2", + "var x:=1; 2+(3+abs(x)) == 6 ", + "var x:=1; (3+abs(x))+2 == 6 ", + "var x:=1; 2+(abs(x)+3) == 6 ", + "var x:=1; (abs(x)+3)+2 == 6 ", + "var x:=1; 2+(3-abs(x)) == 4 ", + "var x:=1; (3-abs(x))+2 == 4 ", + "var x:=1; 2+(abs(x)-3) == 0 ", + "var x:=1; (abs(x)-3)+2 == 0 ", + "var x:=1; 2-(3+abs(x)) == -2 ", + "var x:=1; (3+abs(x))-2 == 2 ", + "var x:=1; 2-(abs(x)+3) == -2 ", + "var x:=1; (abs(x)+3)-2 == 2 ", + "var x:=1; 2*(3*abs(x)) == 6 ", + "var x:=1; (3*abs(x))*2 == 6 ", + "var x:=1; 2*(abs(x)*3) == 6 ", + "var x:=1; (abs(x)*3)*2 == 6 ", + "var x:=1; 2*(3/abs(x)) == 6 ", + "var x:=1; (3/abs(x))*2 == 6 ", + "var x:=1; 2*(abs(x)/3) == (2/3)", + "var x:=1; (abs(x)/3)*2 == (2/3)", + "var x:=1; 2/(3*abs(x)) == (2/3)", + "var x:=1; (3*abs(x))/2 == (3/2)", + "var x:=1; 2/(abs(x)*3) == (2/3)", + "var x:=1; (abs(x)*3)/2 == (3/2)", + "var x:=1; 2/(3/abs(x)) == (2/3)", + "var x:=1; (3/abs(x))/2 == (3/2)", + "var x:=1; 2/(abs(x)/3) == 6 ", + "var x:=1; (abs(x)/3)/2 == (1/6)", + "var x:=3; var y:=6; -(-x)*-(-y) == 18", + "var x:=3; var y:=6; -(-x)*-(-(-y)) == -18", + "var x:=3; var y:=6; -(-(-x))*-(-y) == -18", + "var x:=3; var y:=6; -(-(-x))*-(-(-y)) == 18", + "var x:=3; var y:=6; -(-(x+y))*-(-(y+x)) == 81", + "var x:=3; var y:=6; -(-(-(x+y)))*-(-(y+x)) == -81", + "var x:=3; var y:=6; -(-(x+y))*-(-(-(y+x))) == -81", + "var x:=3; var y:=6; -(-(-(x+y)))*-(-(-(y+x))) == 81", + "var x:= 2; var y := 3; (-abs(x)+-abs(y)) == -5 ", + "var x:= 2; var y := 3; (-abs(x)--abs(y)) == 1 ", + "var x:= 2; var y := 3; (-abs(x)*-abs(y)) == 6 ", + "var x:= 2; var y := 3; (-abs(x)/-abs(y)) == (2/3) ", + "var x:= 2; var y := 3; (-abs(x)+abs(y)) == 1 ", + "var x:= 2; var y := 3; (-abs(x)-abs(y)) == -5 ", + "var x:= 2; var y := 3; (-abs(x)*abs(y)) == -6 ", + "var x:= 2; var y := 3; (-abs(x)/abs(y)) == -(2/3) ", + "var x:= 2; var y := 3; (abs(x)+-abs(y)) == -1 ", + "var x:= 2; var y := 3; (abs(x)--abs(y)) == 5 ", + "var x:= 2; var y := 3; (abs(x)*-abs(y)) == -6 ", + "var x:= 2; var y := 3; (abs(x)/-abs(y)) == -(2/3) ", + "var x:= 2; var y := 3; (-abs(x + 0)+-abs(y - 0)) == -5 ", + "var x:= 2; var y := 3; (-abs(x + 0)--abs(y - 0)) == 1 ", + "var x:= 2; var y := 3; (-abs(x + 0)*-abs(y - 0)) == 6 ", + "var x:= 2; var y := 3; (-abs(x + 0)/-abs(y - 0)) == (2/3) ", + "var x:= 2; var y := 3; (-abs(x + 0)+abs(y - 0)) == 1 ", + "var x:= 2; var y := 3; (-abs(x + 0)-abs(y - 0)) == -5 ", + "var x:= 2; var y := 3; (-abs(x + 0)*abs(y - 0)) == -6 ", + "var x:= 2; var y := 3; (-abs(x + 0)/abs(y - 0)) == -(2/3) ", + "var x:= 2; var y := 3; (abs(x + 0)+-abs(y - 0)) == -1 ", + "var x:= 2; var y := 3; (abs(x + 0)--abs(y - 0)) == 5 ", + "var x:= 2; var y := 3; (abs(x + 0)*-abs(y - 0)) == -6 ", + "var x:= 2; var y := 3; (abs(x + 0)/-abs(y - 0)) == -(2/3) ", + "var x := 1; var y := 2; swap(x,y); (x == 2) and (y == 1)", + "var x := 1; var y := 2; x <=> y ; (x == 2) and (y == 1)", + "var x := 'abc'; x == 'abc' ", + "var x := 'abc'; var y := '123'; x != y ", + "var x := 'abc'; var y := x + '123'; y == 'abc123' ", + "var x := 'abc'; var y := '123' + x; y == '123abc' ", + "~{var x := '123'; x[]} + ~{var x := '1234'; x[]} == 7", + "~{var x := '123'; x[]} + ~{~{var x := '1234'; x[]}} == 7", + "~{~{var x := '123'; x[]}} + ~{var x := '1234'; x[]} == 7", + "~{var x := '123'; x[]} + ~{var x := 4} == 7", + "~{var x := 3} + ~{var x := '1234'; x[]} == 7", + "~{var x := '123'; x[]} + ~{~{var x := 4}} == 7", + "~{~{var x := 3}} + ~{var x := '1234'; x[]} == 7", + "var v[2] := {1,2}; swap(v[0],v[1]); (v[0] == 2) and (v[1] == 1)", + "var v[2] := {1,2}; v[0] <=> v[1] ; (v[0] == 2) and (v[1] == 1)", + "var x := 1; var y := 2; ~(swap(x,y),(x == 2) and (y == 1))", + "var x := 1; var y := 2; ~(x <=> y , (x == 2) and (y == 1))", + "var v[2] := {1,2}; ~(swap(v[0],v[1]), (v[0] == 2) and (v[1] == 1))", + "var v[2] := {1,2}; ~(v[0] <=> v[1] , (v[0] == 2) and (v[1] == 1))", + "var v[2] := {1,2}; swap(v[zero],v[one]); (v[zero] == 2) and (v[one] == 1)", + "var v[2] := {1,2}; v[zero] <=> v[one] ; (v[zero] == 2) and (v[one] == 1)", + "var v[2] := {1,2}; ~(swap(v[zero],v[one]), (v[zero] == 2) and (v[one] == 1))", + "var v[2] := {1,2}; ~(v[zero] <=> v[one] , (v[zero] == 2) and (v[one] == 1))", + "var v[2] := {1,2}; swap(v[2 * zero],v[(2 * one) / (1 + 1)]); (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1)", + "var v[2] := {1,2}; v[2 * zero] <=> v[(2*one)/(1+1)] ; (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1)", + "var v[2] := {1,2}; ~(swap(v[2 * zero],v[(2 * one) / (1 + 1)]), (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1))", + "var v[2] := {1,2}; ~(v[2 * zero] <=> v[(2 * one) / (1 + 1)] , (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1))", + "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[0]); swap(v[1],y); (x == 3) and (y == 4)", + "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[0]; v[1] <=> y; (x == 3) and (y == 4)", + "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[zero]); swap(v[one],y); (x == 3) and (y == 4)", + "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[zero]; v[one] <=> y; (x == 3) and (y == 4)", + "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[2 * zero]); swap(v[(2 * one) / (1 + 1)],y); (x == 3) and (y == 4)", + "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[zero / 3]; v[(2 * one)/(1 + 1)] <=> y; (x == 3) and (y == 4)", + "~{ var x := 1 } + ~{ var x := 2 } == 3", + "(~{ var x := 1 } + ~{ var x := 2 }) == (~{ var x := 2 } + ~{ var x := 1 })", + "(~{ var x := 1 } + ~{ var x := 2 } + ~{~{ var x := 1 } + ~{ var x := 2 }}) == 6", + "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6", + "(~{ var x := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6", + "(~{ var x[1] := [1] } + ~{ var x := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6", + "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x := [1] } + ~{ var x[1] := [2] }}) == 6", + "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x := [2] }}) == 6", + "(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6", + "(~{~{ var x := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6", + "(~{~{ var x[1] := [1] } + ~{ var x := [2] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] }) == 6", + "(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x := [1] } + ~{ var x[1] := [2] }) == 6", + "(~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }} + ~{ var x[1] := [1] } + ~{ var x := [2] }) == 6", + "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6", + "(~{~{ var x := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6", + "(~{~{ var x[1] := [1] }} + ~{ var x := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6", + "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x := [2] } + ~{{ var x[1] := [2] }}) == 6", + "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x := [2] }}) == 6", + "(~{~{~{var x[1] := [1]}}} + ~{~{var x[1] := [2]}} + ~{var x[1] := [3]}) == 6", + "(~{var x[1] := [1]} + ~{~{var x[1] := [2]}} + ~{~{~{var x[1] := [3]}}}) == 6", + "(~{ var x[3] := [1] } + ~{ var x[6] := {6,5,4,3,2,1}}) == 7", + "(~{ var x[6] := {6,5,4,3,2,1} } + ~{ var x := 1 }) == 7", + "(~{ var x := 1 } + ~{ var x[6] := {6,5,4,3,2,1} }) == 7", + "var x[3] := {}; (x[0] == 0) and (x[1] == 0) and (x[2] == 0)", + "var x[3] := {1,2}; (x[0] == 1) and (x[1] == 2) and (x[2] == 0)", + "var x[3] := {1,2,3}; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", + "var x[3] := [1]; (x[0] == 1) and (x[1] == 1) and (x[2] == 1)", + "var v[3] := [1]; v += 1; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 2)", + "var v[3] := [1]; v -= 1; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 0)", + "var v[3] := [1]; v *= 2; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 2)", + "var v[3] := [3]; v /= 3; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 1)", + "var v[3] := {1,2, 3}; v += 1; (v[0] == 2) and (v[1] == 3) and (v[2] == 4)", + "var v[3] := {1,2, 3}; v -= 1; (v[0] == 0) and (v[1] == 1) and (v[2] == 2)", + "var v[3] := {1,2, 3}; v *= 2; (v[0] == 2) and (v[1] == 4) and (v[2] == 6)", + "var v[3] := {3,9,15}; v /= 3; (v[0] == 1) and (v[1] == 3) and (v[2] == 5)", + "var v0[3] := [1]; var v1[3] := [1]; v0 += v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 2)", + "var v0[3] := [1]; var v1[3] := [1]; v0 -= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 0)", + "var v0[3] := [1]; var v1[3] := [2]; v0 *= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 2)", + "var v0[3] := [3]; var v1[3] := [3]; v0 /= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 1)", + "var v0[3] := {1,2, 3}; var v1[3] := {1,1,1}; v0 += v1; (v0[0] == 2) and (v0[1] == 3) and (v0[2] == 4)", + "var v0[3] := {1,2, 3}; var v1[3] := {1,1,1}; v0 -= v1; (v0[0] == 0) and (v0[1] == 1) and (v0[2] == 2)", + "var v0[3] := {1,2, 3}; var v1[3] := {2,2,2}; v0 *= v1; (v0[0] == 2) and (v0[1] == 4) and (v0[2] == 6)", + "var v0[3] := {3,9,15}; var v1[3] := {3,3,3}; v0 /= v1; (v0[0] == 1) and (v0[1] == 3) and (v0[2] == 5)", + "var x[3] := {}; var y[4] := {1,2,3,4}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", + "var x[3] := {}; var y[3] := {1,2,3}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", + "var x[3] := {}; var y[2] := {1,2}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == 0)", + "var x[3] := {}; var y[1] := {1}; x := y; (x[0] == y[0]) and (x[1] == 0) and (x[2] == 0)", + "var x[3] := {}; var y[4] := {1,2,3,4}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", + "var x[3] := {}; var y[3] := {1,2,3}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", + "var x[3] := {}; var y[2] := {1,2}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == 0)", + "var x[3] := {}; var y[1] := {1}; x := (y+=1); (x[0] == y[0]) and (x[1] == 0) and (x[2] == 0)", + "var x[3] := {}; var y[4] := {1,2,3,4}; x += (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", + "var x[3] := {}; var y[3] := {1,2,3}; x += (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])", + "var x[3] := {}; var y[2] := {1,2}; x += (y+=1); (x[0] == y[0]) ", + "var x[3] := {}; var y[2] := {1,2}; x += (y+=1); (x[0] == y[0]) and (x[1] == y[1]) ", + "var x[3] := {}; var y[2] := {1,2}; x += (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == 0)", + "var x[3] := {}; var y[1] := {1}; x += (y+=1); (x[0] == y[0]) ", + "var x[3] := {}; var y[1] := {1}; x += (y+=1); (x[0] == y[0]) and (x[1] == 0) ", + "var x[3] := {}; var y[1] := {1}; x += (y+=1); (x[0] == y[0]) and (x[1] == 0) and (x[2] == 0)", + "var x[3] := [9]; var y[4] := {1,2,3,4}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", + "var x[3] := [9]; var y[3] := {1,2,3}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", + "var x[3] := [9]; var y[2] := {1,2}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 9)", + "var x[3] := [9]; var y[1] := {1}; x <=> y; (x[0] == 1) and (x[1] == 9) and (x[2] == 9)", + "var x[3] := [9]; var y[4] := {1,2,3,4}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)", + "var x[3] := [9]; var y[3] := {1,2,3}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)", + "var x[3] := [9]; var y[2] := {1,2}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 9)", + "var x[3] := [9]; var y[1] := {1}; x <=> (y += 1); (x[0] == 2) and (x[1] == 9) and (x[2] == 9)", + "var x[3] := [8]; var y[4] := {1,2,3,4}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", + "var x[3] := [8]; var y[3] := {1,2,3}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)", + "var x[3] := [8]; var y[2] := {1,2}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 9)", + "var x[3] := [8]; var y[1] := {1}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 9) and (x[2] == 9)", + "var x[3] := [8]; var y[4] := {1,2,3,4}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)", + "var x[3] := [8]; var y[3] := {1,2,3}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)", + "var x[3] := [8]; var y[2] := {1,2}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 9)", + "var x[3] := [8]; var y[1] := {1}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 9) and (x[2] == 9)", + "var x[3] := [0]; var y[4] := {1,2,3,4}; X < y", + "var x[3] := [0]; var y[3] := {1,2,3}; x < Y", + "var x[3] := [0]; var y[2] := {1,2}; X < y", + "var x[3] := [0]; var y[1] := {1}; x < Y", + "var x[3] := [0]; var y[4] := {1,2,3,4}; x <= y", + "var x[3] := [0]; var y[3] := {1,2,3}; x <= y", + "var x[3] := [0]; var y[2] := {1,2}; x <= y", + "var x[3] := [0]; var y[1] := {1}; x <= y", + "var x[3] := [5]; var y[4] := {1,2,3,4}; x > y", + "var x[3] := [5]; var y[3] := {1,2,3}; x > y", + "var x[3] := [5]; var y[2] := {1,2}; x > y", + "var x[3] := [5]; var y[1] := {1}; x > y", + "var x[3] := [5]; var y[4] := {1,2,3,4}; x >= y", + "var x[3] := [5]; var y[3] := {1,2,3}; x >= y", + "var x[3] := [5]; var y[2] := {1,2}; x >= y", + "var x[3] := [5]; var y[1] := {1}; x >= y", + "var x[3] := [1]; var y[4] := [1]; x == y", + "var x[3] := [1]; var y[3] := [1]; x == y", + "var x[3] := [1]; var y[2] := [1]; x == y", + "var x[3] := [1]; var y[1] := [1]; x == y", + "var x[3] := [1]; var y[4] := [2]; x != y", + "var x[3] := [1]; var y[3] := [2]; x != y", + "var x[3] := [1]; var y[2] := [2]; x != y", + "var x[3] := [1]; var y[1] := [2]; x != y", + "var x[3] := [0]; var y[4] := {5,6,7,8}; (x += 1) < y", + "var x[3] := [0]; var y[3] := {5,6,7}; (x += 1) < y", + "var x[3] := [0]; var y[2] := {5,6}; (x += 1) < y", + "var x[3] := [0]; var y[1] := {5}; (x += 1) < y", + "var x[3] := [0]; var y[4] := {1,2,3,4}; x < (y += 1)", + "var x[3] := [0]; var y[3] := {1,2,3}; x < (y += 1)", + "var x[3] := [0]; var y[2] := {1,2}; x < (y += 1)", + "var x[3] := [0]; var y[1] := {1}; x < (y += 1)", + "var x[3] := [0]; var y[4] := {5,6,7,8}; (x += 1) < (y += 1)", + "var x[3] := [0]; var y[3] := {5,6,7}; (x += 1) < (y += 1)", + "var x[3] := [0]; var y[2] := {5,6}; (x += 1) < (y += 1)", + "var x[3] := [0]; var y[1] := {5}; (x += 1) < (y += 1)", + "var x[3] := {1,2,3}; var y := 5; x < y ", + "var x[3] := {1,2,3}; var y := 3; x < y + 1 ", + "var x[3] := {1,2,3}; var y := 5; x <= y ", + "var x[3] := {1,2,3}; var y := 3; x <= y + 1", + "var x[3] := {1,1,1}; var y := 1; x == y ", + "var x[3] := {1,1,1}; var y := 2; x == y - 1", + "var x[3] := {1,2,3}; var y := 5; y > x ", + "var x[3] := {1,2,3}; var y := 3; y >= x ", + "var x[3] := {1,2,3}; var y := 5; y + 1 > x ", + "var x[3] := {1,1,1}; var y := 1; y == x ", + "var x[3] := {1,1,1}; var y := 2; y - 1 == x", + "var x[3] := {1,2,3}; var y := 5; equal(true,(x += 1) < y) ", + "var x[3] := {1,2,3}; var y := 3; equal(true,(x -= 1) < y + 1)", + "var x[3] := {1,2,3}; var y := 5; equal(true,(x -= 1) <= y) ", + "var x[3] := {2,2,2}; var y := 1; (x -= 1) == y ", + "var x[3] := {1,2,3}; var y := 5; y > (x += 1) ", + "var x[3] := {1,2,3}; var y := 5; y + 1 > (x += 1) ", + "var x[3] := {2,2,2}; var y := 1; y == (x -= 1) ", + "var x[3] := {2,2,2}; var y := 0; y + 1 == (x -= 1)", + "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := (x + y); z == (x + y)", + "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := (x - y); z == (x - y)", + "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := (x / y); z == (x / y)", + "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := (x * y); z == (x * y)", + "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := 2(x + y); z == (x + y)2", + "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := 2(x - y); z == (x - y)2", + "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := 2(x / y); z == (x / y)2", + "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := 2(x * y); z == (x * y)2", + "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := 2(x + y)/3; z == 2(x + y)/3", + "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := 2(x - y)/3; z == 2(x - y)/3", + "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := 2(x / y)/3; z == 2(x / y)/3", + "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := 2(x * y)/3; z == 2(x * y)/3", + "var x[6] := {1,2,3,4,5,6}; equal(sqrt(sum([x - avg(x)]^2) / x[]),1.70782512765993300)", + "var x[3] := {-1,-2,-3}; sum(abs(x) ) == 6", + "var x[3] := {0.1,0.2,0.3}; sum(trunc(x)) == 0", + + "var x[10^6]:=[2];var y[10^6]:=[3]; var s:=0;equal(for(var i:=0; i<10;i+=1){s+= sum(5 *(2x-y/3)) + i;},150000045.0)", + + "var x := 2; (~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; " + "j += 1) { var y := 3; if ((i + j + y + x) < 6) { y += x; continue; } else " + "break[i + j]; } } } + ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; " + "j <= i; j += 1) { var y := 3; if ((i + j + y + x) < 6) { y += x; continue; } " + " else break[i + j]; } } }) == 18 ", + + "var x := 2; var v0[3] := {1,2,3}; ( ~{ for (var i := 0; i < 10; i += 1) { " + "for (var j := 0; j <= i; j += 1) { var y := 3; var v2[3] := {1,2,3}; if ( " + "(i + j + y + x + abs(v0[i % v0[]] - v2[j % v2[]])) < 6) { var v3[3] := " + "{1,2,3}; y += x / v3[j % v3[]]; continue; } else break[i + j]; } } } " + "+ ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; j += 1) " + " { var y := 3; var v2[3] := {1,2,3}; if ((i + j + y + x + abs(v0[i % v0[]] - " + "v2[j % v2[]])) < 6) { var v3[3] := {1,2,3}; y += x / v3[j % v3[]]; " + "continue; } else break[i + j]; } } } ) == 18 ", + + "12 == (if (1 > 2) { var x:= 2; } else { var x[3] := {7,2,3}; sum(x); })", + "12 == (if (1 < 2) { var x[3] := {7,2,3}; sum(x); } else { var x:= 2; })", + "12 == (if (1 > 2) { var x:= 2; } else { var x[3] := {7,2,3}; sum(x); })", + "12 == (if (1 < 2) { var x[3] := {7,2,3}; sum(x); } else { var x:= 2; })", + + "21 == (for (var i := 0; i < 10; i += 1) { if (i > 2) { break [i * 7]; i += 1;" + "i += 2; i += 3; }; })", + + "21 == (for (var i := 0; i < 10; i += 1) { if (i > 2) { break [i * 7]; return " + "[i * 8]; i += 1; i += 2; i += 3; }; })", + + "2 == for (var i := 0; i < 10; i += 1) { if (i > 2) { continue; i += 1; i += 2;" + "i += 3; } else i; }", + + "2 == for (var i := 0; i < 10; i += 1) { if (i > 2) { continue; return [i * 8];" + "i += 1; i += 2; i += 3; } else i; }", + + "var x[10] := [-1]; var y[10] := [-1]; for (var i := 0; i < 10; i += 1) { x[i] := i; " + "y[i] := 2 * x[i]; }; (sum(x) == 45) and (sum(y) == (2 * sum(x)));" + + "7 == (for (var i := 0; i < 10; i += 1) { ~{break[7]; continue; i += i} })", + "0 == (for (var i := 0; i < 10; i += 1) { ~{break[i]; continue; i += i} })", + "0 == (for (var i := 0; i < 10; i += 1) { ~{continue; break[7]; i += i} })", + "1 == (for (var i := 0; i < 10; i += 1) { ~{break[i += 1]; continue; i += i} })", + + "var s := 'abc'; s == ~{'abc' } ", + "var s := 'abc'; s == ~{s } ", + "var s := 'abc'; s == ~{'ab' + 'c'} ", + "var s := 'abc'; ~{'abc' } == s ", + "var s := 'abc'; ~{s } == s ", + "var s := 'abc'; ~{'ab' + 'c'} == s ", + "var s := 'abc'; ~{1 + 2; 'abc' + s; s} == s ", + "var s := 'abc'; ~{1 + 2; var x := 'ab'; x + 'c'} == s ", + + "var x[10^6] := null; var y[10^7] := null; 0 * (min(x) + min(y)) + x[] + y[] == 10^7 + 10^6", + + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; if (1 < 2, v0, v1) == v0", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; if (1 > 2, v0, v1) == v1", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; if (1 < 2, v0 - v1, v1 - v0) == (v0 - v1)", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; if (1 > 2, v0 - v1, v1 - v0) == (v1 - v0)", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; if (x < y, v0, v1) == v0", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; if (x > y, v0, v1) == v1", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; if (x < y, v0 - v1, v1 - v0) == (v0 - v1)", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; if (x > y, v0 - v1, v1 - v0) == (v1 - v0)", + + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; if (1 < 2, v0, v1) == v0", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; if (1 > 2, v0, v1) == v1", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; if (1 < 2, v0 - v1, v1 - v0) == (v0 - v1)", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; if (1 > 2, v0 - v1, v1 - v0) == (v1 - v0)", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; if (x < y, v0, v1) == v0", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; if (x > y, v0, v1) == v1", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; if (x < y, v0 - v1, v1 - v0) == (v0 - v1)", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; if (x > y, v0 - v1, v1 - v0) == (v1 - v0)", + + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; (if (1 < 2) v0; else v1;) == v0", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; (if (1 > 2) v0; else v1;) == v1", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; (if (1 < 2) v0 - v1; else v1 - v0;) == (v0 - v1)", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; (if (1 > 2) v0 - v1; else v1 - v0;) == (v1 - v0)", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; (if (x < y) v0; else v1;) == v0", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; (if (x > y) v0; else v1;) == v1", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; (if (x < y) v0 - v1; else v1 - v0;) == (v0 - v1)", + "var v0[3] := {1,2,3}; var v1[3] := {7,8,9}; var x := 1; var y := 2; (if (x > y) v0 - v1; else v1 - v0;) == (v1 - v0)", + + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; (if (1 < 2) v0; else v1;) == v0", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; (if (1 > 2) v0; else v1;) == v1", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; (if (1 < 2) v0 - v1; else v1 - v0;) == (v0 - v1)", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; (if (1 > 2) v0 - v1; else v1 - v0;) == (v1 - v0)", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; (if (x < y) v0; else v1;) == v0", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; (if (x > y) v0; else v1;) == v1", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; (if (x < y) v0 - v1; else v1 - v0;) == (v0 - v1)", + "var v0[3] := {1,2,3}; var v1[4] := {6,7,8,9}; var x := 1; var y := 2; (if (x > y) v0 - v1; else v1 - v0;) == (v1 - v0)", + + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((-x * -y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((-x + -y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((-x - -y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((-x / -y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) + (1.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) - (1.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) + (y * 1.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) - (y * 1.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) * (y / z)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) / (y / z)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) / y); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) * 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) / 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) * (2.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) * (y * 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) / (2.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) / (2.123 / y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) / (y * 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 * x) / (y / 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 + x) + 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 + x) - 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 + x) + (2.123 + y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 + x) + (y + 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 + x) - (2.123 + y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 + x) - (y + 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 - x) + 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 - x) - 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 - x) - (2.123 - y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 - x) - (y - 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) * 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) / 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) * (2.123 / y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) * (y / 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) / (2.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) / (2.123 / y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) / (y * 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123 / x) / (y / 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) * (2.123 * x)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) * (2.123 / x)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) * (x * 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) * (x / 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) + (2.123 + x)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) + (2.123 - x)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) + (x + 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) + (x - 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) - (2.123 + x)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) - (2.123 - x)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) - (x + 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) - (x - 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) / (2.123 * x)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) / (2.123 / x)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) / (x * 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((1.123) / (x / 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) * 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) / 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x + 1.123) + 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x + 1.123) - 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x - 1.123) + 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x - 1.123) - 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) * 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) / 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x ^ 1.123) ^ 2.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) + (1.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) - (1.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) + (y * 1.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) - (y * 1.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) * (2.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) * (y * 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) / (2.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) / (2.123 / y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) / (y * 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * 1.123) / (y / 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x * y) / (z / w)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x + 1.123) + (2.123 + y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x + 1.123) + (y + 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x + 1.123) - (2.123 + y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x + 1.123) - (y + 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x + y) / (z / w)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x - 1.123) - (2.123 - y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x - 1.123) - (y - 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x - y) / (z / w)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) * (y / z)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) + (y / 1.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) - (y / 1.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) / (y / z)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) / y); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) * (2.123 / y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) * (y + 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) * (y - 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) * (y / 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) / (2.123 * y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) / (2.123 / y)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) / (y * 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / 1.123) / (y / 2.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / y) * (1.123 / z)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / y) * (z / 1.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / y) * (z / w)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / y) / (1.123 / z)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / y) / (z / 1.123)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / y) / (z / w)); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / y) / 1.123); true;", + "var x := 1.111; var y := 2.222; var z := 3.333; var w := 4.444; ((x / y) / z); true;", }; const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); @@ -4954,6 +5185,8 @@ inline bool run_test10() failed = true; } + + expression.release(); } if (failed) @@ -5004,9 +5237,10 @@ inline bool run_test10() } template -inline bool run_test11() +bool run_test11() { typedef exprtk::expression expression_t; + std::string expression_string = "(x + y) / 3"; T x = T(1.0); @@ -5076,36 +5310,38 @@ inline bool run_test11() } template -inline bool run_test12() +bool run_test12() { typedef exprtk::expression expression_t; + static const std::string expression_string[] = - { - "equal(poly01(x,2.2,1.1),(2.2x^1+1.1))", - "equal(poly02(x,3.3,2.2,1.1),(3.3x^2+2.2x^1+1.1))", - "equal(poly03(x,4.4,3.3,2.2,1.1),(4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly04(x,5.5,4.4,3.3,2.2,1.1),(5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly05(x,6.6,5.5,4.4,3.3,2.2,1.1),(6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly06(x,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly07(x,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly08(x,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly09(x,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly10(x,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly11(x,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(3.3x^11+2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equal(poly12(x,4.4,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(4.4x^12+3.3x^11+2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "EquaL(Poly01(x,2.2,1.1),(2.2x^1+1.1))", - "eQuAl(pOly02(x,3.3,2.2,1.1),(3.3x^2+2.2x^1+1.1))", - "eqUal(poLy03(x,4.4,3.3,2.2,1.1),(4.4x^3+3.3x^2+2.2x^1+1.1))", - "eQuAl(polY04(x,5.5,4.4,3.3,2.2,1.1),(5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "EquAl(pOLy05(x,6.6,5.5,4.4,3.3,2.2,1.1),(6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "EqUaL(pOly06(x,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "Equal(Poly07(x,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "eQual(PoLy08(x,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "eqUal(pOlY09(x,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equAl(POLY10(x,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "equaL(PolY11(x,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(3.3x^11+2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", - "EQUAL(pOLy12(x,4.4,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(4.4x^12+3.3x^11+2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))" - }; + { + "equal(poly01(x,2.2,1.1),(2.2x^1+1.1))", + "equal(poly02(x,3.3,2.2,1.1),(3.3x^2+2.2x^1+1.1))", + "equal(poly03(x,4.4,3.3,2.2,1.1),(4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly04(x,5.5,4.4,3.3,2.2,1.1),(5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly05(x,6.6,5.5,4.4,3.3,2.2,1.1),(6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly06(x,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly07(x,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly08(x,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly09(x,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly10(x,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly11(x,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(3.3x^11+2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equal(poly12(x,4.4,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(4.4x^12+3.3x^11+2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "EquaL(Poly01(x,2.2,1.1),(2.2x^1+1.1))", + "eQuAl(pOly02(x,3.3,2.2,1.1),(3.3x^2+2.2x^1+1.1))", + "eqUal(poLy03(x,4.4,3.3,2.2,1.1),(4.4x^3+3.3x^2+2.2x^1+1.1))", + "eQuAl(polY04(x,5.5,4.4,3.3,2.2,1.1),(5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "EquAl(pOLy05(x,6.6,5.5,4.4,3.3,2.2,1.1),(6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "EqUaL(pOly06(x,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "Equal(Poly07(x,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "eQual(PoLy08(x,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "eqUal(pOlY09(x,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equAl(POLY10(x,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "equaL(PolY11(x,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(3.3x^11+2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))", + "EQUAL(pOLy12(x,4.4,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1),(4.4x^12+3.3x^11+2.2x^10+1.1x^9+9.9x^8+8.8x^7+7.7x^6+6.6x^5+5.5x^4+4.4x^3+3.3x^2+2.2x^1+1.1))" + }; + static const std::size_t expression_string_size = sizeof(expression_string) / sizeof(std::string); T x = T(1.23456); @@ -5175,57 +5411,57 @@ inline bool run_test12() } template -struct sine_deg : public exprtk::ifunction +struct sine_deg exprtk_test_final : public exprtk::ifunction { using exprtk::ifunction::operator(); sine_deg() : exprtk::ifunction(1) {} - inline T operator()(const T& v) + inline T operator()(const T& v) exprtk_test_override { return std::sin((v * T(exprtk::details::numeric::constant::pi)) / T(180)); } }; template -struct cosine_deg : public exprtk::ifunction +struct cosine_deg exprtk_test_final : public exprtk::ifunction { using exprtk::ifunction::operator(); cosine_deg() : exprtk::ifunction(1) {} - inline T operator()(const T& v) + inline T operator()(const T& v) exprtk_test_override { return std::cos((v * T(exprtk::details::numeric::constant::pi)) / T(180)); } }; template -inline bool run_test13() +bool run_test13() { typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; static const std::string expression_string[] = - { - "equal(sin(30),0.5) ", - "equal(cos(60),0.5) ", - "equal(sin(60),sqrt(3)/2) ", - "equal(cos(30),sqrt(3)/2) ", - "equal(sin(x_deg),0.5) ", - "equal(cos(y_deg),0.5) ", - "equal(sin(y_deg),sqrt(3)/2) ", - "equal(cos(x_deg),sqrt(3)/2) ", - "equal(sin(30) + sin(30),1.0) ", - "equal(cos(60) + cos(60),1.0) ", - "equal(sin(60) + sin(60),sqrt(3)) ", - "equal(cos(30) + cos(30),sqrt(3)) ", - "equal(sin(x_deg) + sin(x_deg),1.0) ", - "equal(cos(y_deg) + cos(y_deg),1.0) ", - "equal(sin(y_deg) + sin(y_deg),sqrt(3))", - "equal(cos(x_deg) + cos(x_deg),sqrt(3))" - }; + { + "equal(sin(30),0.5) ", + "equal(cos(60),0.5) ", + "equal(sin(60),sqrt(3)/2) ", + "equal(cos(30),sqrt(3)/2) ", + "equal(sin(x_deg),0.5) ", + "equal(cos(y_deg),0.5) ", + "equal(sin(y_deg),sqrt(3)/2) ", + "equal(cos(x_deg),sqrt(3)/2) ", + "equal(sin(30) + sin(30),1.0) ", + "equal(cos(60) + cos(60),1.0) ", + "equal(sin(60) + sin(60),sqrt(3)) ", + "equal(cos(30) + cos(30),sqrt(3)) ", + "equal(sin(x_deg) + sin(x_deg),1.0) ", + "equal(cos(y_deg) + cos(y_deg),1.0) ", + "equal(sin(y_deg) + sin(y_deg),sqrt(3))", + "equal(cos(x_deg) + cos(x_deg),sqrt(3))" + }; static const std::size_t expression_string_size = sizeof(expression_string) / sizeof(std::string); @@ -5372,9 +5608,17 @@ inline std::size_t load_expressions(const std::string& file_name, } template -inline bool run_test14() +inline T isnan(const T t) { - typedef exprtk::expression expression_t; + return std::isnan(t) ? T(1) : T(0); +} + +template +bool run_test14() +{ + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + typedef typename parser_t::settings_store settings_t; T x = T(0); T y = T(0); @@ -5394,6 +5638,8 @@ inline bool run_test14() exprtk::polynomial poly11; exprtk::polynomial poly12; + exprtk::rtl::vecops::package vector_package; + exprtk::symbol_table symbol_table; symbol_table.add_constants(); symbol_table.add_variable("x",x); @@ -5412,24 +5658,42 @@ inline bool run_test14() symbol_table.add_function("poly10", poly10); symbol_table.add_function("poly11", poly11); symbol_table.add_function("poly12", poly12); + symbol_table.add_function("isnan" , isnan ); + + symbol_table.add_package(vector_package); expression_t expression; expression.register_symbol_table(symbol_table); exprtk::parser parser; + static const std::size_t secondary_compile_options = + settings_t::e_replacer + + settings_t::e_joiner + + settings_t::e_numeric_check + + settings_t::e_bracket_check + + settings_t::e_sequence_check + + settings_t::e_strength_reduction; + + const settings_t settings(secondary_compile_options); + parser_t secondary_parser(settings); + std::deque expr_str_list; + std::deque expr_noncomm_str_list; - load_expressions("exprtk_functional_test.txt" ,expr_str_list); - load_expressions("exprtk_functional_ext_test.txt",expr_str_list); + load_expressions("exprtk_functional_test.txt" , expr_str_list); + load_expressions("exprtk_functional_ext_test.txt" , expr_str_list); if (expr_str_list.empty()) { return true; } + load_expressions("exprtk_noncommutative_test.txt" , expr_noncomm_str_list); + std::deque > expression_list; - bool failure = false; + bool error_found = false; + static const std::size_t rounds = 5; for (std::size_t r = 0; r < rounds; ++r) @@ -5446,22 +5710,42 @@ inline bool run_test14() parser.error().c_str(), expr_str_list[i].c_str()); - failure = true; + error_found = true; } else + { expression_list.push_back(current_expression); + } + } + + for (std::size_t i = 0; i < expr_noncomm_str_list.size(); ++i) + { + exprtk::expression current_expression; + + current_expression.register_symbol_table(symbol_table); + + if (!secondary_parser.compile(expr_noncomm_str_list[i],current_expression)) + { + printf("run_test14() - Error: %s Expression: %s [secondary parser]\n", + secondary_parser.error().c_str(), + expr_noncomm_str_list[i].c_str()); + + error_found = true; + } } - if (failure) + if (error_found) + { break; + } for (std::size_t i = 0; i < expression_list.size(); ++i) { - T result = expression_list[i].value(); + const T result = expression_list[i].value(); if (result != T(1)) { - failure = true; + error_found = true; printf("run_test14() - Error with evaluation of expression: %s\n", expr_str_list[i].c_str()); @@ -5470,15 +5754,17 @@ inline bool run_test14() expression_list.clear(); - if (failure) + if (error_found) + { break; + } } - return !failure; + return !error_found; } template -inline bool run_test15() +bool run_test15() { typedef exprtk::expression expression_t; @@ -5493,26 +5779,26 @@ inline bool run_test15() symbol_table.add_variable("z",z); static const std::string expr_str_list[] = - { - "2 - (x + y) / z//Comment 01 ", - "2 - (x + y) / z#Comment 02 ", - "2 - (x + y) / z //Comment 03 ", - "2 - (x + y) / z #Comment 04 ", - "2 - (x + y) / z//Comment 05 \n", - "2 - (x + y) / z#Comment 06 \n", - "2 - (x + y) / z //Comment 07\n", - "2 - (x + y) / z #Comment 08 \n", - "/* Comment 09*/2 - (x + y) / z", - "/* Comment 10*/2 - (x + y) / z\n", - "/* Comment 11*/2 - (x + y) / z/* Comment 12*/", - "/* Comment 13*/2 - (x + y) / z/* Comment 14*/\n", - "2 - /* Comment 15 */(x + y) / z", - "2 - /* Comment 16 */(x + y) /* Comment 17 *// z \n", - "2 - /* Comment 18 */(x + y) /* Comment 19 */ / z //Comment 20\n", - "2 - /* Comment 21 */(x + y) /* Comment 22 */ / z #Comment 23\n", - "2 - /* Comment 24 */(x + y) /* Comment 25 */ / z //Comment 26", - "2 - /* Comment 27 */(x + y) /* Comment 28 */ / z #Comment 29" - }; + { + "2 - (x + y) / z//Comment 01 ", + "2 - (x + y) / z#Comment 02 ", + "2 - (x + y) / z //Comment 03 ", + "2 - (x + y) / z #Comment 04 ", + "2 - (x + y) / z//Comment 05 \n", + "2 - (x + y) / z#Comment 06 \n", + "2 - (x + y) / z //Comment 07\n", + "2 - (x + y) / z #Comment 08 \n", + "/* Comment 09*/2 - (x + y) / z", + "/* Comment 10*/2 - (x + y) / z\n", + "/* Comment 11*/2 - (x + y) / z/* Comment 12*/", + "/* Comment 13*/2 - (x + y) / z/* Comment 14*/\n", + "2 - /* Comment 15 */(x + y) / z", + "2 - /* Comment 16 */(x + y) /* Comment 17 *// z \n", + "2 - /* Comment 18 */(x + y) /* Comment 19 */ / z //Comment 20\n", + "2 - /* Comment 21 */(x + y) /* Comment 22 */ / z #Comment 23\n", + "2 - /* Comment 24 */(x + y) /* Comment 25 */ / z //Comment 26", + "2 - /* Comment 27 */(x + y) /* Comment 28 */ / z #Comment 29" + }; static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); std::deque expression_list; @@ -5554,7 +5840,7 @@ inline bool run_test15() } } - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list.size(); ++i) { @@ -5568,11 +5854,11 @@ inline bool run_test15() static_cast(result), expr_str_list[i].c_str()); - failure = true; + error_found = true; } } - return !failure; + return !error_found; } template @@ -5582,23 +5868,23 @@ struct base_func : public exprtk::ifunction typedef const T& type; base_func(const std::size_t& n) : exprtk::ifunction(n) {} - inline T operator()(type v0, type v1, type v2, type v3, type v4) { return (v0 + v1 + v2 + v3 + v4); } - inline T operator()(type v0, type v1, type v2, type v3) { return (v0 + v1 + v2 + v3); } - inline T operator()(type v0, type v1, type v2) { return (v0 + v1 + v2); } - inline T operator()(type v0, type v1) { return (v0 + v1); } - inline T operator()(type v0) { return v0; } - inline T operator()() { return T(1.1234); } + inline T operator()(type v0, type v1, type v2, type v3, type v4) exprtk_test_override { return (v0 + v1 + v2 + v3 + v4); } + inline T operator()(type v0, type v1, type v2, type v3) exprtk_test_override { return (v0 + v1 + v2 + v3); } + inline T operator()(type v0, type v1, type v2) exprtk_test_override { return (v0 + v1 + v2); } + inline T operator()(type v0, type v1) exprtk_test_override { return (v0 + v1); } + inline T operator()(type v0) exprtk_test_override { return v0; } + inline T operator()() exprtk_test_override { return T(1.1234); } }; -template struct test_func5 : public base_func { test_func5() : base_func(5){} }; -template struct test_func4 : public base_func { test_func4() : base_func(4){} }; -template struct test_func3 : public base_func { test_func3() : base_func(3){} }; -template struct test_func2 : public base_func { test_func2() : base_func(2){} }; -template struct test_func1 : public base_func { test_func1() : base_func(1){} }; -template struct test_func0 : public base_func { test_func0() : base_func(0){} }; +template struct test_func5 exprtk_test_final : public base_func { test_func5() : base_func(5){} }; +template struct test_func4 exprtk_test_final : public base_func { test_func4() : base_func(4){} }; +template struct test_func3 exprtk_test_final : public base_func { test_func3() : base_func(3){} }; +template struct test_func2 exprtk_test_final : public base_func { test_func2() : base_func(2){} }; +template struct test_func1 exprtk_test_final : public base_func { test_func1() : base_func(1){} }; +template struct test_func0 exprtk_test_final : public base_func { test_func0() : base_func(0){} }; template -inline bool run_test16() +bool run_test16() { typedef exprtk::expression expression_t; @@ -5631,71 +5917,71 @@ inline bool run_test16() symbol_table.add_function("test_func5",test_func05); static const std::string expr_str_list[] = - { - "test_func0 = test_func0()", - "test_func0 == test_func0()", - "equal(1.1 + test_func0,test_func0() + 1.1)", - "equal(test_func0 + 1.1,1.1 + test_func0())", - "equal((1.1 + test_func0),(test_func0() + 1.1))", - "equal((test_func0 + 1.1),(1.1 + test_func0()))", - "equal(test_func0,test_func0())", - "equal(test_func0,1.1234)", - "equal(test_func0(),1.1234)", - "equal(test_func0 + test_func0(),2 * 1.1234)", - "equal((test_func0 + test_func0()),2 * 1.1234)", - "equal((test_func0) + (test_func0()),2 * 1.1234)", - "equal(test_func1(x),(x))", - "equal(test_func2(x,y),(x + y))", - "equal(test_func3(x,y,z),(x + y + z))", - "equal(test_func4(x,y,z,w),(x + y + z + w))", - "equal(test_func5(x,y,z,w,u),(x + y + z + w + u))", - "equal(1.1 + test_func0,1.1234 + 1.1)", - "equal(1.1 + test_func0(),1.1234 + 1.1)", - "equal(1.1 + test_func1(x),(x + 1.1))", - "equal(1.1 + test_func2(x,y),(x + y + 1.1))", - "equal(1.1 + test_func3(x,y,z),(x + y + z + 1.1))", - "equal(1.1 + test_func4(x,y,z,w),(x + y + z + w + 1.1))", - "equal(1.1 + test_func5(x,y,z,w,u),(x + y + z + w + u + 1.1))", - "equal(test_func0 + 2.2,1.1234 + 2.2)", - "equal(test_func0() + 2.2,1.1234 + 2.2)", - "equal(test_func1(x) + 2.2,(x + 2.2))", - "equal(test_func2(x,y) + 2.2,(x + y + 2.2))", - "equal(test_func3(x,y,z) + 2.2,(x + y + z + 2.2))", - "equal(test_func4(x,y,z,w) + 2.2,(x + y + z + w + 2.2))", - "equal(test_func5(x,y,z,w,u) + 2.2,(x + y + z + w + u + 2.2))", - "equal({[test_func1(x)]},{[(x)]})", - "equal({[test_func2(x,y)]},{[(x + y)]})", - "equal({[test_func3(x,y,z)]},{[(x + y + z)]})", - "equal({[test_func4(x,y,z,w)]},{[(x + y + z + w)]})", - "equal({[test_func5(x,y,z,w,u)]},{[(x + y + z + w + u)]})", - "equal(test_func1(2.12),(2.12))", - "equal(test_func2(2.12,3.12),(2.12 + 3.12))", - "equal(test_func3(2.12,3.12,4.12),(2.12 + 3.12 + 4.12))", - "equal(test_func4(2.12,3.12,4.12,5.12),(2.12 + 3.12 + 4.12 + 5.12))", - "equal(test_func5(2.12,3.12,4.12,5.12,6.12),(2.12 + 3.12 + 4.12 + 5.12 + 6.12))", - "equal(1.1 + test_func1(2.12),(2.12 + 1.1))", - "equal(1.1 + test_func2(2.12,3.12),(2.12 + 3.12 + 1.1))", - "equal(1.1 + test_func3(2.12,3.12,4.12),(2.12 + 3.12 + 4.12 + 1.1))", - "equal(1.1 + test_func4(2.12,3.12,4.12,5.12),(2.12 + 3.12 + 4.12 + 5.12 + 1.1))", - "equal(1.1 + test_func5(2.12,3.12,4.12,5.12,6.12),(2.12 + 3.12 + 4.12 + 5.12 + 6.12 + 1.1))", - "equal(test_func1(2.12) + 2.2,(2.12 + 2.2))", - "equal(test_func2(2.12,3.12) + 2.2,(2.12 + 3.12 + 2.2))", - "equal(test_func3(2.12,3.12,4.12) + 2.2,(2.12 + 3.12 + 4.12 + 2.2))", - "equal(test_func4(2.12,3.12,4.12,5.12) + 2.2,(2.12 + 3.12 + 4.12 + 5.12 + 2.2))", - "equal(test_func5(2.12,3.12,4.12,5.12,6.12) + 2.2,(2.12 + 3.12 + 4.12 + 5.12 + 6.12 + 2.2))", - "equal({[test_func1(2.12)]},{[(2.12)]})", - "equal({[test_func2(2.12,3.12)]},{[(2.12 + 3.12)]})", - "equal({[test_func3(2.12,3.12,4.12)]},{[(2.12 + 3.12 + 4.12)]})", - "equal({[test_func4(2.12,3.12,4.12,5.12)]},{[(2.12 + 3.12 + 4.12 + 5.12)]})", - "equal({[test_func5(2.12,3.12,4.12,5.12,6.12)]},{[(2.12 + 3.12 + 4.12 + 5.12 + 6.12)]})", - "TeSt_FuNc0 = tEsT_fUnC0()", - "TEst_fuNC0 == tESt_fUNc0()", - "EquaL(tEsT_FuNC1(x),(x))", - "eQuAl(teSt_fUnc2(x,y),(x + y))", - "EqUaL(tEsT_fUNc3(x,y,z),(x + y + z))", - "EQUal(TEst_FunC4(x,y,z,w),(x + y + z + w))", - "eqUAL(tEsT_FuNc5(x,y,z,w,u),(x + y + z + w + u))" - }; + { + "test_func0 = test_func0()", + "test_func0 == test_func0()", + "equal(1.1 + test_func0,test_func0() + 1.1)", + "equal(test_func0 + 1.1,1.1 + test_func0())", + "equal((1.1 + test_func0),(test_func0() + 1.1))", + "equal((test_func0 + 1.1),(1.1 + test_func0()))", + "equal(test_func0,test_func0())", + "equal(test_func0,1.1234)", + "equal(test_func0(),1.1234)", + "equal(test_func0 + test_func0(),2 * 1.1234)", + "equal((test_func0 + test_func0()),2 * 1.1234)", + "equal((test_func0) + (test_func0()),2 * 1.1234)", + "equal(test_func1(x),(x))", + "equal(test_func2(x,y),(x + y))", + "equal(test_func3(x,y,z),(x + y + z))", + "equal(test_func4(x,y,z,w),(x + y + z + w))", + "equal(test_func5(x,y,z,w,u),(x + y + z + w + u))", + "equal(1.1 + test_func0,1.1234 + 1.1)", + "equal(1.1 + test_func0(),1.1234 + 1.1)", + "equal(1.1 + test_func1(x),(x + 1.1))", + "equal(1.1 + test_func2(x,y),(x + y + 1.1))", + "equal(1.1 + test_func3(x,y,z),(x + y + z + 1.1))", + "equal(1.1 + test_func4(x,y,z,w),(x + y + z + w + 1.1))", + "equal(1.1 + test_func5(x,y,z,w,u),(x + y + z + w + u + 1.1))", + "equal(test_func0 + 2.2,1.1234 + 2.2)", + "equal(test_func0() + 2.2,1.1234 + 2.2)", + "equal(test_func1(x) + 2.2,(x + 2.2))", + "equal(test_func2(x,y) + 2.2,(x + y + 2.2))", + "equal(test_func3(x,y,z) + 2.2,(x + y + z + 2.2))", + "equal(test_func4(x,y,z,w) + 2.2,(x + y + z + w + 2.2))", + "equal(test_func5(x,y,z,w,u) + 2.2,(x + y + z + w + u + 2.2))", + "equal({[test_func1(x)]},{[(x)]})", + "equal({[test_func2(x,y)]},{[(x + y)]})", + "equal({[test_func3(x,y,z)]},{[(x + y + z)]})", + "equal({[test_func4(x,y,z,w)]},{[(x + y + z + w)]})", + "equal({[test_func5(x,y,z,w,u)]},{[(x + y + z + w + u)]})", + "equal(test_func1(2.12),(2.12))", + "equal(test_func2(2.12,3.12),(2.12 + 3.12))", + "equal(test_func3(2.12,3.12,4.12),(2.12 + 3.12 + 4.12))", + "equal(test_func4(2.12,3.12,4.12,5.12),(2.12 + 3.12 + 4.12 + 5.12))", + "equal(test_func5(2.12,3.12,4.12,5.12,6.12),(2.12 + 3.12 + 4.12 + 5.12 + 6.12))", + "equal(1.1 + test_func1(2.12),(2.12 + 1.1))", + "equal(1.1 + test_func2(2.12,3.12),(2.12 + 3.12 + 1.1))", + "equal(1.1 + test_func3(2.12,3.12,4.12),(2.12 + 3.12 + 4.12 + 1.1))", + "equal(1.1 + test_func4(2.12,3.12,4.12,5.12),(2.12 + 3.12 + 4.12 + 5.12 + 1.1))", + "equal(1.1 + test_func5(2.12,3.12,4.12,5.12,6.12),(2.12 + 3.12 + 4.12 + 5.12 + 6.12 + 1.1))", + "equal(test_func1(2.12) + 2.2,(2.12 + 2.2))", + "equal(test_func2(2.12,3.12) + 2.2,(2.12 + 3.12 + 2.2))", + "equal(test_func3(2.12,3.12,4.12) + 2.2,(2.12 + 3.12 + 4.12 + 2.2))", + "equal(test_func4(2.12,3.12,4.12,5.12) + 2.2,(2.12 + 3.12 + 4.12 + 5.12 + 2.2))", + "equal(test_func5(2.12,3.12,4.12,5.12,6.12) + 2.2,(2.12 + 3.12 + 4.12 + 5.12 + 6.12 + 2.2))", + "equal({[test_func1(2.12)]},{[(2.12)]})", + "equal({[test_func2(2.12,3.12)]},{[(2.12 + 3.12)]})", + "equal({[test_func3(2.12,3.12,4.12)]},{[(2.12 + 3.12 + 4.12)]})", + "equal({[test_func4(2.12,3.12,4.12,5.12)]},{[(2.12 + 3.12 + 4.12 + 5.12)]})", + "equal({[test_func5(2.12,3.12,4.12,5.12,6.12)]},{[(2.12 + 3.12 + 4.12 + 5.12 + 6.12)]})", + "TeSt_FuNc0 = tEsT_fUnC0()", + "TEst_fuNC0 == tESt_fUNc0()", + "EquaL(tEsT_FuNC1(x),(x))", + "eQuAl(teSt_fUnc2(x,y),(x + y))", + "EqUaL(tEsT_fUNc3(x,y,z),(x + y + z))", + "EQUal(TEst_FunC4(x,y,z,w),(x + y + z + w))", + "eqUAL(tEsT_FuNc5(x,y,z,w,u),(x + y + z + w + u))" + }; static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); std::deque expression_list; @@ -5719,7 +6005,7 @@ inline bool run_test16() expression_list.push_back(expression); } - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list.size(); ++i) { @@ -5728,15 +6014,15 @@ inline bool run_test16() printf("run_test16() - Error in evaluation! (1) Expression: %s\n", expr_str_list[i].c_str()); - failure = true; + error_found = true; } } - return !failure; + return !error_found; } template -inline bool run_test17() +bool run_test17() { typedef exprtk::expression expression_t; @@ -5765,55 +6051,55 @@ inline bool run_test17() symbol_table.add_variable("zero",zero); static const std::string expr_str_list[] = - { - "equal(mand(one,one),1.0)", - "equal(mand(one,zero),0.0)", - "equal(mand(zero,one),0.0)", - "equal(mand(zero,zero),0.0)", - "equal(mand(one,one),1.0)", - "equal(mand(one,one,one),1.0)", - "equal(mand(one,one,one,one),1.0)", - "equal(mand(one,one,one,one,one),1.0)", - "equal(mand(one,one,zero),0.0)", - "equal(mand(one,one,one,zero),0.0)", - "equal(mand(one,one,one,one,zero),0.0)", - "equal(mand(one,one,one,one,one,zero),0.0)", - "equal(mor(one,one),1.0)", - "equal(mor(one,zero),1.0)", - "equal(mor(zero,one),1.0)", - "equal(mor(zero,zero),0.0)", - "equal(mor(one,one),1.0)", - "equal(mor(one,one,zero),1.0)", - "equal(mor(one,zero,one),1.0)", - "equal(mor(one,zero,one,zero),1.0)", - "equal(mor(zero,one),1.0)", - "equal(mor(zero,zero,one),1.0)", - "equal(mor(zero,zero,zero,zero,one),1.0)", - "equal(mor(zero,zero,zero,zero,zero,one),1.0)", - "equal(mor(zero,zero,zero,zero,zero,zero,zero,zero),0.0)", - "equal((one nand one),not(mand(one,one)))", - "equal((one nand zero),not(mand(one,zero)))", - "equal((zero nand one),not(mand(zero,one)))", - "equal((zero nand zero),not(mand(zero,zero)))", - "equal((one nor one),not(mor(one,one)))", - "equal((one nor zero),not(mor(one,zero)))", - "equal((zero nor one),not(mor(zero,one)))", - "equal((zero nor zero),not(mor(zero,zero)))", - "equal(sum(x,y,z,w,u,v,t),(x+y+z+w+u+v+t))", - "equal(sum(x+t,y+v,z+u,w+w,u+z,v+y,t+x),2*(x+y+z+w+u+v+t))", - "equal(mul(x,y,z,w,u,v,t),(x*y*z*w*u*v*t))", - "equal(mul(x*t,y*v,z*u,w*w,u*z,v*y,t*x),(x*y*z*w*u*v*t)^2)", - "equal(sum(x,1.0,y,2.0,z,3.0,w,4.0,u,5.0,v,6.0,t),(x+y+z+w+u+v+t+21.0))", - "equal(sum(x+1.0,y+2.0,z+3.0,w+4.0,u+5.0,v+6.0,t),(x+y+z+w+u+v+t+21.0))", - "equal(mul(x,1.0,y,2.0,z,3.0,w,4.0,u,5.0,v,6.0,t),(x*y*z*w*u*v*t*720.0))", - "equal(mul(x*1.0,y*2.0,z*3.0,w*4.0,u*5.0,v*6.0,t),(x*y*z*w*u*v*t*720.0))", - "equal(min(x,y,z,w,u,v,t,zero),zero)", - "equal(min(x+y,z+w,u+v,t,zero),zero)", - "equal(max(one,x,y,z,w,u,v,t),t)", - "equal(max(x+y,z+w,u+v,t,one),u+v)", - "equal(avg(x,y,z,w,u,v,t),(x+y+z+w+u+v+t)/7.0)", - "equal(avg(x+t,y+v,z+u,w+w,u+z,v+y,t+x),2/7*(x+y+z+w+u+v+t))" - }; + { + "equal(mand(one,one),1.0)", + "equal(mand(one,zero),0.0)", + "equal(mand(zero,one),0.0)", + "equal(mand(zero,zero),0.0)", + "equal(mand(one,one),1.0)", + "equal(mand(one,one,one),1.0)", + "equal(mand(one,one,one,one),1.0)", + "equal(mand(one,one,one,one,one),1.0)", + "equal(mand(one,one,zero),0.0)", + "equal(mand(one,one,one,zero),0.0)", + "equal(mand(one,one,one,one,zero),0.0)", + "equal(mand(one,one,one,one,one,zero),0.0)", + "equal(mor(one,one),1.0)", + "equal(mor(one,zero),1.0)", + "equal(mor(zero,one),1.0)", + "equal(mor(zero,zero),0.0)", + "equal(mor(one,one),1.0)", + "equal(mor(one,one,zero),1.0)", + "equal(mor(one,zero,one),1.0)", + "equal(mor(one,zero,one,zero),1.0)", + "equal(mor(zero,one),1.0)", + "equal(mor(zero,zero,one),1.0)", + "equal(mor(zero,zero,zero,zero,one),1.0)", + "equal(mor(zero,zero,zero,zero,zero,one),1.0)", + "equal(mor(zero,zero,zero,zero,zero,zero,zero,zero),0.0)", + "equal((one nand one),not(mand(one,one)))", + "equal((one nand zero),not(mand(one,zero)))", + "equal((zero nand one),not(mand(zero,one)))", + "equal((zero nand zero),not(mand(zero,zero)))", + "equal((one nor one),not(mor(one,one)))", + "equal((one nor zero),not(mor(one,zero)))", + "equal((zero nor one),not(mor(zero,one)))", + "equal((zero nor zero),not(mor(zero,zero)))", + "equal(sum(x,y,z,w,u,v,t),(x+y+z+w+u+v+t))", + "equal(sum(x+t,y+v,z+u,w+w,u+z,v+y,t+x),2*(x+y+z+w+u+v+t))", + "equal(mul(x,y,z,w,u,v,t),(x*y*z*w*u*v*t))", + "equal(mul(x*t,y*v,z*u,w*w,u*z,v*y,t*x),(x*y*z*w*u*v*t)^2)", + "equal(sum(x,1.0,y,2.0,z,3.0,w,4.0,u,5.0,v,6.0,t),(x+y+z+w+u+v+t+21.0))", + "equal(sum(x+1.0,y+2.0,z+3.0,w+4.0,u+5.0,v+6.0,t),(x+y+z+w+u+v+t+21.0))", + "equal(mul(x,1.0,y,2.0,z,3.0,w,4.0,u,5.0,v,6.0,t),(x*y*z*w*u*v*t*720.0))", + "equal(mul(x*1.0,y*2.0,z*3.0,w*4.0,u*5.0,v*6.0,t),(x*y*z*w*u*v*t*720.0))", + "equal(min(x,y,z,w,u,v,t,zero),zero)", + "equal(min(x+y,z+w,u+v,t,zero),zero)", + "equal(max(one,x,y,z,w,u,v,t),t)", + "equal(max(x+y,z+w,u+v,t,one),u+v)", + "equal(avg(x,y,z,w,u,v,t),(x+y+z+w+u+v+t)/7.0)", + "equal(avg(x+t,y+v,z+u,w+w,u+z,v+y,t+x),2/7*(x+y+z+w+u+v+t))" + }; static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); std::deque expression_list; @@ -5837,7 +6123,7 @@ inline bool run_test17() expression_list.push_back(expression); } - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list.size(); ++i) { @@ -5846,15 +6132,15 @@ inline bool run_test17() printf("run_test17() - Error in evaluation! (1) Expression: %s\n", expr_str_list[i].c_str()); - failure = true; + error_found = true; } } - return !failure; + return !error_found; } template -struct va_func : public exprtk::ivararg_function +struct va_func exprtk_test_final : public exprtk::ivararg_function { va_func() { @@ -5863,7 +6149,7 @@ struct va_func : public exprtk::ivararg_function exprtk::set_max_num_args(*this, 20); } - inline T operator()(const std::vector& arglist) + inline T operator()(const std::vector& arglist) exprtk_test_override { T result = T(0); @@ -5877,7 +6163,7 @@ struct va_func : public exprtk::ivararg_function }; template -struct gen_func : public exprtk::igeneric_function +struct gen_func exprtk_test_final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::generic_type generic_type; typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -5889,12 +6175,12 @@ struct gen_func : public exprtk::igeneric_function using exprtk::igeneric_function::operator(); gen_func() - : scalar_count(0), - vector_count(0), - string_count(0) + : scalar_count(0) + , vector_count(0) + , string_count(0) {} - inline T operator()(parameter_list_t params) + inline T operator()(parameter_list_t params) exprtk_test_override { for (std::size_t i = 0; i < params.size(); ++i) { @@ -5934,7 +6220,7 @@ struct gen_func : public exprtk::igeneric_function }; template -struct gen_func2 : public exprtk::igeneric_function +struct gen_func2 exprtk_test_final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -5943,19 +6229,19 @@ struct gen_func2 : public exprtk::igeneric_function gen_func2() {} - inline T operator()(parameter_list_t) + inline T operator()(parameter_list_t) exprtk_test_override { return T(0); } - inline T operator()(const std::size_t&, parameter_list_t params) + inline T operator()(const std::size_t&, parameter_list_t params) exprtk_test_override { return this->operator()(params); } }; template -struct inc_func : public exprtk::igeneric_function +struct inc_func exprtk_test_final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::generic_type generic_type; typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -5969,7 +6255,7 @@ struct inc_func : public exprtk::igeneric_function inc_func() {} - inline T operator()(parameter_list_t params) + inline T operator()(parameter_list_t params) exprtk_test_override { for (std::size_t i = 0; i < params.size(); ++i) { @@ -6010,14 +6296,14 @@ struct inc_func : public exprtk::igeneric_function return T(0); } - inline T operator()(const std::size_t&, parameter_list_t params) + inline T operator()(const std::size_t&, parameter_list_t params) exprtk_test_override { return this->operator()(params); } }; template -struct rem_space_and_uppercase : public exprtk::igeneric_function +struct rem_space_and_uppercase exprtk_test_final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function igenfunc_t; typedef typename igenfunc_t::generic_type generic_type; @@ -6030,7 +6316,7 @@ struct rem_space_and_uppercase : public exprtk::igeneric_function : igenfunc_t("S",igenfunc_t::e_rtrn_string) {} - inline T operator()(std::string& result, parameter_list_t params) + inline T operator()(std::string& result, parameter_list_t params) exprtk_test_override { string_t string(params[0]); @@ -6048,7 +6334,7 @@ struct rem_space_and_uppercase : public exprtk::igeneric_function return T(0); } - inline T operator()(const std::size_t& param_seq_index, std::string& result, parameter_list_t params) + inline T operator()(const std::size_t& param_seq_index, std::string& result, parameter_list_t params) exprtk_test_override { if (1 == param_seq_index) return this->operator()(result,params); @@ -6058,7 +6344,7 @@ struct rem_space_and_uppercase : public exprtk::igeneric_function }; template -struct vararg_func : public exprtk::igeneric_function +struct vararg_func exprtk_test_final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -6075,7 +6361,7 @@ struct vararg_func : public exprtk::igeneric_function : exprtk::igeneric_function("Z|T*|V") {} - inline T operator()(const std::size_t& ps_index, parameter_list_t /*arglist*/) + inline T operator()(const std::size_t& ps_index, parameter_list_t /*arglist*/) exprtk_test_override { switch (ps_index) { // Overload resolution: @@ -6088,7 +6374,7 @@ struct vararg_func : public exprtk::igeneric_function }; template -struct vecrebase_func : public exprtk::igeneric_function +struct vecrebase_func exprtk_test_final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -6104,7 +6390,7 @@ struct vecrebase_func : public exprtk::igeneric_function : exprtk::igeneric_function("V") {} - inline T operator()(parameter_list_t params) + inline T operator()(parameter_list_t params) exprtk_test_override { vector_t v(params[0]); return std::accumulate(v.begin(), v.end(), T(0)); @@ -6112,7 +6398,7 @@ struct vecrebase_func : public exprtk::igeneric_function }; template -struct overload_func : exprtk::igeneric_function +struct overload_func exprtk_test_final : exprtk::igeneric_function { typedef typename exprtk::igeneric_function igfun_t; typedef typename igfun_t::parameter_list_t parameter_list_t; @@ -6122,8 +6408,8 @@ struct overload_func : exprtk::igeneric_function using exprtk::igeneric_function::operator(); overload_func(const std::string& param_seq_list) - : exprtk::igeneric_function(param_seq_list, igfun_t::e_rtrn_overload), - current_ps_index(std::numeric_limits::max()) + : exprtk::igeneric_function(param_seq_list, igfun_t::e_rtrn_overload) + , current_ps_index(std::numeric_limits::max()) { clear(); } @@ -6135,7 +6421,7 @@ struct overload_func : exprtk::igeneric_function } inline T operator()(const std::size_t& ps_index, - parameter_list_t parameters) + parameter_list_t parameters) exprtk_test_override { current_ps_index = ps_index; determine_param_seq(parameters); @@ -6144,7 +6430,7 @@ struct overload_func : exprtk::igeneric_function inline T operator()(const std::size_t& ps_index, std::string& result, - parameter_list_t parameters) + parameter_list_t parameters) exprtk_test_override { current_ps_index = ps_index; determine_param_seq(parameters); @@ -6182,8 +6468,8 @@ struct overload_func : exprtk::igeneric_function struct test_result_t { test_result_t(const std::size_t psi, const std::string& ps) - : ps_index(psi), - param_seq(ps) + : ps_index(psi) + , param_seq(ps) {} std::size_t ps_index; @@ -6191,8 +6477,19 @@ struct overload_func : exprtk::igeneric_function }; }; +struct vector_access_rtc_counter : public exprtk::vector_access_runtime_check +{ + bool handle_runtime_violation(violation_context&) exprtk_test_override + { + rtc_count++; + return false; + } + + std::size_t rtc_count; +}; + template -inline bool run_test18() +bool run_test18() { { exprtk::symbol_table symbol_table; @@ -6309,23 +6606,23 @@ inline bool run_test18() symbol_table.add_function("va_func",vaf); static const std::string expr_str_list[] = - { - "equal(va_func,(0))", - "equal(va_func(),(0))", - "equal(va_func(1,2,3,4,5,6,7,8,9),(1+2+3+4+5+6+7+8+9))", - "equal(va_func(1,x,3,y,5,z,7,w,9),(1+x+3+y+5+z+7+w+9))", - "equal(va_func(x,2,y,4,z,6,w,8,u),(x+2+y+4+z+6+w+8+u))", - "equal(va_func(x,y,z,w,u,v,t,1,2,3),(x+y+z+w+u+v+t+1+2+3))", - "equal(va_func(x,y,z,w,u,v,t),(x+y+z+w+u+v+t))", - "equal(va_func(x+t,y+v,z+u,w+w,u+z,v+y,t+x),2*(x+y+z+w+u+v+t))", - "equal(1+va_func(1,x,3,y,5,z,7,w,9),(1+x+3+y+5+z+7+w+9)+1)", - "equal(va_func(va_func(x,y,z,w,u,v,t),va_func(x,y,z,w,u,v,t)),2*(x+y+z+w+u+v+t))", - "equal(va_func(va_func(x),va_func(y),va_func(z)),va_func(x,y,z))", - "equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x)))))))),x)", - "equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(123.456)))))))),123.456)", - "equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x+1)))))))),x+1)", - "equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x+y)))))))),x+y)" - }; + { + "equal(va_func,(0))", + "equal(va_func(),(0))", + "equal(va_func(1,2,3,4,5,6,7,8,9),(1+2+3+4+5+6+7+8+9))", + "equal(va_func(1,x,3,y,5,z,7,w,9),(1+x+3+y+5+z+7+w+9))", + "equal(va_func(x,2,y,4,z,6,w,8,u),(x+2+y+4+z+6+w+8+u))", + "equal(va_func(x,y,z,w,u,v,t,1,2,3),(x+y+z+w+u+v+t+1+2+3))", + "equal(va_func(x,y,z,w,u,v,t),(x+y+z+w+u+v+t))", + "equal(va_func(x+t,y+v,z+u,w+w,u+z,v+y,t+x),2*(x+y+z+w+u+v+t))", + "equal(1+va_func(1,x,3,y,5,z,7,w,9),(1+x+3+y+5+z+7+w+9)+1)", + "equal(va_func(va_func(x,y,z,w,u,v,t),va_func(x,y,z,w,u,v,t)),2*(x+y+z+w+u+v+t))", + "equal(va_func(va_func(x),va_func(y),va_func(z)),va_func(x,y,z))", + "equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x)))))))),x)", + "equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(123.456)))))))),123.456)", + "equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x+1)))))))),x+1)", + "equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x+y)))))))),x+y)" + }; static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); std::deque expression_list; @@ -6339,7 +6636,7 @@ inline bool run_test18() if (!parser.compile(expr_str_list[i],expression)) { - printf("run_test18() - VarArg Error: %s Expression: %s\n", + printf("run_test18() - [1] VarArg Error: %s Expression: %s\n", parser.error().c_str(), expr_str_list[i].c_str()); @@ -6349,7 +6646,7 @@ inline bool run_test18() expression_list.push_back(expression); } - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list.size(); ++i) { @@ -6358,12 +6655,14 @@ inline bool run_test18() printf("run_test18() - Error in evaluation! (1) Expression: %s\n", expr_str_list[i].c_str()); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } { @@ -6400,39 +6699,40 @@ inline bool run_test18() symbol_table.add_stringvar("s0", s0); symbol_table.add_function ("gen_func", f); - std::string expression_list[] = - { - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func('abc123', s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');" - }; + const std::string expression_list[] = + { + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:6]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:6]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:6],v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:6],v0, v1 + v2);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(x, 2x + y, z, 2w / 3, 'abc123',s0[2:6],v0, v1 + v2, v0[2]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(2x + y, z, 2w / 3, 'abc123',s0[2:6],v0, v1 + v2, v0[2], x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(z, 2w / 3, 'abc123',s0[2:6],v0, v1 + v2, v0[2], x, 2x + y);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(2w / 3, 'abc123',s0[2:6],v0, v1 + v2, v0[2], x, 2x + y, z);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func('abc123', s0[2:6],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(s0[2:6],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');" + }; static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list_size; ++i) { + const std::string& expression_str = expression_list[i]; expression_t expression; expression.register_symbol_table(symbol_table); parser_t parser; - if (!parser.compile(expression_list[i],expression)) + if (!parser.compile(expression_str,expression)) { - printf("run_test18() - GenFunc Error: %s Expression: %s [2]\n", + printf("run_test18() - [2] GenFunc Error: %s Expression: %s [2]\n", parser.error().c_str(), - expression_list[i].c_str()); + expression_str.c_str()); - failure = true; + error_found = true; continue; } @@ -6457,12 +6757,16 @@ inline bool run_test18() static_cast(f.vector_count), static_cast(f.string_count)); - failure = true; + error_found = true; } + + expression.release(); } - if (failure) + if (error_found) + { return false; + } } { @@ -6493,104 +6797,105 @@ inline bool run_test18() symbol_table.add_stringvar("s0", s0); symbol_table.add_function ("foo", f); - std::string expression_list[] = - { - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo('abc123', s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:3]+s0[4:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x,x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x,x,x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0,s0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0,s0,s0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0,v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0,v0,v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x,x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x,x,x);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0,s0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0,s0,s0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0,v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0,v0,v0);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", - "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);" - }; + const std::string expression_list[] = + { + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:6]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:6],v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:6],v0, v1 + v2);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x, 2x + y, z, 2w / 3, 'abc123',s0[2:6],v0, v1 + v2, v0[2]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(2x + y, z, 2w / 3, 'abc123',s0[2:6],v0, v1 + v2, v0[2], x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(z, 2w / 3, 'abc123',s0[2:6],v0, v1 + v2, v0[2], x, 2x + y);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(2w / 3, 'abc123',s0[2:6],v0, v1 + v2, v0[2], x, 2x + y, z);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo('abc123', s0[2:6],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:6],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:3]+s0[4:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x,x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x,x,x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0,s0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0,s0,s0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0,v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0,v0,v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x,x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x,x,x,x);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0,s0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0,s0,s0,s0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0,v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v0,v0,v0);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);", + "var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);" + }; static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); - std::string parameter_type_list[] = - { - "VVTTTTVSS", - "VTTTTVSSV", - "TTTTVSSVV", - "TTTVSSVVT", - "TTVSSVVT*", - "TVSSVVT*" , - "VSSVVT*" , - "SSVVTTTTV", - "SVVTTTTVS", - "SVVTTTTVS", - "V*T*VS*" , - "V*TTTTVSS", - "VVT*VSS" , - "VVTTTTVS*", - "T*", - "T*", - "T*", - "T*", - "S*", - "S*", - "S*", - "S*", - "V*", - "V*", - "V*", - "V*", - "T", - "TT", - "TTT", - "TTTT", - "S", - "SS", - "SSS", - "SSSS", - "V", - "VV", - "VVV", - "VVVV", - "TTTTTTT|STSTSTS|V*T*VS*" , - "TTTTTTT|STSTSTS|V*TTTTVSS", - "TTTTTTT|STSTSTS|VVT*VSS" , - "TTTTTTT|STSTSTS|VVTTTTVS*", - }; - - bool failure = false; + const std::string parameter_type_list[] = + { + "VVTTTTVSS", + "VTTTTVSSV", + "TTTTVSSVV", + "TTTVSSVVT", + "TTVSSVVT*", + "TVSSVVT*" , + "VSSVVT*" , + "SSVVTTTTV", + "SVVTTTTVS", + "SVVTTTTVS", + "V*T*VS*" , + "V*TTTTVSS", + "VVT*VSS" , + "VVTTTTVS*", + "T*", + "T*", + "T*", + "T*", + "S*", + "S*", + "S*", + "S*", + "V*", + "V*", + "V*", + "V*", + "T", + "TT", + "TTT", + "TTTT", + "S", + "SS", + "SSS", + "SSSS", + "V", + "VV", + "VVV", + "VVVV", + "TTTTTTT|STSTSTS|V*T*VS*" , + "TTTTTTT|STSTSTS|V*TTTTVSS", + "TTTTTTT|STSTSTS|VVT*VSS" , + "TTTTTTT|STSTSTS|VVTTTTVS*", + }; + + bool error_found = false; for (std::size_t i = 0; i < expression_list_size; ++i) { + const std::string& expression_str = expression_list[i]; expression_t expression; expression.register_symbol_table(symbol_table); @@ -6599,48 +6904,50 @@ inline bool run_test18() f.parameter_sequence = parameter_type_list[i]; - if (!parser.compile(expression_list[i],expression)) + if (!parser.compile(expression_str,expression)) { - printf("run_test18() - GenFunc2 Error: %s Expression: %s Parameter Sequence: %s [3]\n", + printf("run_test18() - [3] GenFunc2 Error: %s Expression: %s Parameter Sequence: %s [3]\n", parser.error().c_str(), - expression_list[i].c_str(), + expression_str.c_str(), parameter_type_list[i].c_str()); - failure = true; + error_found = true; continue; } expression.value(); } - if (failure) + if (error_found) + { return false; + } } { - bool failure = false; + bool error_found = false; - std::string expression_list[] = - { - "foo(v0,v1,v2,x,y,s0);", - "foo(v1,v2,x,y,s0,v0);", - "foo(v2,x,y,s0,v0,v1);", - "foo(x,y,s0,v0,v1,v2);", - "foo(y,s0,v0,v1,v2,x);", - "foo(s0,v0,v1,v2,x,y);" - }; + const std::string expression_list[] = + { + "foo(v0,v1,v2,x,y,s0);", + "foo(v1,v2,x,y,s0,v0);", + "foo(v2,x,y,s0,v0,v1);", + "foo(x,y,s0,v0,v1,v2);", + "foo(y,s0,v0,v1,v2,x);", + "foo(s0,v0,v1,v2,x,y);" + }; static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); - std::string parameter_type_list[] = - { - "VVVTTS", - "VVTTSV", - "VTTSVV", - "TTSVVV", - "TSVVVT", - "SVVVTT" - }; + const std::string parameter_type_list[] = + { + "VVVTTS", + "VVTTSV", + "VTTSVV", + "TTSVVV", + "TSVVVT", + "SVVVTT" + }; for (std::size_t i = 0; i < expression_list_size; ++i) { @@ -6674,13 +6981,13 @@ inline bool run_test18() symbol_table.add_constants(); - symbol_table.add_variable ("x" , x); - symbol_table.add_variable ("y" , y); - symbol_table.add_vector ("v0" ,v0); - symbol_table.add_vector ("v1" ,v1); - symbol_table.add_vector ("v2" ,v2); - symbol_table.add_stringvar("s0", s0); - symbol_table.add_function ("foo", f); + symbol_table.add_variable ("x" , x ); + symbol_table.add_variable ("y" , y ); + symbol_table.add_vector ("v0" , v0); + symbol_table.add_vector ("v1" , v1); + symbol_table.add_vector ("v2" , v2); + symbol_table.add_stringvar("s0", s0); + symbol_table.add_function ("foo", f ); expression_t expression; @@ -6692,12 +6999,12 @@ inline bool run_test18() if (!parser.compile(expression_list[i],expression)) { - printf("run_test18() - IncFunc Error: %s Expression: %s Parameter Sequence: %s [4]\n", + printf("run_test18() - [4] IncFunc Error: %s Expression: %s Parameter Sequence: %s [4]\n", parser.error().c_str(), expression_list[i].c_str(), parameter_type_list[i].c_str()); - failure = true; + error_found = true; continue; } @@ -6707,51 +7014,53 @@ inline bool run_test18() { printf("run_test18() - Error in evaluation! (3) Expression: %s Check: x\n", expression_list[i].c_str()); - failure = true; + error_found = true; } if (y != y_inc) { printf("run_test18() - Error in evaluation! (3) Expression: %s Check: y\n", expression_list[i].c_str()); - failure = true; + error_found = true; } if (s0 != s0_inc) { printf("run_test18() - Error in evaluation! (3) Expression: %s Check: y\n", expression_list[i].c_str()); - failure = true; + error_found = true; } if (!std::equal(v0,v0 + sizeof_vec,v0_inc)) { printf("run_test18() - Error in evaluation! (3) Expression: %s Check: v0\n", expression_list[i].c_str()); - failure = true; + error_found = true; } if (!std::equal(v1,v1 + sizeof_vec,v1_inc)) { printf("run_test18() - Error in evaluation! (3) Expression: %s Check: v1\n", expression_list[i].c_str()); - failure = true; + error_found = true; } if (!std::equal(v2,v2 + sizeof_vec,v2_inc)) { printf("run_test18() - Error in evaluation! (3) Expression: %s Check: v2\n", expression_list[i].c_str()); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } { - bool failure = false; + bool error_found = false; rem_space_and_uppercase rsauc; @@ -6775,24 +7084,25 @@ inline bool run_test18() symbol_table.add_stringvar("s3", s3); symbol_table.add_stringvar("s4", s4); - symbol_table.add_function("remspc_uc",rsauc); - - std::string program = " s0 := 'How now '; " - " s1 := 'brown cow?'; " - " s2 := remspc_uc(s0 + s1); " - " s3 := remspc_uc(s0) + s1; " - " s4 := s0 + remspc_uc(s1); " - " remspc_uc(s0 + s1) == remspc_uc(s0) + remspc_uc(s1);"; - - std::string parameter_type_list[] = - { - "VVVTTT|S", - "VVTTTV|S", - "VTTTVV|S", - "TTTVVV|S", - "TTVVVT|S", - "TVVVTT|S" - }; + symbol_table.add_function("remspc_uc", rsauc); + + const std::string program = + " s0 := 'How now '; " + " s1 := 'brown cow?'; " + " s2 := remspc_uc(s0 + s1); " + " s3 := remspc_uc(s0) + s1; " + " s4 := s0 + remspc_uc(s1); " + " remspc_uc(s0 + s1) == remspc_uc(s0) + remspc_uc(s1); "; + + const std::string parameter_type_list[] = + { + "VVVTTT|S", + "VVTTTV|S", + "VTTTVV|S", + "TTTVVV|S", + "TTVVVT|S", + "TVVVTT|S" + }; std::size_t parameter_type_list_size = sizeof(parameter_type_list) / sizeof(std::string); @@ -6808,7 +7118,7 @@ inline bool run_test18() if (!parser.compile(program,expression)) { - printf("run_test18() - Error: %s\tExpression: %s\n", + printf("run_test18() - [5] Error: %s\tExpression: %s\n", parser.error().c_str(), program.c_str()); @@ -6821,58 +7131,60 @@ inline bool run_test18() { printf("run_test18() - Error in evaluation! (4) Expression: %s Result <> 1\n", program.c_str()); - failure = true; + error_found = true; } if (result != T(1)) { printf("run_test18() - Error in evaluation! (4) Expression: %s Check: s0\n", program.c_str()); - failure = true; + error_found = true; } if ("How now " != s0) { printf("run_test18() - Error in evaluation! (4) Expression: %s Check: s0\n", program.c_str()); - failure = true; + error_found = true; } if ("brown cow?" != s1) { printf("run_test18() - Error in evaluation! (4) Expression: %s Check: s1\n", program.c_str()); - failure = true; + error_found = true; } if ("HOWNOWBROWNCOW?" != s2) { printf("run_test18() - Error in evaluation! (4) Expression: %s Check: s2\n", program.c_str()); - failure = true; + error_found = true; } if ("HOWNOWbrown cow?" != s3) { printf("run_test18() - Error in evaluation! (4) Expression: %s Check: s3\n", program.c_str()); - failure = true; + error_found = true; } if ("How now BROWNCOW?" != s4) { printf("run_test18() - Error in evaluation! (4) Expression: %s Check: s4\n", program.c_str()); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } { - bool failure = false; + bool error_found = false; typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; @@ -6892,30 +7204,30 @@ inline bool run_test18() parser_t parser; - std::string programs[] = - { - "equal(0,vararg_func())", - "equal(1,vararg_func() + 1)", - "equal(1,1 + vararg_func())", - "equal(1,vararg_func + 1)", - "equal(1,1 + vararg_func)", - "equal(0,vararg_func() + vararg_func)", - "equal(0,vararg_func + vararg_func())", - "equal(1,vararg_func + vararg_func(1))", - "equal(1,vararg_func + vararg_func(1,2))", - "equal(2,vararg_func + vararg_func(v))", - "equal(1,vararg_func() + vararg_func(1))", - "equal(1,vararg_func() + vararg_func(1,2))", - "equal(2,vararg_func() + vararg_func(v))", - "equal(2,vararg_func(v))", - "equal(1,vararg_func(1))", - "equal(1,vararg_func(1,2,3))", - "equal(1,vararg_func(5,6,7,8))", - "equal(5,vararg_func(v) + 3)", - "equal(5,vararg_func(1) + 4)", - "equal(6,vararg_func(1,2,3) + 5)", - "equal(7,vararg_func(5,6,7,8) + 6)" - }; + const std::string programs[] = + { + "equal(0,vararg_func())", + "equal(1,vararg_func() + 1)", + "equal(1,1 + vararg_func())", + "equal(1,vararg_func + 1)", + "equal(1,1 + vararg_func)", + "equal(0,vararg_func() + vararg_func)", + "equal(0,vararg_func + vararg_func())", + "equal(1,vararg_func + vararg_func(1))", + "equal(1,vararg_func + vararg_func(1,2))", + "equal(2,vararg_func + vararg_func(v))", + "equal(1,vararg_func() + vararg_func(1))", + "equal(1,vararg_func() + vararg_func(1,2))", + "equal(2,vararg_func() + vararg_func(v))", + "equal(2,vararg_func(v))", + "equal(1,vararg_func(1))", + "equal(1,vararg_func(1,2,3))", + "equal(1,vararg_func(5,6,7,8))", + "equal(5,vararg_func(v) + 3)", + "equal(5,vararg_func(1) + 4)", + "equal(6,vararg_func(1,2,3) + 5)", + "equal(7,vararg_func(5,6,7,8) + 6)" + }; static const std::size_t programs_size = sizeof(programs) / sizeof(std::string); @@ -6923,27 +7235,29 @@ inline bool run_test18() { if (!parser.compile(programs[i],expression)) { - printf("run_test18() - Error: %s\tExpression: %s\n", + printf("run_test18() - [6] Error: %s\tExpression: %s\n", parser.error().c_str(), programs[i].c_str()); - failure = true; + error_found = true; } else if (T(1) != expression.value()) { printf("run_test18() - Error in evaluation! (5) Expression: %s\n", programs[i].c_str()); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } { - bool failure = false; + bool error_found = false; typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; @@ -6977,11 +7291,11 @@ inline bool run_test18() if (!parser.compile(expr_string,expression)) { - printf("run_test18() - Error: %s\tExpression: %s\n", + printf("run_test18() - [7] Error: %s\tExpression: %s\n", parser.error().c_str(), expr_string.c_str()); - failure = true; + error_found = true; } T sum = { T(0) }; @@ -6992,7 +7306,8 @@ inline bool run_test18() { printf("run_test18() - Error in evaluation! (6) Expression: %s\n", expr_string.c_str()); - failure = true; + + error_found = true; } v.rebase(v1.data()); @@ -7002,7 +7317,7 @@ inline bool run_test18() { printf("run_test18() - Error in evaluation! (7) Expression: %s\n", expr_string.c_str()); - failure = true; + error_found = true; } v.rebase(v2.data()); @@ -7012,7 +7327,7 @@ inline bool run_test18() { printf("run_test18() - Error in evaluation! (8) Expression: %s\n", expr_string.c_str()); - failure = true; + error_found = true; } v.rebase(v3.data()); @@ -7022,15 +7337,17 @@ inline bool run_test18() { printf("run_test18() - Error in evaluation! (9) Expression: %s\n", expr_string.c_str()); - failure = true; + error_found = true; } - if (failure) + if (error_found) + { return false; + } } { - bool failure = false; + bool error_found = false; typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; @@ -7063,11 +7380,11 @@ inline bool run_test18() if (!parser.compile(expr_string,expression)) { - printf("run_test18() - Error: %s\tExpression: %s\n", + printf("run_test18() - [8] Error: %s\tExpression: %s\n", parser.error().c_str(), expr_string.c_str()); - failure = true; + error_found = true; } for (std::size_t i = 0; i < v0.size() - 4; ++i) @@ -7083,17 +7400,19 @@ inline bool run_test18() s[i], sum); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } { - bool failure = false; + bool error_found = false; typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; @@ -7126,11 +7445,11 @@ inline bool run_test18() if (!parser.compile(expr_string,expression)) { - printf("run_test18() - Error: %s\tExpression: %s\n", + printf("run_test18() - [9] Error: %s\tExpression: %s\n", parser.error().c_str(), expr_string.c_str()); - failure = true; + error_found = true; } for (std::size_t i = 0; i < v0.size() - 4; ++i) @@ -7146,17 +7465,206 @@ inline bool run_test18() s[i], sum); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } + } + + { + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + const std::string const_folded_expression_list[] = + { + "(0 * dot(2 * v0,v1 - 1))", + "(0 * dot(2 * v0,v1 - 1)) + (dot(2 * v0,v1 - 1) * 0)", + "(0 * dot(v0 - v1,v1 / v0))", + "(0 * dot(v0 - v1,v1 / v0)) + (dot(v0 - v1,v1 / v0) * 0)", + "(0 * dot(v0,v1))", + "(0 * dot(v0,v1)) + (dot(v0,v1) * 0)", + "(0 / dot(2 * v0,v1 - 1))", + "(0 / dot(2 * v0,v1 - 1)) + (dot(2 * v0,v1 - 1) * 0)", + "(0 / dot(v0 - v1,v1 / v0))", + "(0 / dot(v0 - v1,v1 / v0)) + (dot(v0 - v1,v1 / v0) * 0)", + "(0 / dot(v0,v1))", + "(0 / dot(v0,v1)) + (dot(v0,v1) * 0)", + "(dot(2 * v0,v1 - 1) * 0)", + "(dot(2 * v0,v1 - 1) * 0) + (0 * dot(2 * v0,v1 - 1))", + "(dot(2 * v0,v1 - 1) * 0) + (0 / dot(2 * v0,v1 - 1))", + "(dot(v0 - v1,v1 / v0) * 0)", + "(dot(v0 - v1,v1 / v0) * 0) + (0 * dot(v0 - v1,v1 / v0))", + "(dot(v0 - v1,v1 / v0) * 0) + (0 / dot(v0 - v1,v1 / v0))", + "(dot(v0,v1) * 0)", + "(dot(v0,v1) * 0) + (0 * dot(v0,v1))", + "(dot(v0,v1) * 0) + (0 / dot(v0,v1))" + }; + + const std::size_t const_folded_expression_list_size = sizeof(const_folded_expression_list) / sizeof(std::string); + + const std::size_t vector_size = 5; + T v0[vector_size] = { 0, 2, 4, 6, 8 }; + T v1[vector_size] = { 1, 3, 5, 7, 9 }; + + exprtk::vector_view vv0 = exprtk::make_vector_view(v0, vector_size); + exprtk::vector_view vv1 = exprtk::make_vector_view(v1, vector_size); + + exprtk::rtl::vecops::package vector_package; + exprtk::rtl::io::package io_package; + + symbol_table_t symbol_table; + + symbol_table.add_package( vector_package ); + symbol_table.add_package( io_package ); + symbol_table.add_vector ( "v0" , vv0 ); + symbol_table.add_vector ( "v1" , vv1 ); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + for (std::size_t i = 0; i < const_folded_expression_list_size; ++i) + { + const std::string& expression_string = const_folded_expression_list[i]; + + if (!parser.compile(expression_string, expression)) + { + printf("run_test18() - [10] Error: %s Expression: %s\n", + parser.error().c_str(), + expression_string.c_str()); + + return false; + } + + if (!exprtk::expression_helper::is_literal(expression)) + { + printf("run_test18() - Error: Expression did not compile to a constant! [1] Expression: %s\n", + expression_string.c_str()); + + return false; + } + + for (std::size_t j = 0; j < 100; ++j) + { + if ((j % 2) == 0) + { + vv0.rebase(v0); + vv1.rebase(v1); + } + else + { + vv0.rebase(v1); + vv1.rebase(v0); + } + + const T result = expression.value(); + + if (result != T(0)) + { + printf("run_test18() - Error: Expected result of zero, result: %8.4f for Expression: %s\n", + result, + expression_string.c_str()); + + return false; + } + } + + expression.release(); + } + } + + { + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + const std::string rebase_expression_list[] = + { + "dot(v0,v1)", + "dot(2 * v0,v1 - 1) + dot(2 * v0,v1 - 1)", + "dot(2 * v0,v1 - 1)", + "dot(v0 - v1,v1 / v0) + dot(v0 - v1,v1 / v0)", + "dot(v0 - v1,v1 / v0)", + "dot(v0,v1) + dot(v0,v1)", + "dot(v0,v1) + x", + "dot(2 * v0,v1 - 1) * x + dot(2 * v0,v1 - 1) * y", + "x / dot(2 * v0,v1 - 1)", + "x / dot(v0 - v1,v1 / v0) + dot(v0 - v1,v1 / v0) / y", + "x * dot(v0 - v1,v1 / v0) / y", + "x - dot(v0,v1) + dot(v0,v1) + y", + }; + + const std::size_t rebase_expression_list_size = sizeof(rebase_expression_list) / sizeof(std::string); + + T x = T(1.234); + T y = T(5.678); + + const std::size_t vector_size = 5; + T v0[vector_size] = { 0, 2, 4, 6, 8 }; + T v1[vector_size] = { 1, 3, 5, 7, 9 }; + + exprtk::vector_view vv0 = exprtk::make_vector_view(v0, vector_size); + exprtk::vector_view vv1 = exprtk::make_vector_view(v1, vector_size); + + exprtk::rtl::vecops::package vector_package; + exprtk::rtl::io::package io_package; + + symbol_table_t symbol_table; + + symbol_table.add_package ( vector_package ); + symbol_table.add_package ( io_package ); + symbol_table.add_variable( "x" , x ); + symbol_table.add_variable( "y" , y ); + symbol_table.add_vector ( "v0" , vv0 ); + symbol_table.add_vector ( "v1" , vv1 ); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + for (std::size_t i = 0; i < rebase_expression_list_size; ++i) + { + const std::string& expression_string = rebase_expression_list[i]; + + if (!parser.compile(expression_string, expression)) + { + printf("run_test18() - [11] Error: %s Expression: %s\n", + parser.error().c_str(), + expression_string.c_str()); + + return false; + } + + for (std::size_t j = 0; j < 100; ++j) + { + if ((j % 2) == 0) + { + vv0.rebase(v0); + vv1.rebase(v1); + } + else + { + vv0.rebase(v1); + vv1.rebase(v0); + } + + expression.value(); + } + + expression.release(); + } } { - bool failure = false; + bool error_found = false; typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; @@ -7189,11 +7697,11 @@ inline bool run_test18() if (!parser.compile(expr_string,expression)) { - printf("run_test18() - Error: %s\tExpression: %s\n", + printf("run_test18() - [12] Error: %s\tExpression: %s\n", parser.error().c_str(), expr_string.c_str()); - failure = true; + error_found = true; } for (std::size_t i = 0; i < v0.size() - 4; ++i) @@ -7209,13 +7717,15 @@ inline bool run_test18() s[i], sum); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } { @@ -7246,7 +7756,7 @@ inline bool run_test18() if (!parser.compile(expr_string,expression)) { - printf("run_test18() - Error: %s\tExpression: %s\n", + printf("run_test18() - [13] Error: %s\tExpression: %s\n", parser.error().c_str(), expr_string.c_str()); @@ -7281,7 +7791,7 @@ inline bool run_test18() } { - bool failure = false; + bool error_found = false; typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; @@ -7292,101 +7802,184 @@ inline bool run_test18() symbol_table_t symbol_table; symbol_table.add_package(vecops_pkg); - std::string expr_str_list[] = - { - "var v[9] := {1,2,3,4,5,6,7,8,9}; all_true(v) == true" , - "var v[6] := {-1,-2,-3,-4,-5,-6}; all_true(v) == true" , - "var v[8] := {1,2,3,0,0,0,0,0}; all_true(v) == false", - "var v[8] := {-1,-2,-3,0,0,0,0,0}; all_true(v) == false", - "var v[9] := {0,0,0,0,0,0,0,0,0}; all_true(v + 1) == true", - - "var v[9] := {0,0,0,0,0,0,0,0,0}; all_false(v) == true" , - "var v[9] := {0,0,0,0,0,1,2,3,4}; all_false(v) == false" , - "var v[8] := {0,0,0,0,0,-1,-2,-3}; all_false(v) == false" , - "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v - 1) == true", - - "var v[9] := {0,0,0,0,0,0,0,0,1}; any_true(v) == true" , - "var v[9] := {0,0,0,0,1,0,0,0,0}; any_true(v) == true" , - "var v[9] := {0,0,0,0,0,0,0,0,0}; any_true(v) == false" , - "var v[9] := {0,0,0,0,0,0,0,0,0}; any_true(v + 1) == true", - - "var v[9] := {1,1,1,1,1,1,1,1,0}; any_false(v) == true" , - "var v[9] := {1,1,1,1,0,1,1,1,1}; any_false(v) == true" , - "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v) == false" , - "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v - 1) == true", - - "var v[9] := {0,0,0,0,0,0,0,0,0}; count(v) == 0" , - "var v[9] := {0,0,0,0,0,0,0,0,1}; count(v) == 1" , - "var v[9] := {0,0,0,0,0,0,0,2,1}; count(v) == 2" , - "var v[9] := {0,0,0,0,0,0,3,2,1}; count(v) == 3" , - "var v[9] := {0,0,0,0,0,0,0,0,0}; count(v + 1) == v[]", - "var v[9] := {1,1,1,1,1,1,1,1,1}; count(v - 1) == 0", - - "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,r); sum(v == r) == v[]", - "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,0,8,r,0,8); sum(r) == 45", - "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,1,7,r,1,7); sum(r) == 35", - "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[5] := [0]; copy(v,0,4,r,0,4); sum(r) == 15", - - "var v[5] := {1,2,3,4,5}; var r[5] := {4,5,1,2,3}; rol(v,3); sum(v == r) == v[]", - "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,1,2}; ror(v,3); sum(v == r) == v[]", - - "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,1,2}; rol(v,2); sum(v == r) == v[]", - "var v[5] := {1,2,3,4,5}; var r[5] := {4,5,1,2,3}; ror(v,2); sum(v == r) == v[]", - - "var v[5] := {1,2,3,4,5}; var r[5] := {1,3,4,2,5}; rol(v,1,1,3); sum(v == r) == v[]", - "var v[5] := {1,2,3,4,5}; var r[5] := {1,4,2,3,5}; ror(v,1,1,3); sum(v == r) == v[]", - - "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,0,0}; shftl(v,2); sum(v == r) == v[]", - "var v[5] := {1,2,3,4,5}; var r[5] := {5,0,0,0,0}; shftl(v,4); sum(v == r) == v[]", - "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,0}; shftl(v,5); sum(v == r) == v[]", - - "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,1,2,3}; shftr(v,2); sum(v == r) == v[]", - "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,1}; shftr(v,4); sum(v == r) == v[]", - "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,0}; shftr(v,5); sum(v == r) == v[]", - - "var v[5] := {1,2,3,4,5}; var r[5] := {1,3,4,0,5}; shftl(v,1,1,3); sum(v == r) == v[]", - "var v[5] := {1,2,3,4,5}; var r[5] := {1,0,2,3,5}; shftr(v,1,1,3); sum(v == r) == v[]", - - "var v[5] := {1,3,5,2,4}; var r[5] := {1,2,3,4,5}; sort(v); sum(v == r) == v[]", - "var v[5] := {5,4,3,2,1}; var r[5] := {1,2,3,4,5}; sort(v); sum(v == r) == v[]", - "var v[5] := {1,4,2,3,5}; var r[5] := {1,2,3,4,5}; sort(v,1,3); sum(v == r) == v[]", - "var v[5] := {5,4,2,3,1}; var r[5] := {5,2,3,4,1}; sort(v,1,3); sum(v == r) == v[]", - "var v[5] := {3,1,2,4,5}; var r[5] := {1,2,3,4,5}; sort(v,0,2); sum(v == r) == v[]", - "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,3,4,5}; sort(v,2,4); sum(v == r) == v[]", - - "var v[5] := {1,3,5,2,4}; var r[5] := {1,2,3,4,5}; sort(v,'ascending'); sum(v == r) == v[]", - "var v[5] := {1,3,5,2,4}; var r[5] := {1,2,3,4,5}; sort(v,'aScEnDiNg'); sum(v == r) == v[]", - "var v[5] := {5,4,3,2,1}; var r[5] := {1,2,3,4,5}; sort(v,'ascending'); sum(v == r) == v[]", - "var v[5] := {1,4,2,3,5}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',1,3); sum(v == r) == v[]", - "var v[5] := {3,1,2,4,5}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',0,2); sum(v == r) == v[]", - "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',2,4); sum(v == r) == v[]", - - "var v[5] := {1,3,5,2,4}; var r[5] := {5,4,3,2,1}; sort(v,'descending'); sum(v == r) == v[]", - "var v[5] := {1,3,5,2,4}; var r[5] := {5,4,3,2,1}; sort(v,'DeScEnDiNg'); sum(v == r) == v[]", - "var v[5] := {5,4,3,2,1}; var r[5] := {5,4,3,2,1}; sort(v,'descending'); sum(v == r) == v[]", - "var v[5] := {1,4,2,3,5}; var r[5] := {1,4,3,2,5}; sort(v,'descending',1,3); sum(v == r) == v[]", - "var v[5] := {3,1,2,4,5}; var r[5] := {3,2,1,4,5}; sort(v,'descending',0,2); sum(v == r) == v[]", - "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,5,4,3}; sort(v,'descending',2,4); sum(v == r) == v[]", - - "var v[9] := {7,8,9,1,2,3,4,5,6}; nth_element(v,trunc(v[] / 2)); v[v[] / 2] == 5", - "var v[9] := {7,8,9,1,2,3,4,5,6}; nth_element(v,trunc(v[] / 3)); v[v[] / 3] == 4", - - "var v[9] := {7,8,9,1,2,3,4,5,6}; nth_element(v,trunc(v[] / 2)); sort(v,0,trunc(v[] / 2)); (v[v[] / 2] == 5) and (v[0] == 1)", - "var v[9] := {7,8,9,1,2,3,4,5,6}; nth_element(v,trunc(v[] / 3)); sort(v,0,trunc(v[] / 3)); (v[v[] / 3] == 4) and (v[0] == 1)", - - "var v[5]; iota(v,2); var r[5] := {0,2,4,6,8}; sum(v == r) == v[]", - "var v[5]; iota(v,2,1); var r[5] := {1,3,5,7,9}; sum(v == r) == v[]", - "var v[5]; iota(v,1,1,3); var r[5] := {0,0,1,2,0}; sum(v == r) == v[]", - "var v[5]; iota(v,2,2,1,3);var r[5] := {0,2,4,6,0}; sum(v == r) == v[]", - "var v[5]; iota(v,2,1,1,3);var r[5] := {0,1,3,5,0}; sum(v == r) == v[]", - - " var a := 2; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var r[3] := [0]; r := a * x + y; axpy(a,x,y); sum(y == r) == y[]", - " var a := 2; var b := 3; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var r[3] := [0]; r := a * x + b * y; axpby(a,x,b,y); sum(y == r) == y[]", - - " var a := 2; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var z[3] := [0]; var r[3] := [0]; r := a * x + y; axpyz(a,x,y,z); sum(z == r) == z[]", - " var a := 2; var b := 3; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var z[3] := [0]; var r[3] := [0]; r := a * x + b * y; axpbyz(a,x,b,y,z); sum(z == r) == z[]", - " var a := 2; var b := 3; var x[3] := {1,2,3}; var z[3] := [0]; var r[3] := [0]; r := a * x + b; axpbz(a,x,b,z); sum(z == r) == z[]", - }; + const std::string expr_str_list[] = + { + "var v[9] := {1,2,3,4,5,6,7,8,9}; all_true(v) == true" , + "var v[6] := {-1,-2,-3,-4,-5,-6}; all_true(v) == true" , + "var v[8] := {1,2,3,0,0,0,0,0}; all_true(v) == false", + "var v[8] := {-1,-2,-3,0,0,0,0,0}; all_true(v) == false", + "var v[9] := {0,0,0,0,0,0,0,0,0}; all_true(v + 1) == true", + + "var v[9] := {0,0,0,0,0,0,0,0,0}; all_false(v) == true" , + "var v[9] := {0,0,0,0,0,1,2,3,4}; all_false(v) == false" , + "var v[8] := {0,0,0,0,0,-1,-2,-3}; all_false(v) == false" , + "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v - 1) == true", + + "var v[9] := {0,0,0,0,0,0,0,0,1}; any_true(v) == true" , + "var v[9] := {0,0,0,0,1,0,0,0,0}; any_true(v) == true" , + "var v[9] := {0,0,0,0,0,0,0,0,0}; any_true(v) == false" , + "var v[9] := {0,0,0,0,0,0,0,0,0}; any_true(v + 1) == true", + + "var v[9] := {1,1,1,1,1,1,1,1,0}; any_false(v) == true" , + "var v[9] := {1,1,1,1,0,1,1,1,1}; any_false(v) == true" , + "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v) == false" , + "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v - 1) == true", + + "var v[9] := {0,0,0,0,0,0,0,0,0}; count(v) == 0" , + "var v[9] := {0,0,0,0,0,0,0,0,1}; count(v) == 1" , + "var v[9] := {0,0,0,0,0,0,0,2,1}; count(v) == 2" , + "var v[9] := {0,0,0,0,0,0,3,2,1}; count(v) == 3" , + "var v[9] := {0,0,0,0,0,0,0,0,0}; count(v + 1) == v[]", + "var v[9] := {1,1,1,1,1,1,1,1,1}; count(v - 1) == 0", + + "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,r); sum(v == r) == v[]", + "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,0,8,r,0,8); sum(r) == 45", + "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,1,7,r,1,7); sum(r) == 35", + "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[5] := [0]; copy(v,0,4,r,0,4); sum(r) == 15", + + "var v[5] := {1,2,3,4,5}; var r[5] := {4,5,1,2,3}; rol(v,3); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,1,2}; ror(v,3); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,1,2}; rol(v,2); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {4,5,1,2,3}; ror(v,2); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {1,3,4,2,5}; rol(v,1,1,3); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {1,4,2,3,5}; ror(v,1,1,3); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,0,0}; shftl(v,2); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {5,0,0,0,0}; shftl(v,4); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,0}; shftl(v,5); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,1,2,3}; shftr(v,2); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,1}; shftr(v,4); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,0}; shftr(v,5); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {1,3,4,0,5}; shftl(v,1,1,3); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {1,0,2,3,5}; shftr(v,1,1,3); sum(v == r) == v[]", + + "var v[5] := {1,3,5,2,4}; var r[5] := {1,2,3,4,5}; sort(v); sum(v == r) == v[]", + "var v[5] := {5,4,3,2,1}; var r[5] := {1,2,3,4,5}; sort(v); sum(v == r) == v[]", + "var v[5] := {1,4,2,3,5}; var r[5] := {1,2,3,4,5}; sort(v,1,3); sum(v == r) == v[]", + "var v[5] := {5,4,2,3,1}; var r[5] := {5,2,3,4,1}; sort(v,1,3); sum(v == r) == v[]", + "var v[5] := {3,1,2,4,5}; var r[5] := {1,2,3,4,5}; sort(v,0,2); sum(v == r) == v[]", + "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,3,4,5}; sort(v,2,4); sum(v == r) == v[]", + + "var v[5] := {1,3,5,2,4}; var r[5] := {1,2,3,4,5}; sort(v,'ascending'); sum(v == r) == v[]", + "var v[5] := {1,3,5,2,4}; var r[5] := {1,2,3,4,5}; sort(v,'aScEnDiNg'); sum(v == r) == v[]", + "var v[5] := {5,4,3,2,1}; var r[5] := {1,2,3,4,5}; sort(v,'ascending'); sum(v == r) == v[]", + "var v[5] := {1,4,2,3,5}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',1,3); sum(v == r) == v[]", + "var v[5] := {3,1,2,4,5}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',0,2); sum(v == r) == v[]", + "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',2,4); sum(v == r) == v[]", + + "var v[5] := {1,3,5,2,4}; var r[5] := {5,4,3,2,1}; sort(v,'descending'); sum(v == r) == v[]", + "var v[5] := {1,3,5,2,4}; var r[5] := {5,4,3,2,1}; sort(v,'DeScEnDiNg'); sum(v == r) == v[]", + "var v[5] := {5,4,3,2,1}; var r[5] := {5,4,3,2,1}; sort(v,'descending'); sum(v == r) == v[]", + "var v[5] := {1,4,2,3,5}; var r[5] := {1,4,3,2,5}; sort(v,'descending',1,3); sum(v == r) == v[]", + "var v[5] := {3,1,2,4,5}; var r[5] := {3,2,1,4,5}; sort(v,'descending',0,2); sum(v == r) == v[]", + "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,5,4,3}; sort(v,'descending',2,4); sum(v == r) == v[]", + + "var v[9] := {7,8,9,1,2,3,4,5,6}; nth_element(v,trunc(v[] / 2)); v[v[] / 2] == 5", + "var v[9] := {7,8,9,1,2,3,4,5,6}; nth_element(v,trunc(v[] / 3)); v[v[] / 3] == 4", + + "var v[9] := {7,8,9,1,2,3,4,5,6}; nth_element(v,trunc(v[] / 2)); sort(v,0,trunc(v[] / 2)); (v[v[] / 2] == 5) and (v[0] == 1)", + "var v[9] := {7,8,9,1,2,3,4,5,6}; nth_element(v,trunc(v[] / 3)); sort(v,0,trunc(v[] / 3)); (v[v[] / 3] == 4) and (v[0] == 1)", + + "var v[5]; iota(v, 0,1); var r[5] := { 0, 1, 2, 3, 4}; sum(v == r) == v[]", + "var v[5]; iota(v, 0,2); var r[5] := { 0, 2, 4, 6, 8}; sum(v == r) == v[]", + "var v[5]; iota(v, 1,1); var r[5] := { 1, 2, 3, 4, 5}; sum(v == r) == v[]", + "var v[5]; iota(v, 1,2); var r[5] := { 1, 3, 5, 7, 9}; sum(v == r) == v[]", + "var v[5]; iota(v,-1,1); var r[5] := {-1, 0, 1, 2, 3}; sum(v == r) == v[]", + "var v[5]; iota(v,-1,2); var r[5] := {-1, 1, 3, 5, 7}; sum(v == r) == v[]", + "var v[5]; iota(v,-2,1); var r[5] := {-2,-1, 0, 1, 2}; sum(v == r) == v[]", + "var v[5]; iota(v,-2,2); var r[5] := {-2, 0, 2, 4, 6}; sum(v == r) == v[]", + "var v[5]; iota(v, 0); var r[5] := { 0, 1, 2, 3, 4}; sum(v == r) == v[]", + "var v[5]; iota(v, 1); var r[5] := { 1, 2, 3, 4, 5}; sum(v == r) == v[]", + "var v[5]; iota(v,-1); var r[5] := {-1, 0, 1, 2, 3}; sum(v == r) == v[]", + "var v[5]; iota(v,-2); var r[5] := {-2,-1, 0, 1, 2}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, 0); var r[5] := { 0, 0, 0, 0, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 1, 0); var r[5] := { 1, 1, 1, 1, 1}; sum(v == r) == v[]", + + "var v[5]; iota(v, 0, v[] - 1, 0,1); var r[5] := { 0, 1, 2, 3, 4}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1, 0,2); var r[5] := { 0, 2, 4, 6, 8}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1, 1,1); var r[5] := { 1, 2, 3, 4, 5}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1, 1,2); var r[5] := { 1, 3, 5, 7, 9}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1,-1,1); var r[5] := {-1, 0, 1, 2, 3}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1,-1,2); var r[5] := {-1, 1, 3, 5, 7}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1,-2,1); var r[5] := {-2,-1, 0, 1, 2}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1,-2,2); var r[5] := {-2, 0, 2, 4, 6}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1, 0 ); var r[5] := { 0, 1, 2, 3, 4}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1, 1 ); var r[5] := { 1, 2, 3, 4, 5}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1,-1 ); var r[5] := {-1, 0, 1, 2, 3}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1,-2 ); var r[5] := {-2,-1, 0, 1, 2}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1, 0,0); var r[5] := { 0, 0, 0, 0, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 1, 1,0); var r[5] := { 1, 1, 1, 1, 1}; sum(v == r) == v[]", + + "var v[5]; iota(v, 1, v[] - 1, 0,1); var r[5] := { 0, 0, 1, 2, 3 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1, 0,2); var r[5] := { 0, 0, 2, 4, 6 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1, 1,1); var r[5] := { 0, 1, 2, 3, 4 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1, 1,2); var r[5] := { 0, 1, 3, 5, 7 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1,-1,1); var r[5] := { 0, -1, 0, 1, 2 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1,-1,2); var r[5] := { 0, -1, 1, 3, 5 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1,-2,1); var r[5] := { 0, -2,-1, 0, 1 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1,-2,2); var r[5] := { 0, -2, 0, 2, 4 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1, 0 ); var r[5] := { 0, 0, 1, 2, 3 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1, 1 ); var r[5] := { 0, 1, 2, 3, 4 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1,-1 ); var r[5] := { 0, -1, 0, 1, 2 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 1,-2 ); var r[5] := { 0, -2,-1, 0, 1 }; sum(v == r) == v[]", + + "var v[5]; iota(v, 1, v[] - 2, 0,1); var r[5] := { 0, 0, 1, 2, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2, 0,2); var r[5] := { 0, 0, 2, 4, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2, 1,1); var r[5] := { 0, 1, 2, 3, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2, 1,2); var r[5] := { 0, 1, 3, 5, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2,-1,1); var r[5] := { 0, -1, 0, 1, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2,-1,2); var r[5] := { 0, -1, 1, 3, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2,-2,1); var r[5] := { 0, -2,-1, 0, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2,-2,2); var r[5] := { 0, -2, 0, 2, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2, 0 ); var r[5] := { 0, 0, 1, 2, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2, 1 ); var r[5] := { 0, 1, 2, 3, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2,-1 ); var r[5] := { 0, -1, 0, 1, 0 }; sum(v == r) == v[]", + "var v[5]; iota(v, 1, v[] - 2,-2 ); var r[5] := { 0, -2,-1, 0, 0 }; sum(v == r) == v[]", + + "var v[5]; iota(v, 0, v[] - 2, 0,1); var r[5] := { 0, 1, 2, 3, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2, 0,2); var r[5] := { 0, 2, 4, 6, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2, 1,1); var r[5] := { 1, 2, 3, 4, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2, 1,2); var r[5] := { 1, 3, 5, 7, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2,-1,1); var r[5] := {-1, 0, 1, 2, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2,-1,2); var r[5] := {-1, 1, 3, 5, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2,-2,1); var r[5] := {-2,-1, 0, 1, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2,-2,2); var r[5] := {-2, 0, 2, 4, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2, 0 ); var r[5] := { 0, 1, 2, 3, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2, 1 ); var r[5] := { 1, 2, 3, 4, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2,-1 ); var r[5] := {-1, 0, 1, 2, 0}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] - 2,-2 ); var r[5] := {-2,-1, 0, 1, 0}; sum(v == r) == v[]", + + "var v[5]; iota(v, 0, -1); var r[5] := { 0, -1, -2, -3, -4}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, -2); var r[5] := { 0, -2, -4, -6, -8}; sum(v == r) == v[]", + "var v[5]; iota(v, -1, -2); var r[5] := { -1, -3, -5, -7, -9}; sum(v == r) == v[]", + + "var v[5]; iota(v, 0, v[] -1, 0, -1); var r[5] := { 0, -1, -2, -3, -4}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] -1, 0, -2); var r[5] := { 0, -2, -4, -6, -8}; sum(v == r) == v[]", + "var v[5]; iota(v, 0, v[] -1, -1, -2); var r[5] := { -1, -3, -5, -7, -9}; sum(v == r) == v[]", + + "var v[5]; iota(v, 0,1); threshold_below(v,2, 0); var r[5] := { 0, 0, 2, 3, 4}; sum(v == r) == v[]", + "var v[5]; iota(v, 0,1); threshold_above(v,2, 0); var r[5] := { 0, 1, 2, 0, 0}; sum(v == r) == v[]", + + "var v[5]; iota(v, 0,1); threshold_below(v,0,v[] - 1,2, 0); var r[5] := { 0, 0, 2, 3, 4}; sum(v == r) == v[]", + "var v[5]; iota(v, 0,1); threshold_above(v,0,v[] - 1,2, 0); var r[5] := { 0, 1, 2, 0, 0}; sum(v == r) == v[]", + + "var v[5]; iota(v, 1,1); threshold_below(v,1,v[] - 1,2, 0); var r[5] := { 1, 2, 3, 4, 5}; sum(v == r) == v[]", + "var v[5]; iota(v, 1,1); threshold_above(v,1,v[] - 1,2, 0); var r[5] := { 1, 2, 0, 0, 0}; sum(v == r) == v[]", + + "var v[5]; iota(v, 0,1); threshold_below(v,0,v[] - 2,2, 0); var r[5] := { 0, 0, 2, 3, 4}; sum(v == r) == v[]", + "var v[5]; iota(v, 0,1); threshold_above(v,0,v[] - 2,2, 0); var r[5] := { 0, 1, 2, 0, 4}; sum(v == r) == v[]", + + " var a := 2; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var r[3] := [0]; r := a * x + y; axpy(a,x,y); sum(y == r) == y[]", + " var a := 2; var b := 3; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var r[3] := [0]; r := a * x + b * y; axpby(a,x,b,y); sum(y == r) == y[]", + + " var a := 2; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var z[3] := [0]; var r[3] := [0]; r := a * x + y; axpyz(a,x,y,z); sum(z == r) == z[]", + " var a := 2; var b := 3; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var z[3] := [0]; var r[3] := [0]; r := a * x + b * y; axpbyz(a,x,b,y,z); sum(z == r) == z[]", + " var a := 2; var b := 3; var x[3] := {1,2,3}; var z[3] := [0]; var r[3] := [0]; r := a * x + b; axpbz(a,x,b,z); sum(z == r) == z[]", + }; const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); @@ -7399,11 +7992,11 @@ inline bool run_test18() if (!parser.compile(expr_str_list[i], expression)) { - printf("run_test18() - Error: %s Expression: %s\n", + printf("run_test18() - [14] Error: %s Expression: %s\n", parser.error().c_str(), expr_str_list[i].c_str()); - failure = true; + error_found = true; continue; } @@ -7415,12 +8008,14 @@ inline bool run_test18() printf("run_test18() - Error in evaluation! (11) Expression: %s\n", expr_str_list[i].c_str()); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } { @@ -7464,44 +8059,44 @@ inline bool run_test18() typedef std::pair::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")) - }; + { + 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); @@ -7516,7 +8111,7 @@ inline bool run_test18() if (!parser.compile(test_pack_list[i].first, expression)) { - printf("run_test18() - (12) Overload VarArg Error: %s Expression: %s\n", + printf("run_test18() - [15] Overload VarArg Error: %s Expression: %s\n", parser.error().c_str(), test_pack_list[i].first.c_str()); @@ -7526,7 +8121,7 @@ inline bool run_test18() expression_list.push_back(expression); } - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list.size(); ++i) { @@ -7537,7 +8132,7 @@ inline bool run_test18() printf("run_test18() - Error in evaluation! (12) Expression: %s\n", test_pack_list[i].first.c_str()); - failure = true; + error_found = true; } if (ovrld_func.current_ps_index != test_pack_list[i].second.ps_index) @@ -7547,7 +8142,7 @@ inline bool run_test18() static_cast(test_pack_list[i].second.ps_index), static_cast(ovrld_func.current_ps_index)); - failure = true; + error_found = true; } if (ovrld_func.current_param_seq != test_pack_list[i].second.param_seq) @@ -7557,13 +8152,15 @@ inline bool run_test18() test_pack_list[i].second.param_seq.c_str(), ovrld_func.current_param_seq.c_str()); - failure = true; + error_found = true; } ::fflush(stdout); } - if (failure) + if (error_found) + { return false; + } } { @@ -7581,13 +8178,13 @@ inline bool run_test18() T w = T(4.4); overload_func 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" - ); + ( + "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 symbol_table; @@ -7609,44 +8206,44 @@ inline bool run_test18() typedef std::pair::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")) - }; + { + 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); @@ -7661,7 +8258,7 @@ inline bool run_test18() if (!parser.compile(test_pack_list[i].first, expression)) { - printf("run_test18() - (13) Overload VarArg Error: %s Expression: %s\n", + printf("run_test18() - [16] Overload VarArg Error: %s Expression: %s\n", parser.error().c_str(), test_pack_list[i].first.c_str()); @@ -7671,7 +8268,7 @@ inline bool run_test18() expression_list.push_back(expression); } - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list.size(); ++i) { @@ -7684,7 +8281,7 @@ inline bool run_test18() printf("run_test18() - Error in evaluation! (13) Expression: %s\n", test_pack_list[i].first.c_str()); - failure = true; + error_found = true; } if (ovrld_func.current_ps_index != test_pack_list[i].second.ps_index) @@ -7694,7 +8291,7 @@ inline bool run_test18() static_cast(test_pack_list[i].second.ps_index), static_cast(ovrld_func.current_ps_index)); - failure = true; + error_found = true; } if (ovrld_func.current_param_seq != test_pack_list[i].second.param_seq) @@ -7704,21 +8301,214 @@ inline bool run_test18() test_pack_list[i].second.param_seq.c_str(), ovrld_func.current_param_seq.c_str()); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } - return true; -} + { + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; -template -inline bool run_test19() -{ - typedef exprtk::symbol_table symbol_table_t; + typedef std::pair rtc_test_t; + static const rtc_test_t rtc_tests[] = + { + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i + v[]]; } ", 5 ), + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i + 10]; } ", 5 ), + std::make_pair(" x:= 0; for (var i := 0; i < (2 * v[]); i += 1) { x += (v[i] == vv[i]); } ", 10), + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i + v[]] := i; } ", 5 ), + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i + v[]] <=> v[i]; } ", 5 ), + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i] <=> v[i + v[]]; } ", 10), + std::make_pair(" var z[5] := [1]; for (var i := 0; i < z[]; i += 1) { z[i + z[]]; } ", 5 ), + std::make_pair(" var z[5] := [1]; for (var i := 0; i < z[]; i += 1) { z[i + 10]; } ", 5 ), + std::make_pair(" var z[5] := [1]; for (var i := 0; i < z[]; i += 1) { z[i + z[]] := i; } ", 5 ), + std::make_pair(" var z[5] := [1]; for (var i := 0; i < z[]; i += 1) { z[i + z[]] <=> z[i]; } ", 5 ), + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i+v[]] := (v*w)[i + v[]]; } ", 10), + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i+v[]] := (v*w)[i+w[]]; } ", 10), + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i+v[]] := (v+w)[i + v[]]; } ", 10), + std::make_pair(" for (var i := 0; i < v[]; i += 1) { v[i+v[]] := (v+w)[i+w[]]; } ", 10), + std::make_pair(" var z[4] := [1]; for (var i := 0; i < v[]; i += 1) { v[i+v[]] := (v*z)[i+v[]]; } ", 10), + std::make_pair(" var z[4] := [1]; for (var i := 0; i < v[]; i += 1) { v[i+v[]] := (v*z)[i+w[]]; } ", 9 ), + std::make_pair(" var z[4] := [1]; for (var i := 0; i < v[]; i += 1) { v[i+v[]] := (v+z)[i+v[]]; } ", 10), + std::make_pair(" var z[4] := [1]; for (var i := 0; i < v[]; i += 1) { v[i+v[]] := (v+z)[i+z[]]; } ", 10), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; qq[i[0]] += xx ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[1] + xx) == (xx + qq[1])) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[0] += xx) == xx) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[0] += xx + yy) == (xx + yy)) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[0] -= xx) == -xx) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[0] -= (xx + yy)) == -(xx + yy)) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[1] + qq[2]) == (qq[3 - 1] + qq[2 * 1/2]))", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; (qq[qq[1]] == qq[1]) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; (qq[1] += qq[1]) == qq[1 + 1] ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[i[1]] + xx) == (xx + qq[i[1]])) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[i[0]] += xx) == xx) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[i[0]] += xx + yy) == (xx + yy)) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[i[0]] -= xx) == -xx) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[i[0]] -= (xx + yy)) == -(xx + yy))", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; ((qq[i[1]] + qq[2]) == (qq[i[3] - i[1]] + qq[i[2] * 1/2]))", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; (qq[qq[i[1]]] == qq[i[1]]) ", 0 ), + std::make_pair(" var xx := 1; var yy := 1; var qq[5] := {0,1,2,3,4}; var i[5] := {0,1,2,3,4}; (qq[i[1]] += qq[i[1]]) == qq[i[1] + 1] ", 0 ), + }; + + static const std::size_t rtc_tests_size = sizeof(rtc_tests) / sizeof(rtc_test_t); + + bool error_found = false; + + for (std::size_t i = 0; i < rtc_tests_size; ++i) + { + const std::string& expression_str = rtc_tests[i].first; + + { + T x = 6; + T v[5] = { 0, 1, 2, 3, 4 }; + T w[3] = { 0, 1, 2 }; + exprtk::vector_view vv = exprtk::make_vector_view(v, 5); + exprtk::vector_view ww = exprtk::make_vector_view(w, 3); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + symbol_table.add_variable("x" , x ); + symbol_table.add_vector ("v" , v ); + symbol_table.add_vector ("w" , w ); + symbol_table.add_vector ("vv", vv); + symbol_table.add_vector ("ww", ww); + + vector_access_rtc_counter vartc; + + expression.register_symbol_table(symbol_table); + + parser.register_vector_access_runtime_check(vartc); + + if (!parser.compile(expression_str, expression)) + { + printf("run_test18() - Error: %s\t [1] Expression: %s\n", + parser.error().c_str(), + expression_str.c_str()); + + error_found = true; + return false; + } + + vartc.rtc_count = 0; + expression.value(); + + if (vartc.rtc_count != rtc_tests[i].second) + { + printf("run_test18() - Expected rtc_count: %d got rtc_count: %d [0] Expression: %s\n", + static_cast(rtc_tests[i].second), + static_cast(vartc.rtc_count), + expression_str.c_str()); + error_found = true; + } + } + + { + T x = 6; + T v[5] = { 0, 1, 2, 3, 4 }; + T w[3] = { 0, 1, 2 }; + T v0[5] = { 0, 1, 2, 3, 4 }; + T v1[5] = { 0, 1, 2, 3, 4 }; + exprtk::vector_view vv = exprtk::make_vector_view(v, 5); + exprtk::vector_view ww = exprtk::make_vector_view(w, 3); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + symbol_table.add_variable("x" , x ); + symbol_table.add_vector ("v" , v ); + symbol_table.add_vector ("w" , w ); + symbol_table.add_vector ("vv", vv); + symbol_table.add_vector ("ww", ww); + + vector_access_rtc_counter vartc; + + expression.register_symbol_table(symbol_table); + + parser.register_vector_access_runtime_check(vartc); + + if (!parser.compile(expression_str, expression)) + { + printf("run_test18() - Error: %s\t [2] Expression: %s\n", + parser.error().c_str(), + expression_str.c_str()); + + error_found = true; + return false; + } + + vartc.rtc_count = 0; + vv.rebase(v0); + expression.value(); + + if (vartc.rtc_count != rtc_tests[i].second) + { + printf("run_test18() - Expected rtc_count: %d got rtc_count: %d [1] Expression: %s\n", + static_cast(rtc_tests[i].second), + static_cast(vartc.rtc_count), + expression_str.c_str()); + error_found = true; + } + + vartc.rtc_count = 0; + vv.rebase(v1); + expression.value(); + + if (vartc.rtc_count != rtc_tests[i].second) + { + printf("run_test18() - Expected rtc_count: %d got rtc_count: %d [2] Expression: %s\n", + static_cast(rtc_tests[i].second), + static_cast(vartc.rtc_count), + expression_str.c_str()); + error_found = true; + } + } + } + + if (error_found) + { + return false; + } + } + + return true; +} + +template +struct depth_to_str exprtk_test_final : public exprtk::igeneric_function +{ + typedef exprtk::igeneric_function igenfunct_t; + typedef typename igenfunct_t::generic_type generic_t; + typedef typename igenfunct_t::parameter_list_t parameter_list_t; + typedef typename generic_t::scalar_view scalar_t; + + depth_to_str() + : exprtk::igeneric_function("T",igenfunct_t::e_rtrn_string) + {} + + using igenfunct_t::operator(); + + inline T operator()(std::string& result, + parameter_list_t parameters) exprtk_test_override + { + + result = "depth" + exprtk::details::to_str(static_cast(scalar_t(parameters[0])())); + return T(0); + } +}; + +template +bool run_test19() +{ + typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; typedef exprtk::function_compositor compositor_t; @@ -7730,44 +8520,44 @@ inline bool run_test19() compositor_t compositor; // f(x) = x + 2 - compositor.add(function_t("f","x + 2","x")); + compositor.add(function_t("f", "x + 2", "x")); // g(x) = x^2-3 - compositor.add(function_t("g","x^2 - 3","x")); + compositor.add(function_t("g", "x^2 - 3", "x")); // fof(x) = f(f(x)) - compositor.add(function_t("fof","f(f(x))","x")); + compositor.add(function_t("fof", "f(f(x))", "x")); // gog(x) = g(g(x)) - compositor.add(function_t("gog","g(g(x))","x")); + compositor.add(function_t("gog", "g(g(x))", "x")); // fog(x) = f(g(x)) - compositor.add(function_t("fog","f(g(x))","x")); + compositor.add(function_t("fog", "f(g(x))", "x")); // gof(x) = g(f(x)) - compositor.add(function_t("gof","g(f(x))","x")); + compositor.add(function_t("gof", "g(f(x))", "x")); // fogof(x) = f(g(f(x))) - compositor.add(function_t("fogof","f(g(f(x)))","x")); + compositor.add(function_t("fogof", "f(g(f(x)))", "x")); // gofog(x) = g(f(g(x))) - compositor.add(function_t("gofog","g(f(g(x)))","x")); + compositor.add(function_t("gofog", "g(f(g(x)))", "x")); symbol_table_t& symbol_table = compositor.symbol_table(); symbol_table.add_constants(); - symbol_table.add_variable("x",x); + symbol_table.add_variable("x", x); static const std::string expr_str_list[] = - { - "equal(f(x),(x + 2))", - "equal(g(x),(x^2 - 3))", - "equal(fof(x),(x + 4))", - "equal(gog(x),(x^4 - 6x^2 + 6))", - "equal(fog(x),(x^2 - 1))", - "equal(gof(x),(x^2 + 4x + 1))", - "equal(fogof(x),(x^2 + 4x + 3))", - "equal(gofog(x),(x^4 - 2x^2 - 2))" - }; + { + "equal(f(x),(x + 2))", + "equal(g(x),(x^2 - 3))", + "equal(fof(x),(x + 4))", + "equal(gog(x),(x^4 - 6x^2 + 6))", + "equal(fog(x),(x^2 - 1))", + "equal(gof(x),(x^2 + 4x + 1))", + "equal(fogof(x),(x^2 + 4x + 3))", + "equal(gofog(x),(x^4 - 2x^2 - 2))" + }; static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); std::deque expression_list; @@ -7779,7 +8569,7 @@ inline bool run_test19() parser_t parser; - if (!parser.compile(expr_str_list[i],expression)) + if (!parser.compile(expr_str_list[i], expression)) { printf("run_test19() - Error: %s Expression: %s\n", parser.error().c_str(), @@ -7791,7 +8581,7 @@ inline bool run_test19() expression_list.push_back(expression); } - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list.size(); ++i) { @@ -7800,153 +8590,160 @@ inline bool run_test19() printf("run_test19() - Error in evaluation! (1) Expression: %s\n", expr_str_list[i].c_str()); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } - const std::size_t rounds = 100; - - for (std::size_t r = 0; r < rounds; ++r) { - T x = T(1); - T y = T(2); - T z = T(3); - T w = T(4); - T u = T(5); - T v = T(6); - - compositor_t compositor; - - // f0() = 6 - compositor - .add( - function_t("f0") - .expression("3 * 2")); - - // f1(x) = 5 * (f0 + x) - compositor - .add( - function_t("f1") - .var("x") - .expression("5 * (f0 + x)")); - - // f2(x,y) = 7 * (f1(x) + f1(y)) - compositor - .add( - function_t("f2") - .var("x").var("y") - .expression("7 * (f1(x) + f1(y))")); + const std::size_t rounds = 100; - // f3(x,y,z) = 9 * (f2(x,y) + f2(y,z) + f2(x,z)) - compositor - .add( - function_t("f3") - .var("x").var("y").var("z") - .expression("9 * (f2(x,y) + f2(y,z) + f2(x,z))")); + for (std::size_t r = 0; r < rounds; ++r) + { + T x = T(1); + T y = T(2); + T z = T(3); + T w = T(4); + T u = T(5); + T v = T(6); + + compositor_t compositor; + + // f0() = 6 + compositor + .add( + function_t("f0") + .expression("3 * 2")); + + // f1(x) = 5 * (f0 + x) + compositor + .add( + function_t("f1") + .var("x") + .expression("5 * (f0 + x)")); + + // f2(x,y) = 7 * (f1(x) + f1(y)) + compositor + .add( + function_t("f2") + .var("x").var("y") + .expression("7 * (f1(x) + f1(y))")); + + // f3(x,y,z) = 9 * (f2(x,y) + f2(y,z) + f2(x,z)) + compositor + .add( + function_t("f3") + .var("x").var("y").var("z") + .expression("9 * (f2(x,y) + f2(y,z) + f2(x,z))")); + + // f4(x,y,z,w) = 11 * (f3(x,y,z) + f3(y,z,w) + f3(z,w,z)) + compositor + .add( + function_t("f4") + .var("x").var("y").var("z").var("w") + .expression("11 * (f3(x,y,z) + f3(y,z,w) + f3(z,w,x))")); + + // f5(x,y,z,w,u) = 13 * (f4(x,y,z,w) + f4(y,z,w,u) + f4(z,w,u,x) + f4(w,u,x,y)) + compositor + .add( + function_t("f5") + .var("x").var("y").var("z").var("w").var("u") + .expression("13 * (f4(x,y,z,w) + f4(y,z,w,u) + f4(z,w,u,x) + f4(w,u,x,y))")); + + // f6(x,y,z,w,u,v) = 17 * (f5(x,y,z,w,u) + f5(y,z,w,u,v) + f5(z,w,u,v,x) + f5(w,u,v,x,y)) + compositor + .add( + function_t("f6") + .var("x").var("y").var("z") + .var("w").var("u").var("v") + .expression("17 * (f5(x,y,z,w,u) + f5(y,z,w,u,v) + f5(z,w,u,v,x) + f5(w,u,v,x,y))")); + + symbol_table_t& symbol_table = compositor.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_variable("u", u); + symbol_table.add_variable("v", v); - // f4(x,y,z,w) = 11 * (f3(x,y,z) + f3(y,z,w) + f3(z,w,z)) - compositor - .add( - function_t("f4") - .var("x").var("y").var("z").var("w") - .expression("11 * (f3(x,y,z) + f3(y,z,w) + f3(z,w,x))")); + parser_t parser; - // f5(x,y,z,w,u) = 13 * (f4(x,y,z,w) + f4(y,z,w,u) + f4(z,w,u,x) + f4(w,u,x,y)) - compositor - .add( - function_t("f5") - .var("x").var("y").var("z").var("w").var("u") - .expression("13 * (f4(x,y,z,w) + f4(y,z,w,u) + f4(z,w,u,x) + f4(w,u,x,y))")); + const std::string expr_str_list[] = + { + "f0()", + "f1(x)", + "f2(x,x)", + "f3(x,x,x)", + "f4(x,x,x,x)", + "f5(x,x,x,x,x)", + "f6(x,x,x,x,x,x)", + "f2(x,y)", + "f3(x,y,z)", + "f4(x,y,z,w)", + "f5(x,y,z,w,u)", + "f6(x,y,z,w,u,v)" + }; - // f6(x,y,z,w,u,v) = 17 * (f5(x,y,z,w,u) + f5(y,z,w,u,v) + f5(z,w,u,v,x) + f5(w,u,v,x,y)) - compositor - .add( - function_t("f6") - .var("x").var("y").var("z") - .var("w").var("u").var("v") - .expression("17 * (f5(x,y,z,w,u) + f5(y,z,w,u,v) + f5(z,w,u,v,x) + f5(w,u,v,x,y))")); + const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); + + const T result_list[] = + { + T(6), + T(35), + T(490), + T(13230), + T(436590), + T(22702680), + T(1543782240), + T(525), + T(15120), + T(533610), + T(29459430), + T(2122700580) + }; - symbol_table_t& symbol_table = compositor.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_variable("u",u); - symbol_table.add_variable("v",v); + bool error_found = false; - parser_t parser; + for (std::size_t i = 0; i < expr_str_list_size; ++i) + { + expression_t expression; + expression.register_symbol_table(symbol_table); - const std::string expr_str_list[] = - { - "f0()", - "f1(x)", - "f2(x,x)", - "f3(x,x,x)", - "f4(x,x,x,x)", - "f5(x,x,x,x,x)", - "f6(x,x,x,x,x,x)", - "f2(x,y)", - "f3(x,y,z)", - "f4(x,y,z,w)", - "f5(x,y,z,w,u)", - "f6(x,y,z,w,u,v)" - }; - const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); + if (!parser.compile(expr_str_list[i], expression)) + { + printf("run_test19() - Error: %s Expression: %s\n", + parser.error().c_str(), + expr_str_list[i].c_str()); - const T result_list[] = - { - T(6 ), - T(35 ), - T(490 ), - T(13230 ), - T(436590 ), - T(22702680 ), - T(1543782240), - T(525 ), - T(15120 ), - T(533610 ), - T(29459430 ), - T(2122700580) - }; - - bool failure = false; + error_found = true; + continue; + } - for (std::size_t i = 0; i < expr_str_list_size; ++i) - { - expression_t expression; - expression.register_symbol_table(symbol_table); + const T result = expression.value(); - if (!parser.compile(expr_str_list[i],expression)) - { - printf("run_test19() - Error: %s Expression: %s\n", - parser.error().c_str(), - expr_str_list[i].c_str()); + if (result_list[i] != result) + { + printf("run_test19() - Error in evaluation! (2) Expression: %s Expected: %10.1f\tResult: %10.1f\n", + expr_str_list[i].c_str(), + result_list[i], + result); - failure = true; - continue; + error_found = true; + continue; + } } - const T result = expression.value(); - - if (result_list[i] != result) + if (error_found) { - printf("run_test19() - Error in evaluation! (2) Expression: %s Expected: %10.1f\tResult: %10.1f\n", - expr_str_list[i].c_str(), - result_list[i], - result); - - failure = true; - continue; + return false; } } - - if (failure) - return false; } { @@ -8064,12 +8861,13 @@ inline bool run_test19() symbol_table.add_constants(); symbol_table.add_variable("x",x); - const std::string expression_str[] = { - "is_prime1(x)", - "is_prime2(x)", - "is_prime3(x)", - "is_prime4(x)" - }; + const std::string expression_str[] = + { + "is_prime1(x)", + "is_prime2(x)", + "is_prime3(x)", + "is_prime4(x)" + }; const std::size_t expression_count = sizeof(expression_str) / sizeof(std::string); @@ -8095,32 +8893,32 @@ inline bool run_test19() expression_list.push_back(expression); } - bool failure = false; + bool error_found = false; const std::size_t prime_list[] = - { - 2, 3, 5, 7, 11, 13, 17, 19, - 877, 947, 1087, 1153, 1229, 1297, 1381, 1453, - 1523, 1597, 1663, 1741, 1823, 1901, 1993, 2063, - 2131, 2221, 2293, 2371, 2437, 2539, 2621, 2689, - 2749, 2833, 2909, 3001, 3083, 3187, 3259, 3343, - 3433, 3517, 3581, 3659, 3733, 3823, 3911, 4001, - 4073, 4153, 4241, 4327, 4421, 4507, 4591, 4663, - 4759, 4861, 4943, 5009, 5099, 5189, 5281, 5393, - 5449, 5527, 5641, 5701, 5801, 5861, 5953, 6067, - 6143, 6229, 6311, 6373, 6481, 6577, 6679, 6763, - 6841, 6947, 7001, 7109, 7211, 7307, 7417, 7507, - 104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, - 104393, 104399, 104417, 104459, 104471, 104473, 104479, 104491, - 104513, 104527, 104537, 104543, 104549, 104551, 104561, 104579, - 104593, 104597, 104623, 104639, 104651, 104659, 104677, 104681, - 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, - 1000621, 1000639, 1000651, 1000667, 1000669, 1001023, 1001027, 1001041 - }; + { + 2, 3, 5, 7, 11, 13, 17, 19, + 877, 947, 1087, 1153, 1229, 1297, 1381, 1453, + 1523, 1597, 1663, 1741, 1823, 1901, 1993, 2063, + 2131, 2221, 2293, 2371, 2437, 2539, 2621, 2689, + 2749, 2833, 2909, 3001, 3083, 3187, 3259, 3343, + 3433, 3517, 3581, 3659, 3733, 3823, 3911, 4001, + 4073, 4153, 4241, 4327, 4421, 4507, 4591, 4663, + 4759, 4861, 4943, 5009, 5099, 5189, 5281, 5393, + 5449, 5527, 5641, 5701, 5801, 5861, 5953, 6067, + 6143, 6229, 6311, 6373, 6481, 6577, 6679, 6763, + 6841, 6947, 7001, 7109, 7211, 7307, 7417, 7507, + 104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, + 104393, 104399, 104417, 104459, 104471, 104473, 104479, 104491, + 104513, 104527, 104537, 104543, 104549, 104551, 104561, 104579, + 104593, 104597, 104623, 104639, 104651, 104659, 104677, 104681, + 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, + 1000621, 1000639, 1000651, 1000667, 1000669, 1001023, 1001027, 1001041 + }; const std::size_t prime_list_size = sizeof(prime_list) / sizeof(std::size_t); - for (std::size_t i = 0; (i < prime_list_size) && (!failure); ++i) + for (std::size_t i = 0; (i < prime_list_size) && (!error_found); ++i) { x = static_cast(prime_list[i]); @@ -8135,12 +8933,12 @@ inline bool run_test19() { if (result[j] != result[0]) { - failure = true; + error_found = true; break; } } - if (failure) + if (error_found) { printf("run_test19() - Error in evaluation! (3) Results don't match! Prime: %d\n", static_cast(prime_list[i])); @@ -8168,8 +8966,10 @@ inline bool run_test19() } } - if (failure) + if (error_found) + { return false; + } } { @@ -8265,13 +9065,14 @@ inline bool run_test19() symbol_table.add_constants(); symbol_table.add_variable("x",x); - const std::string expression_str[] = { - "fibonacci1(x)", - "fibonacci2(x)", - "fibonacci3(x)", - "fibonacci4(x)", - "fibonacci5(x)" - }; + const std::string expression_str[] = + { + "fibonacci1(x)", + "fibonacci2(x)", + "fibonacci3(x)", + "fibonacci4(x)", + "fibonacci5(x)" + }; const std::size_t expression_count = sizeof(expression_str) / sizeof(std::string); @@ -8297,23 +9098,23 @@ inline bool run_test19() expression_list.push_back(expression); } - bool failure = false; + bool error_found = false; const std::size_t fibonacci_list[] = - { - 0, 1, 1, 2, - 3, 5, 8, 13, - 21, 34, 55, 89, - 144, 233, 377, 610, - 987, 1597, 2584, 4181, - 6765, 10946, 17711, 28657, - 46368, 75025, 121393, 196418, - 317811, 514229, 832040, 1346269 - }; + { + 0, 1, 1, 2, + 3, 5, 8, 13, + 21, 34, 55, 89, + 144, 233, 377, 610, + 987, 1597, 2584, 4181, + 6765, 10946, 17711, 28657, + 46368, 75025, 121393, 196418, + 317811, 514229, 832040, 1346269 + }; const std::size_t fibonacci_list_size = sizeof(fibonacci_list) / sizeof(std::size_t); - for (std::size_t i = 0; (i < fibonacci_list_size) && (!failure); ++i) + for (std::size_t i = 0; (i < fibonacci_list_size) && (!error_found); ++i) { x = static_cast(i); @@ -8328,12 +9129,12 @@ inline bool run_test19() { if (result[j] != result[0]) { - failure = true; + error_found = true; break; } } - if (failure) + if (error_found) { printf("run_test19() - Error in evaluation! (5) Results don't match! fibonacci(%d) = %d\n", static_cast(i), @@ -8363,8 +9164,10 @@ inline bool run_test19() } } - if (failure) + if (error_found) + { return false; + } } { @@ -8422,7 +9225,7 @@ inline bool run_test19() return false; } - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < 100; ++i) { @@ -8438,12 +9241,14 @@ inline bool run_test19() static_cast(std::sqrt(x)), static_cast(result)); - failure = true; + error_found = true; } } - if (failure) + if (error_found) + { return false; + } } { @@ -8570,7 +9375,395 @@ inline bool run_test19() return false; } } + } + + { + const std::pair test_funcprog[] = + { + std::make_pair + ( + " var s := depth_to_str(depth); " + " " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " " + " s == depth_to_str(depth); ", + + " recursive(1000) " + ), + + std::make_pair + ( + " var v[7] := [ depth ]; " + " " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " " + " return [sum(v == depth) == v[]]; ", + + " recursive(1000) " + ), + + std::make_pair + ( + " var v1[ 7] := [ depth ]; " + " var v2[21] := [ depth ]; " + " " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " " + " (sum(v1 == depth) == v1[]) and " + " (sum(v2 == depth) == v2[]) ; " + " ", + + " recursive(1000) " + ), + + std::make_pair + ( + " var s := depth_to_str(depth); " + " " + " for (var i := 0; i < 2; i += 1) " + " { " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " }; " + " " + " s == depth_to_str(depth); ", + + " recursive(20) " + ), + + std::make_pair + ( + " var s := depth_to_str(depth); " + " " + " for (var i := 0; i < 2; i += 1) " + " { " + " for (var j := 0; j < 2; j += 1) " + " { " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " }; " + " }; " + " " + " s == depth_to_str(depth); ", + + " recursive(10) " + ), + + std::make_pair + ( + " var v[7] := [ depth ]; " + " " + " for (var i := 0; i < 2; i += 1) " + " { " + " var w[21] := [ depth + 1 ]; " + " " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " " + " if (sum(w == (depth + 1)) != w[]) " + " { " + " return [false]; " + " }; " + " }; " + " " + " return [sum(v == depth) == v[]]; ", + + " recursive(5) " + ), + + std::make_pair + ( + " var v[7] := [ depth ]; " + " " + " for (var i := 0; i < 2; i += 1) " + " { " + " var u[21] := [ depth + 1 ]; " + " " + " for (var j := 0; j < 2; j += 1) " + " { " + " var w[35] := [ depth + 2 ]; " + " " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " " + " if (sum(w == (depth + 2)) != w[]) " + " { " + " return [false]; " + " }; " + " }; " + " " + " if (sum(u == (depth + 1)) != u[]) " + " { " + " return [false]; " + " }; " + " }; " + " " + " return [sum(v == depth) == v[]]; ", + + " recursive(5) " + ), + + std::make_pair + ( + " var s := depth_to_str(depth); " + " var v[7] := [ depth ]; " + " " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " " + " return " + " [ " + " (s == depth_to_str(depth)) and " + " (sum(v == depth) == v[]) " + " ]; ", + + " recursive(1000) " + ), + + std::make_pair + ( + " var s0 := depth_to_str(depth); " + " var v0[7] := [ depth ]; " + " var s1 := depth_to_str(depth); " + " var v1[42] := [ depth ]; " + " " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " " + " return " + " [ " + " (s0 == depth_to_str(depth)) and " + " (sum(v0 == depth) == v0[]) and " + " (s1 == depth_to_str(depth)) and " + " (sum(v1 == depth) == v1[]) " + " ]; ", + + " recursive(1000) " + ), + + std::make_pair + ( + " var s := depth_to_str(depth); " + " var v[7] := [ depth ]; " + " " + " for (var i := 0; i < 2; i += 1) " + " { " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " }; " + " " + " return " + " [ " + " (s == depth_to_str(depth)) and " + " (sum(v == depth) == v[]) " + " ]; ", + + " recursive(15) " + ), + + std::make_pair + ( + " var s0 := depth_to_str(depth); " + " var v0[7] := [ depth ]; " + " var s1 := depth_to_str(depth); " + " var v1[42] := [ depth ]; " + " " + " for (var i := 0; i < 2; i += 1) " + " { " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " }; " + " " + " return " + " [ " + " (s0 == depth_to_str(depth)) and " + " (sum(v0 == depth) == v0[]) and " + " (s1 == depth_to_str(depth)) and " + " (sum(v1 == depth) == v1[]) " + " ]; ", + + " recursive(15) " + ), + + std::make_pair + ( + " var s0 := depth_to_str(depth); " + " var v0[7] := [ depth ]; " + " " + " for (var i := 0; i < 2; i += 1) " + " { " + " var s1 := depth_to_str(depth); " + " var v1[21] := [ depth + 1 ]; " + " " + " if (depth > 0) " + " { " + " if (recursive(depth - 1) == false) " + " { " + " return [false]; " + " } " + " }; " + " " + " if (s1 != depth_to_str(depth)) " + " { " + " return [false]; " + " }; " + " " + " if (sum(v1 == (depth + 1)) != v1[]) " + " { " + " return [false]; " + " }; " + " }; " + " " + " return " + " [ " + " (s0 == depth_to_str(depth)) and " + " (sum(v0 == depth) == v0[]) " + " ]; ", + + " recursive(15) " + ), + + std::make_pair + ( + " if (depth < 2) " + " depth; " + " else " + " recursive(depth - 1) + " + " recursive(depth - 2) ; ", + + " var n := 20; " + " var total := 0; " + " " + " for (var i := 0; i < n; i += 1) " + " { " + " total += recursive(i); " + " }; " + " " + " total == 10945; " + ) + }; + + const std::size_t test_funcprog_size = sizeof(test_funcprog) / sizeof(std::pair); + const std::size_t rounds = 5; + + bool result = true; + + for (std::size_t r = 0; r < rounds; ++r) + { + for (std::size_t i = 0; i < test_funcprog_size; ++i) + { + depth_to_str dts; + + symbol_table_t symbol_table; + symbol_table.add_function("depth_to_str",dts); + + compositor_t compositor(symbol_table); + + const bool comp_result = compositor.add( + function_t("recursive") + .var("depth") + .expression + ( test_funcprog[i].first )); + + if (!comp_result) + { + printf("run_test19() - Compositor Error: %s\nfunction: %s\n", + compositor.error().c_str(), + test_funcprog[i].first.c_str()); + + result = false; + continue; + } + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + if (!parser.compile(test_funcprog[i].second, expression)) + { + printf("run_test19() - Error: %s Expression: %s\n", + parser.error().c_str(), + test_funcprog[i].second.c_str()); + + result = false; + continue; + } + + if (T(1) != expression.value()) + { + printf("run_test19() - Evaluation Error: test_funcprog %d function: %s\n", + static_cast(i), + test_funcprog[i].second.c_str()); + result = false; + continue; + } + } + + if (!result) + { + return false; + } + } } { @@ -8578,34 +9771,34 @@ inline bool run_test19() symbol_table.add_constants(); - std::string expression_str = - " var sieve[10^7] := [false]; " - " var m := trunc(sqrt(sieve[])); " - " " - " sieve[0] := true; " - " sieve[1] := true; " - " " - " for (var i := 0; i <= m; i += 1) " - " { " - " if (false == sieve[i]) " - " { " - " for (var j := (i * i); j < sieve[]; j += i) " - " { " - " sieve[j] := true; " - " } " - " } " - " }; " - " " - " var prime_count := 0; " - " for (var i := 0; i < sieve[]; i += 1) " - " { " - " if (false == sieve[i]) " - " { " - " prime_count += 1; " - " }; " - " }; " - " " - " prime_count == 664579; "; + const std::string expression_string = + " var sieve[10^7] := [false]; " + " var m := trunc(sqrt(sieve[])); " + " " + " sieve[0] := true; " + " sieve[1] := true; " + " " + " for (var i := 0; i <= m; i += 1) " + " { " + " if (false == sieve[i]) " + " { " + " for (var j := (i * i); j < sieve[]; j += i) " + " { " + " sieve[j] := true; " + " } " + " } " + " }; " + " " + " var prime_count := 0; " + " for (var i := 0; i < sieve[]; i += 1) " + " { " + " if (false == sieve[i]) " + " { " + " prime_count += 1; " + " }; " + " }; " + " " + " prime_count == 664579; "; expression_t expression; @@ -8613,11 +9806,11 @@ inline bool run_test19() parser_t parser; - if (!parser.compile(expression_str,expression)) + if (!parser.compile(expression_string,expression)) { printf("run_test19() - Error: %s Expression: %s\n", parser.error().c_str(), - expression_str.c_str()); + expression_string.c_str()); return false; } @@ -8635,14 +9828,14 @@ inline bool run_test19() symbol_table.add_constants(); - std::string expression_str[] = - { - "var delta := 10^-7; var total := 0; for (var i := 0; i <= 3; i += delta) { total += " - "erf(i) }; abs((delta * total) - (3 * erf(3) + (1 / exp(9) - 1) / sqrt(pi))) < 0.000001", + const std::string expression_str[] = + { + "var delta := 10^-7; var total := 0; for (var i := 0; i <= 3; i += delta) { total += " + "erf(i) }; abs((delta * total) - (3 * erf(3) + (1 / exp(9) - 1) / sqrt(pi))) < 0.000001", - "var delta := 10^-7; var total := 0; for (var i := 0; i <= 3; i += delta) { total += " - "erfc(i) }; abs((delta * total) - (3 * erfc(3) + ((1 - 1 / exp(9)) / sqrt(pi)))) < 0.000001" - }; + "var delta := 10^-7; var total := 0; for (var i := 0; i <= 3; i += delta) { total += " + "erfc(i) }; abs((delta * total) - (3 * erfc(3) + ((1 - 1 / exp(9)) / sqrt(pi)))) < 0.000001" + }; expression_t e[2]; @@ -8675,14 +9868,17 @@ inline bool run_test19() } template -struct my_usr : public exprtk::parser::unknown_symbol_resolver +struct my_usr exprtk_test_final : public exprtk::parser::unknown_symbol_resolver { typedef typename exprtk::parser::unknown_symbol_resolver usr_t; + typedef typename usr_t::usr_symbol_type usr_symbol_type; + + using usr_t::process; bool process(const std::string& unknown_symbol, - typename usr_t::usr_symbol_type& st, + usr_symbol_type& st, T& default_value, - std::string& error_message) + std::string& error_message) exprtk_test_override { if (unknown_symbol[0] == 'v') { @@ -8719,18 +9915,20 @@ struct my_usr : public exprtk::parser::unknown_symbol_resolver }; template -struct my_usr_ext : public exprtk::parser::unknown_symbol_resolver +struct my_usr_ext exprtk_test_final : public exprtk::parser::unknown_symbol_resolver { typedef exprtk::symbol_table symbol_table_t; typedef typename exprtk::parser::unknown_symbol_resolver usr_t; + using usr_t::process; + my_usr_ext() : usr_t(usr_t::e_usrmode_extended) {} - virtual bool process(const std::string& unknown_symbol, - symbol_table_t& symbol_table, - std::string& error_message) + bool process(const std::string& unknown_symbol, + symbol_table_t& symbol_table, + std::string& error_message) exprtk_test_override { bool result = false; @@ -8792,7 +9990,7 @@ struct my_usr_ext : public exprtk::parser::unknown_symbol_resolver }; template -inline bool run_test20() +bool run_test20() { typedef exprtk::expression expression_t; @@ -8885,6 +10083,7 @@ inline bool run_test20() std::vector vec(10,0.0); typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; bool result = true; @@ -8997,27 +10196,115 @@ inline bool run_test20() if (!result) return result; - } - - return true; -} -template -inline std::string results_to_string(const exprtk::results_context& results) -{ - typedef exprtk::results_context results_context_t; - typedef typename results_context_t::type_store_t type_t; + { + symbol_table_t symbol_table1; + symbol_table_t symbol_table2; + expression_t expression; - std::string res_str; + if (!expression.register_symbol_table(symbol_table1)) + { + printf("run_test20() - Failed to register symbol_table1 with expression\n"); + result = false; + } - for (std::size_t i = 0; i < results.count(); ++i) - { - type_t t = results[i]; + if (!expression.register_symbol_table(symbol_table2)) + { + printf("run_test20() - Failed to register symbol_table2 with expression\n"); + result = false; + } - switch (t.type) - { - case type_t::e_scalar : res_str += 'T'; - break; + if (expression.num_symbol_tables() != 2) + { + printf("run_test20() - Invalid number of symbol tables in expression [1]\n"); + result = false; + } + + if (expression.register_symbol_table(symbol_table1)) + { + printf("run_test20() - Error: was able to register symbol_table1 with expression\n"); + result = false; + } + + if (expression.register_symbol_table(symbol_table2)) + { + printf("run_test20() - Error: was able to register symbol_table2 with expression\n"); + result = false; + } + + if (expression.num_symbol_tables() != 2) + { + printf("run_test20() - Invalid number of symbol tables in expression [2]\n"); + result = false; + } + + symbol_table_t symbol_table12 = symbol_table1; + symbol_table_t symbol_table22 = symbol_table2; + + if (expression.register_symbol_table(symbol_table12)) + { + printf("run_test20() - Error: was able to register symbol_table12 with expression\n"); + result = false; + } + + if (expression.register_symbol_table(symbol_table22)) + { + printf("run_test20() - Error: was able to register symbol_table22 with expression\n"); + result = false; + } + + if (expression.num_symbol_tables() != 2) + { + printf("run_test20() - Invalid number of symbol tables in expression [3]\n"); + result = false; + } + + symbol_table12 = symbol_table_t(); + symbol_table22 = symbol_table_t(); + + if (!expression.register_symbol_table(symbol_table12)) + { + printf("run_test20() - Failed to register symbol_table12 with expression [2]\n"); + result = false; + } + + if (!expression.register_symbol_table(symbol_table22)) + { + printf("run_test20() - Failed to register symbol_table22 with expression [2]\n"); + result = false; + } + + if (expression.num_symbol_tables() != 4) + { + printf("run_test20() - Invalid number of symbol tables in expression [4]\n"); + result = false; + } + } + + if (!result) + return result; + + } + + return true; +} + +template +inline std::string results_to_string(const exprtk::results_context& results) +{ + typedef exprtk::results_context results_context_t; + typedef typename results_context_t::type_store_t type_t; + + std::string res_str; + + for (std::size_t i = 0; i < results.count(); ++i) + { + type_t t = results[i]; + + switch (t.type) + { + case type_t::e_scalar : res_str += 'T'; + break; case type_t::e_vector : res_str += 'V'; break; @@ -9048,11 +10335,65 @@ inline bool result_equal(const exprtk::results_context& results, const T& val } template -inline bool run_test21() +class vv_size_handler_t : public exprtk::igeneric_function +{ +public: + + typedef typename exprtk::igeneric_function 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; + typedef typename generic_type::scalar_view scalar_t; + typedef exprtk::vector_view* vv_ptr_t; + typedef std::map map_t; + + using exprtk::igeneric_function::operator(); + + vv_size_handler_t() + : exprtk::igeneric_function("VT") + {} + + inline T operator()(parameter_list_t parameters) + { + vector_t vector(parameters[0]); + size_t new_size = static_cast(scalar_t(parameters[1])()); + void* key = static_cast(&vector[0]); + + typename map_t::iterator itr = vector_map_.find(key); + + if (itr == vector_map_.end()) + { + return T(0); + } + + exprtk::vector_view& vv = *itr->second; + + if (vv.base_size() < new_size) + { + return T(0); + } + + return vv.set_size(new_size) ? T(1) : T(0); + } + + void register_vector_view(exprtk::vector_view& vec_view) + { + vector_map_[vec_view.data()] = &vec_view; + } + +private: + + map_t vector_map_; +}; + + +template +bool run_test21() { typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; + typedef exprtk::parser_error::type error_type; { T x = T(1.1); @@ -9066,48 +10407,48 @@ inline bool run_test21() symbol_table.add_variable("z",z); static const std::string expression_list[] = - { - "return[]; x;", - "return[x]; x;", - "return[x,y]; x;", - "return[x + y,y - x]; x;", - "return[x + y,y - x,'abc']; x;", - "if (x < y) return [1,'abc1']; else return [2,'abc2',x];" , - "if (x > y) return [1,'abc1']; else return [2,'abc2',x];" , - "if (x < y) { return [1,'abc1'];} else { return [2,'abc2',x];}", - "if (x > y) { return [1,'abc1'];} else { return [2,'abc2',x];}", - "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1]; } ", - "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1,'abc']; } ", - "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1,'abc',x]; }", - "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1,'abc',x,y]; }", - "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1,'abc',x,y,z]; }", - "for(var i := 0; i < 10; i += 1) { if (i == 5) return [2,'abc2',x]; else x += 1; }", - "for(var i := 0; i < 10; i += 1) { if (i == 5) { return [1,'abc1'];} else x += 1; }" - }; + { + "return[]; x;", + "return[x]; x;", + "return[x,y]; x;", + "return[x + y,y - x]; x;", + "return[x + y,y - x,'abc']; x;", + "if (x < y) return [1,'abc1']; else return [2,'abc2',x];" , + "if (x > y) return [1,'abc1']; else return [2,'abc2',x];" , + "if (x < y) { return [1,'abc1'];} else { return [2,'abc2',x];}", + "if (x > y) { return [1,'abc1'];} else { return [2,'abc2',x];}", + "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1]; } ", + "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1,'abc']; } ", + "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1,'abc',x]; }", + "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1,'abc',x,y]; }", + "for(var i := 0; i < 10; i += 1) { if (i == 5) return [1,'abc',x,y,z]; }", + "for(var i := 0; i < 10; i += 1) { if (i == 5) return [2,'abc2',x]; else x += 1; }", + "for(var i := 0; i < 10; i += 1) { if (i == 5) { return [1,'abc1'];} else x += 1; }" + }; static const std::string result_list[] = - { - "" , - "T" , - "TT" , - "TT" , - "TTS" , - "TS" , - "TST" , - "TS" , - "TST" , - "T" , - "TS" , - "TST" , - "TSTT" , - "TSTTT", - "TST" , - "TS" - }; + { + "" , + "T" , + "TT" , + "TT" , + "TTS" , + "TS" , + "TST" , + "TS" , + "TST" , + "T" , + "TS" , + "TST" , + "TSTT" , + "TSTTT", + "TST" , + "TS" + }; static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list_size; ++i) { @@ -9122,7 +10463,7 @@ inline bool run_test21() parser.error().c_str(), expression_list[i].c_str()); - failure = true; + error_found = true; continue; } else if (!parser.dec().return_present()) @@ -9130,7 +10471,7 @@ inline bool run_test21() printf("run_test21() - Expected a return statement Expression: %s [1]\n", expression_list[i].c_str()); - failure = true; + error_found = true; continue; } @@ -9143,7 +10484,7 @@ inline bool run_test21() printf("run_test21() - Invalid return invoke state [1] Expression: %s\n", expression_list[i].c_str()); - failure = true; + error_found = true; continue; } else if (result_list[i] != pattern) @@ -9153,13 +10494,15 @@ inline bool run_test21() pattern.c_str(), expression_list[i].c_str()); - failure = true; + error_found = true; continue; } } - if (failure) + if (error_found) + { return false; + } } { @@ -9174,22 +10517,22 @@ inline bool run_test21() symbol_table.add_variable("z",z); static const std::string expression_list[] = - { - "x := 1; x + 1; x + 2; x + 3; x + 5; x + 7; return [x + 1]; ", - "x := 1; x + 1; x + 2; x + 3; x + 5; return [x + 1]; x := 7; ", - "x := 1; x + 1; x + 2; x + 3; return [x + 1]; x + 5; x := 7; ", - "x := 1; x + 1; x + 2; return [x + 1]; x + 3; x + 5; x := 7; ", - "x := 1; x + 1; return [x + 1]; x + 2; x + 3; x + 5; x := 7; ", - "x := 1; return [x + 1]; x + 1; x + 2; x + 3; x + 5; x := 7; ", - "return [x + 1]; x := 1; x + 1; x + 2; x + 3; x + 5; x := 7; ", - "~{x := 1; x + 1; x + 2; x + 3; x + 5; x + 7; return [x + 1]}", - "~{x := 1; x + 1; x + 2; x + 3; x + 5; return [x + 1]; x := 7}", - "~{x := 1; x + 1; x + 2; x + 3; return [x + 1]; x + 5; x := 7}", - "~{x := 1; x + 1; x + 2; return [x + 1]; x + 3; x + 5; x := 7}", - "~{x := 1; x + 1; return [x + 1]; x + 2; x + 3; x + 5; x := 7}", - "~{x := 1; return [x + 1]; x + 1; x + 2; x + 3; x + 5; x := 7}", - "~{return [x + 1]; x := 1; x + 1; x + 2; x + 3; x + 5; x := 7}" - }; + { + "x := 1; x + 1; x + 2; x + 3; x + 5; x + 7; return [x + 1]; ", + "x := 1; x + 1; x + 2; x + 3; x + 5; return [x + 1]; x := 7; ", + "x := 1; x + 1; x + 2; x + 3; return [x + 1]; x + 5; x := 7; ", + "x := 1; x + 1; x + 2; return [x + 1]; x + 3; x + 5; x := 7; ", + "x := 1; x + 1; return [x + 1]; x + 2; x + 3; x + 5; x := 7; ", + "x := 1; return [x + 1]; x + 1; x + 2; x + 3; x + 5; x := 7; ", + "return [x + 1]; x := 1; x + 1; x + 2; x + 3; x + 5; x := 7; ", + "~{x := 1; x + 1; x + 2; x + 3; x + 5; x + 7; return [x + 1]}", + "~{x := 1; x + 1; x + 2; x + 3; x + 5; return [x + 1]; x := 7}", + "~{x := 1; x + 1; x + 2; x + 3; return [x + 1]; x + 5; x := 7}", + "~{x := 1; x + 1; x + 2; return [x + 1]; x + 3; x + 5; x := 7}", + "~{x := 1; x + 1; return [x + 1]; x + 2; x + 3; x + 5; x := 7}", + "~{x := 1; return [x + 1]; x + 1; x + 2; x + 3; x + 5; x := 7}", + "~{return [x + 1]; x := 1; x + 1; x + 2; x + 3; x + 5; x := 7}" + }; static const std::string result_list[] = { @@ -9199,7 +10542,7 @@ inline bool run_test21() static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); - bool failure = false; + bool error_found = false; for (std::size_t i = 0; i < expression_list_size; ++i) { @@ -9214,7 +10557,7 @@ inline bool run_test21() parser.error().c_str(), expression_list[i].c_str()); - failure = true; + error_found = true; continue; } else if (!parser.dec().return_present()) @@ -9222,7 +10565,7 @@ inline bool run_test21() printf("run_test21() - Expected a return statement Expression: %s [2]\n", expression_list[i].c_str()); - failure = true; + error_found = true; continue; } @@ -9235,7 +10578,7 @@ inline bool run_test21() printf("run_test21() - Invalid return invoke state [2] Expression: %s\n", expression_list[i].c_str()); - failure = true; + error_found = true; continue; } else if (result_list[i] != pattern) @@ -9245,7 +10588,7 @@ inline bool run_test21() pattern.c_str(), expression_list[i].c_str()); - failure = true; + error_found = true; continue; } else if (!result_equal(expression.results(), x + T(1))) @@ -9255,13 +10598,116 @@ inline bool run_test21() pattern.c_str(), expression_list[i].c_str()); - failure = true; + error_found = true; continue; } } - if (failure) + if (error_found) + { + return false; + } + } + + { + T x = 1.0; + T y = 2.0; + T z = 3.0; + + T v[] = {0 , 1, 2, 3 }; + std::string s = "Hello "; + + myfunc mf; + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + symbol_table.add_variable ("x", x); + symbol_table.add_variable ("y", y); + symbol_table.add_variable ("z", z); + symbol_table.add_vector ("v", v); + symbol_table.add_stringvar("s", s); + + expression.register_symbol_table(symbol_table); + + const std::string expression_str = + " if (x > y) " + " return [1]; " + " else " + " return [ x, x + y, 2 * v, s + 'world' ]; "; + + if (!parser.compile(expression_str, expression)) + { + printf("run_test21() - ERROR: %s\tExpression: %s\n", + parser.error().c_str(), + expression_str.c_str()); + return false; + } + + expression.value(); + + typedef exprtk::results_context results_context_t; + const results_context_t& results = expression.results(); + + if (results.count() != 4) + { + printf("run_test21() - ERROR Expected 4 return results, instead got: %d\n", + static_cast(results.count())); + return false; + } + + T result_x0; + T result_x1; + std::string result_s; + std::vector result_v; + + const T expected_result_v[] = {0 , 2, 4, 6 }; + const std::string expected_result_s = "Hello world"; + + if (!results.get_scalar(0,result_x0)) + { + printf("run_test21() - ERROR Failed to get scalar index0 from return result!\n"); + return false; + } + else if (result_x0 != T(1)) + { + printf("run_test21() - ERROR result_x0 is not expected value!\n"); + return false; + } + else if (!results.get_scalar(1,result_x1)) + { + printf("run_test21() - ERROR Failed to get scalar index1 from return result!\n"); + return false; + } + else if (result_x1 != T(3)) + { + printf("run_test21() - ERROR result_x1 is not expected value!\n"); + return false; + } + else if (!results.get_vector(2,result_v)) + { + printf("run_test21() - ERROR Failed to get vector from return result!\n"); + return false; + } + else if ( + (result_v.size() != (sizeof(expected_result_v) / sizeof(T))) || + !std::equal(result_v.begin(),result_v.end(),expected_result_v) + ) + { + printf("run_test21() - ERROR result_v is not expected value!\n"); + return false; + } + else if (!results.get_string(3,result_s)) + { + printf("run_test21() - ERROR Failed to get string from return result!\n"); + return false; + } + else if (result_s != expected_result_s) + { + printf("run_test21() - ERROR result_s is not expected value!\n"); return false; + } } { @@ -9344,7 +10790,2019 @@ inline bool run_test21() } } - return true; + { + T x = 1.1; + T y = 2.2; + T z = 3.3; + T w = 4.4; + + symbol_table_t mutable_symbol_table; + symbol_table_t immutable_symbol_table(symbol_table_t::e_immutable); + + mutable_symbol_table.add_variable("x", x); + mutable_symbol_table.add_variable("y", y); + + immutable_symbol_table.add_variable("w", w); + immutable_symbol_table.add_variable("z", z); + + expression_t expression; + expression.register_symbol_table(mutable_symbol_table ); + expression.register_symbol_table(immutable_symbol_table); + + parser_t parser; + + typedef std::pair local_test_t; + + const local_test_t expressions[] = + { + std::make_pair("x := y + (z / w)" , true ), + std::make_pair("y := y / x + (z / w)" , true ), + std::make_pair("z := y + x - w" , false), + std::make_pair("z == (w += y / x)" , false) + }; + + const std::size_t expressions_size = sizeof(expressions) / sizeof(local_test_t); + + bool error_found = false; + + for (std::size_t i = 0; i < expressions_size; ++i) + { + const std::string expression_str = expressions[i].first; + const bool expected_compile_result = expressions[i].second; + + if (expected_compile_result != parser.compile(expression_str, expression)) + { + printf("run_test21() - Invalid compilation of expression. Expected compile result: %c Expression: %s\n", + expected_compile_result ? 'T' : 'F', + expression_str.c_str()); + + error_found = true; + } + + x += 1.1; + y += 2.2; + z += 3.3; + w += 4.4; + + expression.value(); + } + + if (error_found) + { + return false; + } + } + + { + typedef typename parser_t::settings_store settings_t; + + const std::string invalid_expressions[] = + { + "var result := 0; if (true) { result := 2 } if (true) { result := 3 }; result", + "var result := 0; if (true) { result := 2 }; if (true) { result := 3 } result", + "var result := 0; if (true) { result := 2 } if (true) { result := 3 } result", + "var result := 0; var x:=1; if (x > 0) { result := 2 } else if (x > 0) { result := 3 } result", + "var result := 0; var x := 1; if (x > 0) { result := 2 } if (x > 0) { result := 3 }; result", + "var result := 0; var x := 1; if (x > 0) { result := 2 }; if (x > 0) { result := 3 } result", + "var result := 0; var x := 1; if (x > 0) { result := 2 } if (x > 0) { result := 3 } result", + "var result := 0; var x := 1; if (x > 0) { result := 2 } else if (x > 0) { result := 3 } result", + "var result := 0; var x := 1; if (x > 0) result := 2 else if (x > 0) { result := 3 } result", + "var result := 0; var x := 1; if (x > 0) {result := 2 } else if (x > 0) result := 3 result", + "var x := 2; var y := 0; x y ", + "var x := 2; x var y := 0; ", + "var x := 2; var y := 0; while (y < 3) { x := x * x; y += 1; } x ", + "var x := 2; var y := 0; for (var i := 0; i < 2; i += 1) { x := x * x; y += 1; } x ", + "var x := 2; var y := 0; while (y < 3) { x := x * x; y += 1; } 1 ", + "var x := 2; var y := 0; for (var i := 0; i < 2; i += 1) { x := x * x; y += 1; } 1 ", + "var x := 2; var y := 0; x while (y < 3) { x := x * x; y += 1; } ", + "var x := 2; var y := 0; x for (var i := 0; i < 2; i += 1) { x := x * x; y += 1; } ", + "var x := 2; var y := 0; for (var i := 0; i < 2; i += 1) { x := x * x; y += 1; } (1 + x)", + "var x := 2; var y := 0; for (var i := 0; i < 2; i += 1) { x := x * x; y += 1; } (x + 1)", + "var x := 2; var y := 0; (1 + x) for (var i := 0; i < 2; i += 1) { x := x * x; y += 1; }", + "var x := 2; var y := 0; (x + 1) for (var i := 0; i < 2; i += 1) { x := x * x; y += 1; }", + "var x := 2; var y := 0; (x + y) for (var i := 0; i < 2; i += 1) { x := x * x; y += 1; }", + "'hello' 1", + "1 'hello'", + "'hel' + 'lo' 1", + "1 'hel' + 'lo'", + "1 2", + "a b", + "a b c", + "var x := 2; 1 2 ", + "var x := 2; 1 x ", + "var x := 2; x 1 ", + "var x := 2; a 1 ", + "var x := 2; x a ", + "var x := 2; x a b ", + "var x := 2; x a b c ", + "var x := 2; a x ", + "var x := 2; a x b ", + "var x := 2; a x b c ", + "var x := 2; 'hello' 1", + "var x := 2; 1 'hello'", + "var x := 2; 'hello' x", + "var x := 2; x 'hello'", + "var x := 2; (x 1) ", + "var x := 2; (1 x) ", + "var x := 2; 2 + (x 1) ", + "var x := 2; 2 + (1 x) ", + "var x := 2; x + (x 1) ", + "var x := 2; x + (1 x) ", + "var x := 2; (x 1) + 2 ", + "var x := 2; (1 x) + 2 ", + "var x := 2; (x 1) + x ", + "var x := 2; (1 x) + x ", + "var x := 2; var y := 3; (x y) ", + "var x := 2; var y := 3; (y x) ", + "var x := 2; var y := 3; 2 + (x y) ", + "var x := 2; var y := 3; 2 + (y x) ", + "var x := 2; var y := 3; x + (x y) ", + "var x := 2; var y := 3; x + (y x) ", + "var x := 2; var y := 3; (x y) + 2 ", + "var x := 2; var y := 3; (y x) + 2 ", + "var x := 2; var y := 3; (x y) + x ", + "var x := 2; var y := 3; (y x) + x ", + "var x := 2; 2 + x 1 ", + "var x := 2; 2 + 1 x ", + "var x := 2; x + x 1 ", + "var x := 2; x + 1 x ", + "var x := 2; var y := 3; 2 + x y ", + "var x := 2; var y := 3; 2 + y x ", + "var x := 2; var y := 3; x + x y ", + "var x := 2; var y := 3; x + y x ", + "~{1; 2; 3} 1 ", + "1 ~{1; 2; 3} ", + "var x := 2; x ~{x; 1; 2} ", + "var x := 2; 1 ~{x; 1; 2} ", + "var x := 2; ~{x; 1; 2} x ", + "var x := 2; ~{x; 1; 2} 1 ", + "~(1; 2; 3) 1 ", + "1 ~(1; 2; 3) ", + "var x := 2; x ~(x; 1; 2) ", + "var x := 2; 1 ~(x; 1; 2) ", + "var x := 2; ~(x; 1; 2) x ", + "var x := 2; ~(x; 1; 2) 1 ", + "var x := 2; (x + 1) ~{x; 1; 2} ", + "var x := 2; (1 + x) ~{x; 1; 2} ", + "var x := 2; ~{x; 1; 2} (x + 1) ", + "var x := 2; ~{x; 1; 2} (1 + x) ", + "var x := 2; x + 1 ~{x; 1; 2} ", + "var x := 2; 1 + x ~{x; 1; 2} ", + "var x := 2; ~{x; 1; 2} x + 1 ", + "var x := 2; ~{x; 1; 2} 1 + x ", + "~(1, 2, 3) 1 ", + "1 ~(1, 2, 3) ", + "var x := 2; x ~(x, 1, 2) ", + "var x := 2; 1 ~(x, 1, 2) ", + "var x := 2; ~(x, 1, 2) x ", + "var x := 2; ~(x, 1, 2) 1 ", + "var x := 2; 1 switch { case x > 1 : 1; case x < 3 : 2; default : 3; } ", + "var x := 2; x switch { case x > 1 : 1; case x < 3 : 2; default : 3; } ", + "var x := 2; switch { case x > 1 : 1; case x < 3 : 2; default : 3; } x ", + "var x := 2; 1 [*] { case x > 1 : 1; case x < 3 : 2; } ", + "var x := 2; x [*] { case x > 1 : 1; case x < 3 : 2; } ", + "var x := 2; [*] { case x > 1 : 1; case x < 3 : 2; } x ", + "var x := 2; (x + 1) switch { case x > 1 : 1; case x < 3 : 2; default : 3; } ", + "var x := 2; switch { case x > 1 : 1; case x < 3 : 2; default : 3; } (x + 1) ", + "var x := 2; (x + 1) [*] { case x > 1 : 1; case x < 3 : 2; } ", + "var x := 2; [*] { case x > 1 : 1; case x < 3 : 2; } (x + 1) ", + "var x := 2; for (var i := 0; i < 2; i += 1) { return [i] 1; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { 1 return [i]; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { return [i] i; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { i return [i]; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { return [i] 1 + i; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { 1 + i return [i]; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { return [i] i + 1; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { i + 1 return [i]; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { 1 if (i > 3) return [i]; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { if (i > 3) return [i] 1; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { x if (i > 3) return [i]; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { if (i > 3) return [i] x; } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { x + 1 if (i > 3) return [i]; }", + "var x := 2; for (var i := 0; i < 2; i += 1) { if (i > 3) return [i] x + 1; }", + "var x := 2; for (var i := 0; i < 2; i += 1) { 1 + x if (i > 3) return [i]; }", + "var x := 2; for (var i := 0; i < 2; i += 1) { if (i > 3) return [i] 1 + x; }", + "var x := 2; for (var i := 0; i < 2; i += 1) { 1 for (var j := 0; j < 2; j += 1){} } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { for (var j := 0; j < 2; j += 1){} 1 } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { x for (var j := 0; j < 2; j += 1){} } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { for (var j := 0; j < 2; j += 1){} x } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { x + 1 for (var j := 0; j < 2; j += 1){} } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { for (var j := 0; j < 2; j += 1){} x + 1 } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { 1 + x for (var j := 0; j < 2; j += 1){} } ", + "var x := 2; for (var i := 0; i < 2; i += 1) { for (var j := 0; j < 2; j += 1){} 1 + x } " + }; + + const std::size_t expressions_size = sizeof(invalid_expressions) / sizeof(std::string); + + static const std::size_t compile_options = + settings_t::e_replacer + + settings_t::e_joiner + + settings_t::e_numeric_check + + settings_t::e_bracket_check + + settings_t::e_sequence_check + + settings_t::e_strength_reduction; + + const settings_t settings(compile_options); + parser_t parser(settings); + + T a = T(2222); + T b = T(3333); + T c = T(4444); + + symbol_table_t symbol_table; + symbol_table.add_variable("a", a); + symbol_table.add_variable("b", b); + symbol_table.add_variable("c", c); + + bool error_found = false; + + for (std::size_t e = 0; e < expressions_size; ++e) + { + const std::string& expression_string = invalid_expressions[e]; + + expression_t expression; + expression.register_symbol_table(symbol_table); + + if (parser.compile(expression_string,expression)) + { + printf("run_test21() - Expected compilation error for expression: %s\n", + expression_string.c_str()); + error_found = true; + continue; + } + + expression.value(); + } + + if (error_found) + { + return false; + } + } + + { + const std::string expressions[] = + { + // conditional_vector_node + "var x := 2; sum(if (x > 1) { vv8 } else { vv7 }) == sum(vv8)", + "var x := 2; sum(if (x > 1) { vv8 + 1 } else { vv8 + 2 }) == sum(vv8 + 1)", + + // unary_vector_node + "var v[8] := {1,1,1,1,1,1,1,1}; vv8 += 1; sgn(vv8) == v", + "abs(-1 * vv8) == vv8", + "abs(vv8 * -1) == vv8", + "var x := -1; abs(x * vv8) == vv8", + "var x := -1; abs(vv8 * x) == vv8", + "var x := 1; abs(-x * vv8) == vv8", + "var x := 1; abs(vv8 * -x) == vv8", + "var x := -2; abs(x * vv8) == 2vv8", + "var x := -2; abs(vv8 * x) == 2vv8", + "var x := 2; abs(-x * vv8) == 2vv8", + "var x := 2; abs(vv8 * -x) == 2vv8", + "var x := -2; abs(x * vv8) == -x * vv8", + "var x := -2; abs(vv8 * x) == -x * vv8", + "var x := 2; abs(-x * vv8) == x * vv8", + "var x := 2; abs(vv8 * -x) == x * vv8", + "var x := -2; abs(x * vv8) == vv8 * -x", + "var x := -2; abs(vv8 * x) == vv8 * -x", + "var x := 2; abs(-x * vv8) == vv8 * x", + "var x := 2; abs(vv8 * -x) == vv8 * x", + "var x := -2; abs(x * vv8) == abs(x) * vv8", + "var x := -2; abs(vv8 * x) == abs(x) * vv8", + "var x := -2; abs(x * vv8) == vv8 * abs(x)", + "var x := -2; abs(vv8 * x) == vv8 * abs(x)", + + // vec_binop_vecval_node and vec_binop_valvec_node + "var v[8] := {1,2,3,4,5,6,7,8}; var x := 1; (vv8 + x) == v", + "var v[7] := {1,2,3,4,5,6,7}; var x := 1; (vv8 + x) == v", + "var v[6] := {1,2,3,4,5,6}; var x := 1; (vv8 + x) == v", + "var v[5] := {1,2,3,4,5}; var x := 1; (vv8 + x) == v", + "var v[4] := {1,2,3,4}; var x := 1; (vv8 + x) == v", + "var v[3] := {1,2,3}; var x := 1; (vv8 + x) == v", + "var v[2] := {1,2}; var x := 1; (vv8 + x) == v", + "var v[1] := {1}; var x := 1; (vv8 + x) == v", + "var v[8] := {1,2,3,4,5,6,7,8}; var x := 1; (x + vv8) == v", + "var v[7] := {1,2,3,4,5,6,7}; var x := 1; (x + vv8) == v", + "var v[6] := {1,2,3,4,5,6}; var x := 1; (x + vv8) == v", + "var v[5] := {1,2,3,4,5}; var x := 1; (x + vv8) == v", + "var v[4] := {1,2,3,4}; var x := 1; (x + vv8) == v", + "var v[3] := {1,2,3}; var x := 1; (x + vv8) == v", + "var v[2] := {1,2}; var x := 1; (x + vv8) == v", + "var v[1] := {1}; var x := 1; (x + vv8) == v", + + // vec_binop_vecvec_node + "var v[8] := [-1]; v < vv8", + "var v[7] := [-1]; v < vv8", + "var v[3] := [-1]; v < vv8", + "var v[2] := [-1]; v < vv8", + "var v[1] := [-1]; v < vv8", + + // assignment_vecvec_op_node + "var vv8sum := sum(vv8); vv8 += (vv8 + 1); sum(vv8) == (2 * sum(vv8sum) + vv8[] * 1)", + "var vv8sum := sum(vv8); vv8 += (vv8 - 1); sum(vv8) == (2 * sum(vv8sum) - vv8[] * 1)", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 + x); sum(vv8) == (2 * sum(vv8sum) + vv8[] * 1)", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 - x); sum(vv8) == (2 * sum(vv8sum) - vv8[] * 1)", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 + (vv8 + x)); sum(vv8) == (3 * sum(vv8sum) + vv8[] * 1)", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 + (vv8 - x)); sum(vv8) == (3 * sum(vv8sum) - vv8[] * 1)", + "var vv8sum := sum(vv8); vv8 += (vv8 += 1); sum(vv8) == (2 * vv8sum + 2 * (vv8[] * 1))", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 += x); sum(vv8) == (2 * vv8sum + 2 * (vv8[] * x))", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 -= x); sum(vv8) == (2 * vv8sum - 2 * (vv8[] * x))", + "var vv8sum := sum(vv8); vv8 += (vv8 + 1); sum(vv8) == (2 * sum(vv8sum) + vv8[] * 1);", + "var vv8sum := sum(vv8); vv8 += (vv8 - 1); sum(vv8) == (2 * sum(vv8sum) - vv8[] * 1);", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 + x); sum(vv8) == (2 * sum(vv8sum) + vv8[] * 1);", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 - x); sum(vv8) == (2 * sum(vv8sum) - vv8[] * 1);", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 + (vv8 + x)); sum(vv8) == (3 * sum(vv8sum) + vv8[] * 1);", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 + (vv8 - x)); sum(vv8) == (3 * sum(vv8sum) - vv8[] * 1);", + "var vv8sum := sum(vv8); vv8 += (vv8 += 1); sum(vv8) == (2 * vv8sum + 2 * (vv8[] * 1));", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 += x); sum(vv8) == (2 * vv8sum + 2 * (vv8[] * x));", + "var vv8sum := sum(vv8); var x := 1; vv8 += (vv8 -= x); sum(vv8) == (2 * vv8sum - 2 * (vv8[] * x));", + "var vv3sum := sum(vv3); vv3 += (vv3 + 1); sum(vv3) == (2 * sum(vv3sum) + vv3[] * 1)", + "var vv3sum := sum(vv3); vv3 += (vv3 - 1); sum(vv3) == (2 * sum(vv3sum) - vv3[] * 1)", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 + x); sum(vv3) == (2 * sum(vv3sum) + vv3[] * 1)", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 - x); sum(vv3) == (2 * sum(vv3sum) - vv3[] * 1)", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 + (vv3 + x)); sum(vv3) == (3 * sum(vv3sum) + vv3[] * 1)", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 + (vv3 - x)); sum(vv3) == (3 * sum(vv3sum) - vv3[] * 1)", + "var vv3sum := sum(vv3); vv3 += (vv3 += 1); sum(vv3) == (2 * vv3sum + 2 * (vv3[] * 1))", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 += x); sum(vv3) == (2 * vv3sum + 2 * (vv3[] * x))", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 -= x); sum(vv3) == (2 * vv3sum - 2 * (vv3[] * x))", + "var vv3sum := sum(vv3); vv3 += (vv3 + 1); sum(vv3) == (2 * sum(vv3sum) + vv3[] * 1);", + "var vv3sum := sum(vv3); vv3 += (vv3 - 1); sum(vv3) == (2 * sum(vv3sum) - vv3[] * 1);", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 + x); sum(vv3) == (2 * sum(vv3sum) + vv3[] * 1);", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 - x); sum(vv3) == (2 * sum(vv3sum) - vv3[] * 1);", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 + (vv3 + x)); sum(vv3) == (3 * sum(vv3sum) + vv3[] * 1);", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 + (vv3 - x)); sum(vv3) == (3 * sum(vv3sum) - vv3[] * 1);", + "var vv3sum := sum(vv3); vv3 += (vv3 += 1); sum(vv3) == (2 * vv3sum + 2 * (vv3[] * 1));", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 += x); sum(vv3) == (2 * vv3sum + 2 * (vv3[] * x));", + "var vv3sum := sum(vv3); var x := 1; vv3 += (vv3 -= x); sum(vv3) == (2 * vv3sum - 2 * (vv3[] * x));", + + // assignment_vec_op_node + "var vv8sum := sum(vv8); vv8 += 1; sum(vv8) == (vv8sum + vv8[] * 1)", + "var vv7sum := sum(vv7); vv7 += 1; sum(vv7) == (vv7sum + vv7[] * 1)", + "var vv6sum := sum(vv6); vv6 += 1; sum(vv6) == (vv6sum + vv6[] * 1)", + "var vv5sum := sum(vv5); vv5 += 1; sum(vv5) == (vv5sum + vv5[] * 1)", + "var vv4sum := sum(vv4); vv4 += 1; sum(vv4) == (vv4sum + vv4[] * 1)", + "var vv3sum := sum(vv3); vv3 += 1; sum(vv3) == (vv3sum + vv3[] * 1)", + "var vv2sum := sum(vv2); vv2 += 1; sum(vv2) == (vv2sum + vv2[] * 1)", + "var vv1sum := sum(vv1); vv1 += 1; sum(vv1) == (vv1sum + vv1[] * 1)", + "var vv8sum := sum(vv8); var x := 7; vv8 += (x - 1) / 2; sum(vv8) == (vv8sum + vv8[] * 3)", + "var vv7sum := sum(vv7); var x := 7; vv7 += (x - 1) / 2; sum(vv7) == (vv7sum + vv7[] * 3)", + "var vv6sum := sum(vv6); var x := 7; vv6 += (x - 1) / 2; sum(vv6) == (vv6sum + vv6[] * 3)", + "var vv5sum := sum(vv5); var x := 7; vv5 += (x - 1) / 2; sum(vv5) == (vv5sum + vv5[] * 3)", + "var vv4sum := sum(vv4); var x := 7; vv4 += (x - 1) / 2; sum(vv4) == (vv4sum + vv4[] * 3)", + "var vv3sum := sum(vv3); var x := 7; vv3 += (x - 1) / 2; sum(vv3) == (vv3sum + vv3[] * 3)", + "var vv2sum := sum(vv2); var x := 7; vv2 += (x - 1) / 2; sum(vv2) == (vv2sum + vv2[] * 3)", + "var vv1sum := sum(vv1); var x := 7; vv1 += (x - 1) / 2; sum(vv1) == (vv1sum + vv1[] * 3)", + + // assignment_vecvec_node + "var v[8] := [-1]; vv8 := v; sum(vv8) == (-1 * 8 + 0)", + "var v[7] := [-1]; vv8 := v; sum(vv8) == (-1 * 7 + (7))", + "var v[6] := [-1]; vv8 := v; sum(vv8) == (-1 * 6 + (6+7))", + "var v[5] := [-1]; vv8 := v; sum(vv8) == (-1 * 5 + (5+6+7))", + "var v[4] := [-1]; vv8 := v; sum(vv8) == (-1 * 4 + (4+5+6+7))", + "var v[3] := [-1]; vv8 := v; sum(vv8) == (-1 * 3 + (3+4+5+6+7))", + "var v[2] := [-1]; vv8 := v; sum(vv8) == (-1 * 2 + (2+3+4+5+6+7))", + "var v[1] := [-1]; vv8 := v; sum(vv8) == (-1 * 1 + (1+2+3+4+5+6+7))", + "var v[8] := [-1]; vv8 := v; var x[8] := { -1, -1, -1, -1, -1, -1, -1, -1 }; x == vv8", + "var v[7] := [-1]; vv8 := v; var x[8] := { -1, -1, -1, -1, -1, -1, -1, 7 }; x == vv8", + "var v[6] := [-1]; vv8 := v; var x[8] := { -1, -1, -1, -1, -1, -1, 6, 7 }; x == vv8", + "var v[5] := [-1]; vv8 := v; var x[8] := { -1, -1, -1, -1, -1, 5, 6, 7 }; x == vv8", + "var v[4] := [-1]; vv8 := v; var x[8] := { -1, -1, -1, -1, 4, 5, 6, 7 }; x == vv8", + "var v[3] := [-1]; vv8 := v; var x[8] := { -1, -1, -1, 3, 4, 5, 6, 7 }; x == vv8", + "var v[2] := [-1]; vv8 := v; var x[8] := { -1, -1, 2, 3, 4, 5, 6, 7 }; x == vv8", + "var v[1] := [-1]; vv8 := v; var x[8] := { -1, 1, 2, 3, 4, 5, 6, 7 }; x == vv8", + "var v[3] := [-1]; vv3 := v; sum(vv3) == (-1 * 3 + (0))", + "var v[2] := [-1]; vv3 := v; sum(vv3) == (-1 * 2 + (2))", + "var v[1] := [-1]; vv3 := v; sum(vv3) == (-1 * 1 + (1+2))", + "var v[3] := [-1]; vv3 := v; var x[3] := { -1, -1, -1}; x == vv3", + "var v[2] := [-1]; vv3 := v; var x[3] := { -1, -1, 2}; x == vv3", + "var v[1] := [-1]; vv3 := v; var x[3] := { -1, 1, 2}; x == vv3", + "vv8 := vv7; sum(vv8) == (sum(vv7) + 7)", + "vv8 := vv6; sum(vv8) == (sum(vv6) + 6+ 7)", + "vv8 := vv5; sum(vv8) == (sum(vv5) + 5 + 6 + 7)", + "vv8 := vv4; sum(vv8) == (sum(vv4) + 4 + 5 + 6 + 7)", + "vv8 := vv3; sum(vv8) == (sum(vv3) + 3 + 4 + 5 + 6 + 7)", + "vv8 := vv2; sum(vv8) == (sum(vv2) + 2 + 3 + 4 + 5 + 6 + 7)", + "vv8 := vv1; sum(vv8) == (sum(vv1) + 1 + 2 + 3 + 4 + 5 + 6 + 7)", + "vv8 := vv7 + vv7; sum(vv8) == (2 * sum(vv7) + 7)", + "vv8 := vv6 + vv6; sum(vv8) == (2 * sum(vv6) + 6+ 7)", + "vv8 := vv5 + vv5; sum(vv8) == (2 * sum(vv5) + 5 + 6 + 7)", + "vv8 := vv4 + vv4; sum(vv8) == (2 * sum(vv4) + 4 + 5 + 6 + 7)", + "vv8 := vv3 + vv3; sum(vv8) == (2 * sum(vv3) + 3 + 4 + 5 + 6 + 7)", + "vv8 := vv2 + vv2; sum(vv8) == (2 * sum(vv2) + 2 + 3 + 4 + 5 + 6 + 7)", + "vv8 := vv1 + vv1; sum(vv8) == (2 * sum(vv1) + 1 + 2 + 3 + 4 + 5 + 6 + 7)", + + // assignment_vec_node + "var x := 3; vv8 := 2*x+1; sum(vv8) == (vv8[] * 7)", + "var x := 3; vv7 := 2*x+1; sum(vv7) == (vv7[] * 7)", + "var x := 3; vv6 := 2*x+1; sum(vv6) == (vv6[] * 7)", + "var x := 3; vv5 := 2*x+1; sum(vv5) == (vv5[] * 7)", + "var x := 3; vv4 := 2*x+1; sum(vv4) == (vv4[] * 7)", + "var x := 3; vv3 := 2*x+1; sum(vv3) == (vv3[] * 7)", + "var x := 3; vv2 := 2*x+1; sum(vv2) == (vv2[] * 7)", + "var x := 3; vv1 := 2*x+1; sum(vv1) == (vv1[] * 7)", + "var x[3] := [3]; vv8 := 2x[0]+1; sum(vv8) == (vv8[] * 7)", + "var x[3] := [3]; vv7 := 2x[1]+1; sum(vv7) == (vv7[] * 7)", + "var x[3] := [3]; vv6 := 2x[2]+1; sum(vv6) == (vv6[] * 7)", + "var x[3] := [3]; vv5 := 2x[0]+1; sum(vv5) == (vv5[] * 7)", + "var x[3] := [3]; vv4 := 2x[1]+1; sum(vv4) == (vv4[] * 7)", + "var x[3] := [3]; vv3 := 2x[2]+1; sum(vv3) == (vv3[] * 7)", + "var x[3] := [3]; vv2 := 2x[0]+1; sum(vv2) == (vv2[] * 7)", + "var x[3] := [3]; vv1 := 2x[1]+1; sum(vv1) == (vv1[] * 7)", + "var x[3] := [3]; var y[3] := [1]; vv8 := 2x[0]+y[0]; sum(vv8) == (vv8[] * 7)", + "var x[3] := [3]; var y[3] := [1]; vv7 := 2x[1]+y[1]; sum(vv7) == (vv7[] * 7)", + "var x[3] := [3]; var y[3] := [1]; vv6 := 2x[2]+y[2]; sum(vv6) == (vv6[] * 7)", + "var x[3] := [3]; var y[3] := [1]; vv5 := 2x[0]+y[0]; sum(vv5) == (vv5[] * 7)", + "var x[3] := [3]; var y[3] := [1]; vv4 := 2x[1]+y[1]; sum(vv4) == (vv4[] * 7)", + "var x[3] := [3]; var y[3] := [1]; vv3 := 2x[2]+y[2]; sum(vv3) == (vv3[] * 7)", + "var x[3] := [3]; var y[3] := [1]; vv2 := 2x[0]+y[0]; sum(vv2) == (vv2[] * 7)", + "var x[3] := [3]; var y[3] := [1]; vv1 := 2x[1]+y[1]; sum(vv1) == (vv1[] * 7)", + + // swap vec vec node + "var v[8] := [-1]; vv8 <=> v; sum(vv8) == (-1 * 8 + 0)", + "var v[7] := [-1]; vv8 <=> v; sum(vv8) == (-1 * 7 + (7))", + "var v[6] := [-1]; vv8 <=> v; sum(vv8) == (-1 * 6 + (6+7))", + "var v[5] := [-1]; vv8 <=> v; sum(vv8) == (-1 * 5 + (5+6+7))", + "var v[4] := [-1]; vv8 <=> v; sum(vv8) == (-1 * 4 + (4+5+6+7))", + "var v[3] := [-1]; vv8 <=> v; sum(vv8) == (-1 * 3 + (3+4+5+6+7))", + "var v[2] := [-1]; vv8 <=> v; sum(vv8) == (-1 * 2 + (2+3+4+5+6+7))", + "var v[1] := [-1]; vv8 <=> v; sum(vv8) == (-1 * 1 + (1+2+3+4+5+6+7))", + "var v[8] := [-1]; vv8 <=> v; var x[8] := { -1, -1, -1, -1, -1, -1, -1, -1 }; x == vv8", + "var v[7] := [-1]; vv8 <=> v; var x[8] := { -1, -1, -1, -1, -1, -1, -1, 7 }; x == vv8", + "var v[6] := [-1]; vv8 <=> v; var x[8] := { -1, -1, -1, -1, -1, -1, 6, 7 }; x == vv8", + "var v[5] := [-1]; vv8 <=> v; var x[8] := { -1, -1, -1, -1, -1, 5, 6, 7 }; x == vv8", + "var v[4] := [-1]; vv8 <=> v; var x[8] := { -1, -1, -1, -1, 4, 5, 6, 7 }; x == vv8", + "var v[3] := [-1]; vv8 <=> v; var x[8] := { -1, -1, -1, 3, 4, 5, 6, 7 }; x == vv8", + "var v[2] := [-1]; vv8 <=> v; var x[8] := { -1, -1, 2, 3, 4, 5, 6, 7 }; x == vv8", + "var v[1] := [-1]; vv8 <=> v; var x[8] := { -1, 1, 2, 3, 4, 5, 6, 7 }; x == vv8", + "var v[3] := [-1]; vv3 <=> v; sum(vv3) == (-1 * 3 + (0))", + "var v[2] := [-1]; vv3 <=> v; sum(vv3) == (-1 * 2 + (2))", + "var v[1] := [-1]; vv3 <=> v; sum(vv3) == (-1 * 1 + (1+2))", + "var v[3] := [-1]; vv3 <=> v; var x[3] := { -1, -1, -1}; x == vv3", + "var v[2] := [-1]; vv3 <=> v; var x[3] := { -1, -1, 2}; x == vv3", + "var v[1] := [-1]; vv3 <=> v; var x[3] := { -1, 1, 2}; x == vv3", + + // rebasevector_elem_node + "vv8[0] == 0", + "vv8[2 - 2] == 0", + "vv8[vv8[] - 1] == vv8[] - 1", + "var vec_sum := 0; for (var i := 0; i < vv8[]; i +=1) { vec_sum += vv8[i]; }; vec_sum == (vv8[] - 1) * vv8[] / 2", + "var vec_sum := 0; for (var i := 0; i < vv8[]; i +=1) { vec_sum += vv8[2i / 2]; }; vec_sum == (vv8[] - 1) * vv8[] / 2", + "var x:= 1; var y:= 1; (vv8 + x)[y / x] == 2", + "var x:= 1; var y:= 1; (vv8 + x - y)[y / x] == 1", + "var x:= 1; (x + vv8)[1] == 2", + "var x:= 1; var y:= 1; (x + vv8)[y / x] == 2", + "var x:= 1; var y:= 1; (x + vv8 - y)[y / x] == 1", + "var successes := 0; for(var i:=0; i < vv8[]; i += 1) { successes += (vv8 + 1)[i] == i + 1; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (vv8 + x)[i] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (x + vv8)[i] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (vv8 + x)[i / x] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (x + vv8)[i / x] == i + x; }; successes == vv8[]", + "(1 + vv8)[1] == 2", + "(vv8 + 1)[1] == 2", + "(vv8 + 1)[2 / 2] == 2", + "(1 + vv8)[2 / 2] == 2", + "var x:= 1; (x + vv8)[1] == 2", + "var x:= 1; (vv8 + x)[1] == 2", + "var x:= 1; var y:= 1; (x + vv8)[y] == 2", + "var x:= 1; var y:= 1; (vv8 + x)[y] == 2", + "var x:= 1; var y:= 1; (vv8 + x)[y / x] == 2", + "var x:= 1; var y:= 1; (vv8 + x - y)[y / x] == 1", + "var x:= 1; var y:= 1; (x + vv8)[y / x] == 2", + "var x:= 1; var y:= 1; (x + vv8 - y)[y / x] == 1", + "(abs(vv8 + 1))[1] == 2", + "(abs(1 + vv8))[1] == 2", + "(abs(vv8 + 1))[2 / 2] == 2", + "(abs(1 + vv8))[2 / 2] == 2", + "(abs(vv8 + 1)/2)[1] == 1", + "(abs(1 + vv8)/2)[1] == 1", + "(abs(vv8 + 1)/2)[2 / 2] == 1", + "(abs(1 + vv8)/2)[2 / 2] == 1", + "(abs(abs(vv8 + 1)) - 1)[1] == 1", + "(abs(2 * abs(vv8 + 1)) - 1)[1] == 3", + "(abs(abs(vv8 + 1) * 2) - 1)[1] == 3", + "(abs(2abs(vv8 + 1)) - 1)[1] == 3", + "(abs(abs(vv8 + 1)2) - 1)[1] == 3", + "var x:= 1; (abs(x + vv8))[1] == 2", + "var x:= 1; (abs(vv8 + x))[1] == 2", + "var x:= 1; var y:= 1; (abs(x + vv8))[y] == 2", + "var x:= 1; var y:= 1; (abs(vv8 + x))[y] == 2", + "var x:= 1; var y:= 1; (abs(vv8 + x))[y / x] == 2", + "var x:= 1; var y:= 1; (abs(vv8 + x - y))[y / x] == 1", + "var x:= 1; var y:= 1; (abs(x + vv8))[y / x] == 2", + "var x:= 1; var y:= 1; (abs(x + vv8 - y))[y / x] == 1", + "var x:= 1; (abs(x + vv8)/2)[1] == 1", + "var x:= 1; (abs(vv8 + x)/2)[1] == 1", + "var x:= 1; var y:= 1; (abs(x + vv8)/2)[y] == 1", + "var x:= 1; var y:= 1; (abs(vv8 + x)/2)[y] == 1", + "var x:= 1; var y:= 1; (abs(vv8 + x)/2)[y / x] == 1", + "var x:= 1; var y:= 1; (abs(x + vv8)/2)[y / x] == 1", + "var x := 1; (abs(abs(vv8 + x)) - x)[1] == 1", + "var x := 1; (abs(2 * abs(vv8 + x)) - x)[1] == 3", + "var x := 1; (abs(abs(vv8 + x) * 2) - x)[1] == 3", + "var x := 1; (abs(2abs(vv8 + x)) - x)[1] == 3", + "var x := 1; (abs(abs(vv8 + x)2) - x)[1] == 3", + "var x := 1; var y := 1; (abs(abs(vv8 + x)) - x)[y] == 1", + "var x := 1; var y := 1; (abs(2 * abs(vv8 + x)) - x)[y] == 3", + "var x := 1; var y := 1; (abs(abs(vv8 + x) * 2) - x)[y] == 3", + "var x := 1; var y := 1; (abs(2abs(vv8 + x)) - x)[y] == 3", + "var x := 1; var y := 1; (abs(abs(vv8 + x)2) - x)[y] == 3", + "var x := 1; var y := 1; (abs(abs(vv8 + x)) - x)[x / y] == 1", + "var x := 1; var y := 1; (abs(2 * abs(vv8 + x)) - x)[x / y] == 3", + "var x := 1; var y := 1; (abs(abs(vv8 + x) * 2) - x)[x / y] == 3", + "var x := 1; var y := 1; (abs(2abs(vv8 + x)) - x)[x / y] == 3", + "var x := 1; var y := 1; (abs(abs(vv8 + x)2) - x)[x / y] == 3", + "var successes := 0; for(var i:=0; i < vv8[]; i += 1) { successes += (vv8 + 1)[i] == i + 1; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (vv8 + x)[i] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (x + vv8)[i] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (vv8 + x)[i / x] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (x + vv8)[i / x] == i + x; }; successes == vv8[]", + "var successes := 0; for(var i:=0; i < vv8[]; i += 1) { successes += (abs(vv8 + 1))[i] == i + 1; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (abs(vv8 + x))[i] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (abs(x + vv8))[i] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (abs(vv8 + x))[i / x] == i + x; }; successes == vv8[]", + "var successes := 0; var x := 1 ; for(var i:=0; i < vv8[]; i += 1) { successes += (abs(x + vv8))[i / x] == i + x; }; successes == vv8[]", + }; + + bool error_found = false; + + for (std::size_t e = 0; e < sizeof(expressions)/sizeof(std::string); ++e) + { + T vs8[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + T vs7[] = { 0, 1, 2, 3, 4, 5, 6 }; + T vs6[] = { 0, 1, 2, 3, 4, 5 }; + T vs5[] = { 0, 1, 2, 3, 4 }; + T vs4[] = { 0, 1, 2, 3 }; + T vs3[] = { 0, 1, 2 }; + T vs2[] = { 0, 1 }; + T vs1[] = { 0 }; + + exprtk::vector_view vv1 = exprtk::make_vector_view(vs1, 1); + exprtk::vector_view vv2 = exprtk::make_vector_view(vs2, 2); + exprtk::vector_view vv3 = exprtk::make_vector_view(vs3, 3); + exprtk::vector_view vv4 = exprtk::make_vector_view(vs4, 4); + exprtk::vector_view vv5 = exprtk::make_vector_view(vs5, 5); + exprtk::vector_view vv6 = exprtk::make_vector_view(vs6, 6); + exprtk::vector_view vv7 = exprtk::make_vector_view(vs7, 7); + exprtk::vector_view vv8 = exprtk::make_vector_view(vs8, 8); + + symbol_table_t symbol_table; + + symbol_table.add_vector("vv1", vv1); + symbol_table.add_vector("vv2", vv2); + symbol_table.add_vector("vv3", vv3); + symbol_table.add_vector("vv4", vv4); + symbol_table.add_vector("vv5", vv5); + symbol_table.add_vector("vv6", vv6); + symbol_table.add_vector("vv7", vv7); + symbol_table.add_vector("vv8", vv8); + + parser_t parser; + + const std::string& expression_string = expressions[e]; + expression_t expression; + expression.register_symbol_table(symbol_table); + + if (!parser.compile(expression_string,expression)) + { + printf("run_test21() - vector_veiw expression compilation error. Expression: %s\n", + expression_string.c_str()); + + for (std::size_t i = 0; i < parser.error_count(); ++i) + { + error_type error = parser.get_error(i); + exprtk::parser_error::update_error(error,expression_string); + + printf("run_test21() - Exp[%02d] Error[%02d] Position: %02d line: %d column: %d Type: [%14s] Msg: %s\n", + static_cast(e), + static_cast(i), + static_cast(error.token.position), + static_cast(error.line_no), + static_cast(error.column_no), + exprtk::parser_error::to_str(error.mode).c_str(), + error.diagnostic.c_str()); + } + + error_found = true; + + continue; + } + + const T result = expression.value(); + + if (result != T(1.0)) + { + error_found = true; + + printf("run_test21() - Error: Exp[%02d] Expression result: %5.3f expected: 1 expression: %s\n", + static_cast(e), + result, + expression_string.c_str()); + } + } + + if (error_found) + { + return false; + } + } + + { + const std::string expressions[] = + { + "vv0[] == vv0_size", + "sum(vv0) == (vv0[] * (vv0[] + 1) / 2) and (vv0[] == vv0_size)", + "(min(vv0) == 1) and (vv0[] == vv0_size)", + "(max(vv0) == vv0[]) and (vv0[] == vv0_size)", + "(avg(vv0) == (min(vv0) + max(vv0)) / 2) and (vv0[] == vv0_size)", + "(sum(vv0 + 1) == (vv0[] * (vv0[] + 1) / 2 + (vv0[] * 1))) and (vv0[] == vv0_size)", + "(sum(vv0 - 1) == (vv0[] * (vv0[] + 1) / 2 - (vv0[] * 1))) and (vv0[] == vv0_size)", + "(sum(1 + vv0) == (vv0[] * (vv0[] + 1) / 2 + (vv0[] * 1))) and (vv0[] == vv0_size)", + "(sum(-1 + vv0) == (vv0[] * (vv0[] + 1) / 2 - (vv0[] * 1))) and (vv0[] == vv0_size)", + "var x:= 1; sum(vv0 + x) == (vv0[] * (vv0[] + 1) / 2 + (vv0[] * x)) and (vv0[] == vv0_size)", + "var x:= 1; sum(vv0 - x) == (vv0[] * (vv0[] + 1) / 2 - (vv0[] * x)) and (vv0[] == vv0_size)", + "sum(2vv0) == (vv0[] * (vv0[] + 1)) and (vv0[] == vv0_size)", + "sum(vv0 * 2) == (vv0[] * (vv0[] + 1)) and (vv0[] == vv0_size)", + "sum(2vv0 + 1) == (vv0[] * (vv0[] + 1) + vv0[]) and (vv0[] == vv0_size)", + "sum(1 + 2vv0) == (vv0[] * (vv0[] + 1) + vv0[]) and (vv0[] == vv0_size)", + "var x := 1; sum(2vv0 + x) == (vv0[] * (vv0[] + 1) + x * vv0[]) and (vv0[] == vv0_size)", + "var x := 1; sum(x + 2vv0) == (vv0[] * (vv0[] + 1) + x * vv0[]) and (vv0[] == vv0_size)", + "sum(vv0 += 1) == (vv0[] * (vv0[] + 1) / 2 + vv0[]) and (vv0[] == vv0_size)", + "var x:= 1; sum(vv0 += x) == (vv0[] * (vv0[] + 1) / 2 + x * vv0[]) and (vv0[] == vv0_size)", + "var x:= 1; sum(vv0 -= x) == (vv0[] * (vv0[] + 1 - 2x) / 2) and (vv0[] == vv0_size)", + "(sum(2vv0) == 2 * sum(vv0)) and (vv0[] == vv0_size)", + "(sum(vv0 * 2) == 2 * sum(vv0)) and (vv0[] == vv0_size)", + "var x:= 1; sum(2vv0) == (vv0[] * (vv0[] + 1)) and (vv0[] == vv0_size)", + "var x := 2; sum(if (x > 1) { vv0 } else { vv1 }) == sum(vv0)", + "dot(2 * vv0,vv1 - 1) + dot(2 * vv0,vv1 - 1) == 2sum(2vv0 * (vv1 - 1))", + "(0 * dot(2 * vv0,vv1 - 1)) == 0" + }; + + bool error_found = false; + + for (std::size_t e = 0; e < sizeof(expressions) / sizeof(std::string); ++e) + { + const T vanilla[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + const std::size_t vanilla_size = sizeof(vanilla) / sizeof(T); + + std::vector v0(vanilla, vanilla + vanilla_size); + exprtk::vector_view vv0 = exprtk::make_vector_view(v0, v0.size()); + + std::vector v1(vanilla, vanilla + vanilla_size); + exprtk::vector_view vv1 = exprtk::make_vector_view(v1, v1.size()); + + T vv0_size = T(0.0); + + symbol_table_t symbol_table; + symbol_table.add_variable("vv0_size", vv0_size); + symbol_table.add_vector ("vv0" , vv0 ); + symbol_table.add_vector ("vv1" , vv1 ); + + exprtk::rtl::vecops::package vector_package; + exprtk::rtl::io::package io_package; + + symbol_table.add_package( vector_package ); + symbol_table.add_package( io_package ); + + const std::string& expression_string = expressions[e]; + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + if (!parser.compile(expression_string, expression)) + { + printf("run_test21() - Error: %s\tExpression: %s\n", + parser.error().c_str(), + expression_string.c_str()); + + for (std::size_t i = 0; i < parser.error_count(); ++i) + { + error_type error = parser.get_error(i); + exprtk::parser_error::update_error(error,expression_string); + + printf("run_test21() - Exp[%02d] Error[%02d] Position: %02d line: %d column: %d Type: [%14s] Msg: %s\n", + static_cast(e), + static_cast(i), + static_cast(error.token.position), + static_cast(error.line_no), + static_cast(error.column_no), + exprtk::parser_error::to_str(error.mode).c_str(), + error.diagnostic.c_str()); + } + + continue; + } + + for (std::size_t i = 1; i <= vv0.base_size(); ++i) + { + v0.assign(vanilla, vanilla + vanilla_size); + v1.assign(vanilla, vanilla + vanilla_size); + + vv0_size = T(i); + vv0.set_size(i); + + const T result = expression.value(); + + if (result != 1) + { + printf("run_test21() - Exp[%02d] Error: size: %d expected 1 instead got: %f expr:%s\n", + static_cast(e), + static_cast(i), + result, + expression_string.c_str()); + } + } + + vv1.rebase(v0.data()); + vv0.rebase(v1.data()); + expression.value(); + + vv0.rebase(v0.data()); + vv1.rebase(v1.data()); + expression.value(); + + expression.release(); + } + + if (error_found) + { + return false; + } + } + + { + const T vanilla[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + const std::size_t vanilla_size = sizeof(vanilla) / sizeof(T); + + std::vector v0(vanilla, vanilla + vanilla_size); + std::vector v1(vanilla, vanilla + vanilla_size); + + exprtk::vector_view vv = exprtk::make_vector_view(v0, v0.size()); + + vv_size_handler_t vv_size_handler; + vv_size_handler.register_vector_view(vv); + + symbol_table_t symbol_table; + symbol_table.add_vector("v", vv); + + exprtk::rtl::vecops::package vector_package; + exprtk::rtl::io::package io_package; + + symbol_table.add_package( vector_package ); + symbol_table.add_package( io_package ); + symbol_table.add_function("resize", vv_size_handler); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + const std::string resize_expression = + " var vec_original_size := v[]; " + " var success_count := 0; " + " " + " for (var i := 1; i <= vec_original_size; i += 1) " + " { " + " if (resize(v,i) == true and v[] == i) " + " { " + " success_count += 1; " + " } " + " }; " + " " + " success_count == vec_original_size "; + + if (!parser.compile(resize_expression, expression)) + { + printf("run_test21() - Error: %s\tExpression: %s\n", + parser.error().c_str(), + resize_expression.c_str()); + + for (std::size_t i = 0; i < parser.error_count(); ++i) + { + error_type error = parser.get_error(i); + exprtk::parser_error::update_error(error,resize_expression); + + printf("run_test21() - Error[%02d] Position: %02d line: %d column: %d Type: [%14s] Msg: %s\n", + static_cast(i), + static_cast(error.token.position), + static_cast(error.line_no), + static_cast(error.column_no), + exprtk::parser_error::to_str(error.mode).c_str(), + error.diagnostic.c_str()); + } + + return false; + } + + const T value0 = expression.value(); + + if (expression.value() != T(1)) + { + printf("run_test21() - Error: Failed evaluation Expected 1 got: %f (1)\n", value0); + } + + vv.rebase(v1.data()); + vv_size_handler.register_vector_view(vv); + + const T value1 = expression.value(); + + if (expression.value() != T(1)) + { + printf("run_test21() - Error: Failed evaluation Expected 1 got: %f (1)\n", value1); + } + + vv.rebase(v0.data()); + vv_size_handler.register_vector_view(vv); + + expression.release(); + } + + { + const T vanilla[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + const std::size_t vanilla_size = sizeof(vanilla) / sizeof(T); + + std::vector v0(vanilla, vanilla + vanilla_size); + std::vector v1(vanilla, vanilla + vanilla_size); + + exprtk::vector_view vv = exprtk::make_vector_view(v0, v0.size()); + + vv_size_handler_t vv_size_handler; + vv_size_handler.register_vector_view(vv); + + symbol_table_t symbol_table; + symbol_table.add_vector("v", vv); + + exprtk::rtl::vecops::package vector_package; + exprtk::rtl::io::package io_package; + + symbol_table.add_package( vector_package ); + symbol_table.add_package( io_package ); + symbol_table.add_function("resize", vv_size_handler); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + const std::string resize_expression = + " var vec_original_size := v[]; " + " var failure_count := 0; " + " " + " for (var i := vec_original_size + 1; i <= 2 * vec_original_size; i += 1) " + " { " + " if (resize(v,i) == false or v[] != i) " + " { " + " failure_count += 1 " + " } " + " }; " + " " + " failure_count == vec_original_size "; + + if (!parser.compile(resize_expression, expression)) + { + printf("run_test21() - Error: %s\tExpression: %s\n", + parser.error().c_str(), + resize_expression.c_str()); + + for (std::size_t i = 0; i < parser.error_count(); ++i) + { + error_type error = parser.get_error(i); + exprtk::parser_error::update_error(error,resize_expression); + + printf("run_test21() - Error[%02d] Position: %02d line: %d column: %d Type: [%14s] Msg: %s\n", + static_cast(i), + static_cast(error.token.position), + static_cast(error.line_no), + static_cast(error.column_no), + exprtk::parser_error::to_str(error.mode).c_str(), + error.diagnostic.c_str()); + } + + return false; + } + + const T value0 = expression.value(); + + if (expression.value() != T(1)) + { + printf("run_test21() - Error: Failed evaluation Expected 1 got: %f (2)\n", value0); + } + + vv.rebase(v1.data()); + vv_size_handler.register_vector_view(vv); + + const T value1 = expression.value(); + + if (expression.value() != T(1)) + { + printf("run_test21() - Error: Failed evaluation Expected 1 got: %f (2)\n", value1); + } + + vv.rebase(v0.data()); + vv_size_handler.register_vector_view(vv); + + expression.release(); + } + + return true; +} + +struct assert_handler exprtk_test_final : public exprtk::assert_check +{ + std::size_t assert_count; + void handle_assert(const assert_context& /*context*/) exprtk_test_override + { + ++assert_count; + } +}; + +template +bool run_test22() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + bool result = true; + + { + const std::string expressions[] = + { + " assert(1 > 1); ", + " assert(1 > 2, 'assert statement 2'); ", + " assert(1 > 3, 'assert ' + 'statement 3'); ", + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); ", + " assert(1 > 5, 'assert ' + 'statement 5'); ", + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [1]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + else if (!exprtk::expression_helper::is_null(expression)) + { + printf("run_test22() - Error: Expression is not null! expression: %s [1]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + } + } + + { + const std::string expressions[] = + { + " assert(1 > 1); 1 + 0 ", + " assert(1 > 2, 'assert statement 2'); 2 + 0 ", + " assert(1 > 3, 'assert ' + 'statement 3'); 3 + 0 ", + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); 4 + 0 ", + " assert(1 > 5, 'assert ' + 'statement 5'); 5 + 0 ", + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); 6 + 0 " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [2]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + else if (!exprtk::expression_helper::is_literal(expression)) + { + printf("run_test22() - Error: Expression is not constant! expression: %s [2]\n", + expressions[i].c_str()); + continue; + } + + expression.value(); + } + } + + { + const std::string expressions[] = + { + " assert(1 > 1); " + " assert(1 > 2, 'assert statement 2'); " + " assert(1 > 3, 'assert ' + 'statement 3'); " + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); " + " assert(1 > 5, 'assert ' + 'statement 5'); " + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [3]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [3]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (6 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [3]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(1 > 1); 1 ", + " assert(1 > 2, 'assert statement 2'); 2 ", + " assert(1 > 3, 'assert ' + 'statement 3'); 3 ", + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); 4 ", + " assert(1 > 5, 'assert ' + 'statement 5'); 5 ", + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); 6 " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [4]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_literal); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [4]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (1 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [4]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(1 > 1); 1 + 0 ", + " assert(1 > 2, 'assert statement 2'); 2 + 0 ", + " assert(1 > 3, 'assert ' + 'statement 3'); 3 + 0 ", + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); 4 + 0 ", + " assert(1 > 5, 'assert ' + 'statement 5'); 5 + 0 ", + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); 6 + 0 " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [5]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_literal); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [5]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (1 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [5]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(1 > 1); 'assert statement 0001' ", + " assert(1 > 2, 'assert statement 2'); 'assert statement 0002' ", + " assert(1 > 3, 'assert ' + 'statement 3'); 'assert statement 0003' ", + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); 'assert statement 0004' ", + " assert(1 > 5, 'assert ' + 'statement 5'); 'assert statement 0005' ", + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); 'assert statement 0006' " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [6]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_string); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [6]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (1 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [6]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(1 > 1); 'assert statement' + '0001' ", + " assert(1 > 2, 'assert statement 2'); 'assert statement' + '0002' ", + " assert(1 > 3, 'assert ' + 'statement 3'); 'assert statement' + '0003' ", + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); 'assert statement' + '0004' ", + " assert(1 > 5, 'assert ' + 'statement 5'); 'assert statement' + '0005' ", + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); 'assert statement' + '0006' " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [7]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_string); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [7]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (1 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [7]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(x > y); ", + " assert(x > y, 'assert statement 2'); ", + " assert(x > y, 'assert ' + 'statement 3'); ", + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); ", + " assert(x > y, 'assert ' + 'statement 5'); ", + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [8]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + else if (!exprtk::expression_helper::is_null(expression)) + { + printf("run_test22() - Error: Expression is not null! expression: %s [8]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + } + } + + { + const std::string expressions[] = + { + " assert(x > y); 1 + 0 ", + " assert(x > y, 'assert statement 2'); 2 + 0 ", + " assert(x > y, 'assert ' + 'statement 3'); 3 + 0 ", + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); 4 + 0 ", + " assert(x > y, 'assert ' + 'statement 5'); 5 + 0 ", + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); 6 + 0 " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [9]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + else if (!exprtk::expression_helper::is_literal(expression)) + { + printf("run_test22() - Error: Expression is not constant! expression: %s [9]\n", + expressions[i].c_str()); + continue; + } + + expression.value(); + } + } + + { + const std::string expressions[] = + { + " assert(x > y); " + " assert(x > y, 'assert statement 2'); " + " assert(x > y, 'assert ' + 'statement 3'); " + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); " + " assert(x > y, 'assert ' + 'statement 5'); " + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [10]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [10]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (6 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [10]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(x > y); 1 ", + " assert(x > y, 'assert statement 2'); 2 ", + " assert(x > y, 'assert ' + 'statement 3'); 3 ", + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); 4 ", + " assert(x > y, 'assert ' + 'statement 5'); 5 ", + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); 6 " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [11]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_literal); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [11]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (1 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [11]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + + } + } + + { + const std::string expressions[] = + { + " assert(x > y); 1 + 0 ", + " assert(x > y, 'assert statement 2'); 2 + 0 ", + " assert(x > y, 'assert ' + 'statement 3'); 3 + 0 ", + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); 4 + 0 ", + " assert(x > y, 'assert ' + 'statement 5'); 5 + 0 ", + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); 6 + 0 " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [12]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_literal); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [12]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (1 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [12]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(x > y); 'assert statement 0001' ", + " assert(x > y, 'assert statement 2'); 'assert statement 0002' ", + " assert(x > y, 'assert ' + 'statement 3'); 'assert statement 0003' ", + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); 'assert statement 0004' ", + " assert(x > y, 'assert ' + 'statement 5'); 'assert statement 0005' ", + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); 'assert statement 0006' " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [13]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_string); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [13]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (1 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [13]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(x > y); 'assert statement' + '0001' ", + " assert(x > y, 'assert statement 2'); 'assert statement' + '0002' ", + " assert(x > y, 'assert ' + 'statement 3'); 'assert statement' + '0003' ", + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); 'assert statement' + '0004' ", + " assert(x > y, 'assert ' + 'statement 5'); 'assert statement' + '0005' ", + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); 'assert statement' + '0006' " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [14]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_string); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [14]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (1 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [14]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(1 > 1); 1 + 0; " + " assert(1 > 2, 'assert statement 2'); 2 + 0; " + " assert(1 > 3, 'assert ' + 'statement 3'); 3 + 0; " + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); 4 + 0; " + " assert(1 > 5, 'assert ' + 'statement 5'); 5 + 0 " + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); 6 + 0; " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [15]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_assert ); + type_sequence.push_back(et_t::e_literal); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [15]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (6 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [15]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(1 > 1); 'assert' + '01'; " + " assert(1 > 2, 'assert statement 2'); 'assert' + '02'; " + " assert(1 > 3, 'assert ' + 'statement 3'); 'assert' + '03'; " + " assert(1 > 4, 'assert ' + 'statement 4', 'Assert04'); 'assert' + '04'; " + " assert(1 > 5, 'assert ' + 'statement 5'); 'assert' + '05'; " + " assert(1 > 6, 'assert ' + 'statement 6', 'Assert' + '06'); 'assert' + '06'; " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [16]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_string); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [16]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (6 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 1. Expression: %s [16]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(x > y); x + y + 1; " + " assert(x > y, 'assert statement 2'); x + y + 1; " + " assert(x > y, 'assert ' + 'statement 3'); x + y + 1; " + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); x + y + 1; " + " assert(x > y, 'assert ' + 'statement 5'); x + y + 1; " + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); x + y + 1; " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [17]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_sf3ext); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [17]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (6 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 6. Expression: %s [17]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + { + const std::string expressions[] = + { + " assert(x > y); 'assert' + ((x < y) ? '01' : 'XYZ'); " + " assert(x > y, 'assert statement 2'); 'assert' + ((x < y) ? '02' : 'XYZ'); " + " assert(x > y, 'assert ' + 'statement 3'); 'assert' + ((x < y) ? '03' : 'XYZ'); " + " assert(x > y, 'assert ' + 'statement 4', 'Assert04'); 'assert' + ((x < y) ? '04' : 'XYZ'); " + " assert(x > y, 'assert ' + 'statement 5'); 'assert' + ((x < y) ? '05' : 'XYZ'); " + " assert(x > y, 'assert ' + 'statement 6', 'Assert' + '06'); 'assert' + ((x < y) ? '06' : 'XYZ'); " + }; + + const std::size_t expression_count = sizeof(expressions) / sizeof(std::string); + + for (std::size_t i = 0; i < expression_count; ++i) + { + T x = T(1); + T y = T(2); + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + assert_handler handler; + + handler.assert_count = 0; + + symbol_table.add_variable("x", x); + symbol_table.add_variable("y", y); + expression.register_symbol_table(symbol_table); + + parser.register_assert_check(handler); + + if (!parser.compile(expressions[i], expression)) + { + printf("run_test22() - Error: %s\tExpression: %s [18]\n", + parser.error().c_str(), + expressions[i].c_str()); + result = false; + continue; + } + + std::vector::node_types> type_sequence; + + typedef typename exprtk::expression_helper et_t; + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_assert); + type_sequence.push_back(et_t::e_string); + + if (!exprtk::expression_helper::match_type_sequence(expression,type_sequence)) + { + printf("run_test22() - Error: Expression failed to match type sequence. Expression: %s [18]\n", + expressions[i].c_str()); + result = false; + continue; + } + + expression.value(); + + if (6 != handler.assert_count) + { + printf("run_test22() - Error: Invalid assert count of %d expected 6. Expression: %s [18]\n", + static_cast(handler.assert_count), + expressions[i].c_str()); + result = false; + continue; + } + } + } + + return result; } template @@ -9353,51 +12811,61 @@ template <> struct type_name { static inline std::string value() { template <> struct type_name { static inline std::string value() { return "double"; } }; template <> struct type_name { static inline std::string value() { return "long double"; } }; -int main() +int main(int argc, char*argv[]) { - #define perform_test(Type,Number) \ - { \ - exprtk::timer timer; \ - timer.start(); \ - if (!run_test##Number()) \ - { \ - printf("run_test"#Number" (%s) *** FAILED! ***\n", \ - type_name::value().c_str()); \ - result = EXIT_FAILURE; \ - } \ - else \ - { \ - timer.stop(); \ - printf("run_test"#Number" (%s) - Result: SUCCESS Time: %8.4fsec\n", \ - type_name::value().c_str(), \ - timer.time()); \ - } \ - } \ + const std::string test_set = (argc == 2) ? std::string(argv[1]) : ""; + + #define perform_test(Type,Number) \ + { \ + const std::string test_name = "run_test"#Number; \ + if ( \ + test_set.empty() || \ + test_set.find(test_name) != std::string::npos \ + ) \ + { \ + exprtk::timer timer; \ + timer.start(); \ + if (!run_test##Number()) \ + { \ + printf("run_test"#Number" (%s) *** FAILED! ***\n", \ + type_name::value().c_str()); \ + result = EXIT_FAILURE; \ + } \ + else \ + { \ + timer.stop(); \ + printf("run_test"#Number" (%s) - Result: SUCCESS Time: %8.4fsec\n", \ + type_name::value().c_str(), \ + timer.time()); \ + } \ + } \ + } \ int result = 0; - perform_test(numeric_type,00) - perform_test(numeric_type,01) - perform_test(numeric_type,02) - perform_test(numeric_type,03) - perform_test(numeric_type,04) - perform_test(numeric_type,05) - perform_test(numeric_type,06) - perform_test(numeric_type,07) - perform_test(numeric_type,08) - perform_test(numeric_type,09) - perform_test(numeric_type,10) - perform_test(numeric_type,11) - perform_test(numeric_type,12) - perform_test(numeric_type,13) - perform_test(numeric_type,14) - perform_test(numeric_type,15) - perform_test(numeric_type,16) - perform_test(numeric_type,17) - perform_test(numeric_type,18) - perform_test(numeric_type,19) - perform_test(numeric_type,20) - perform_test(numeric_type,21) + perform_test( numeric_type, 00 ) + perform_test( numeric_type, 01 ) + perform_test( numeric_type, 02 ) + perform_test( numeric_type, 03 ) + perform_test( numeric_type, 04 ) + perform_test( numeric_type, 05 ) + perform_test( numeric_type, 06 ) + perform_test( numeric_type, 07 ) + perform_test( numeric_type, 08 ) + perform_test( numeric_type, 09 ) + perform_test( numeric_type, 10 ) + perform_test( numeric_type, 11 ) + perform_test( numeric_type, 12 ) + perform_test( numeric_type, 13 ) + perform_test( numeric_type, 14 ) + perform_test( numeric_type, 15 ) + perform_test( numeric_type, 16 ) + perform_test( numeric_type, 17 ) + perform_test( numeric_type, 18 ) + perform_test( numeric_type, 19 ) + perform_test( numeric_type, 20 ) + perform_test( numeric_type, 21 ) + perform_test( numeric_type, 22 ) #undef perform_test diff --git a/src/third_party/exprtk/license.txt b/src/third_party/exprtk/license.txt new file mode 100644 index 0000000..1135827 --- /dev/null +++ b/src/third_party/exprtk/license.txt @@ -0,0 +1,24 @@ +MIT License + +Copyright (c) 1999-2024 Arash Partow + +https://www.partow.net/programming/exprtk/index.html + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/third_party/exprtk/readme.txt b/src/third_party/exprtk/readme.txt index e1e0275..62ee3ca 100644 --- a/src/third_party/exprtk/readme.txt +++ b/src/third_party/exprtk/readme.txt @@ -24,12 +24,13 @@ C++ Mathematical Expression Toolkit Library Documentation Section 21 - Compilation Errors Section 22 - Runtime Library Packages Section 23 - Helpers & Utils - Section 24 - Benchmarking - Section 25 - Exprtk Notes - Section 26 - Simple Exprtk Example - Section 27 - Build Options - Section 28 - Files - Section 29 - Language Structure + Section 24 - Runtime Checks + Section 25 - Benchmarking + Section 26 - Exprtk Notes + Section 27 - Simple Exprtk Example + Section 28 - Build Options + Section 29 - Files + Section 30 - Language Structure [SECTION 00 - INTRODUCTION] @@ -39,7 +40,7 @@ mathematical expression parsing and evaluation engine. The parsing engine supports numerous forms of functional and logic processing semantics and is easily extensible. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 01 - CAPABILITIES] The ExprTk expression evaluator supports the following fundamental @@ -79,9 +80,13 @@ arithmetic operations, functions and processes: (10) Optimisations: constant-folding, simple strength reduction and dead code elimination - (11) Calculus: numerical integration and differentiation + (11) Runtime checks: vector bounds, string bounds, loop iteration, + execution-time bounds and compilation process + checkpointing, assert statements - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + (12) Calculus: numerical integration and differentiation + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 02 - EXAMPLE EXPRESSIONS] The following is a short listing of infix format based mathematical @@ -108,55 +113,64 @@ expressions that can be parsed and evaluated using the ExprTk library. (19) ((x + 'abc') like '*123*') or ('a123b' ilike y) (20) sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x } - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 03 - COPYRIGHT NOTICE] Free use of the C++ Mathematical Expression Toolkit Library is permitted under the guidelines and in accordance with the most current version of the MIT License. -https://www.opensource.org/licenses/MIT + (1) https://www.opensource.org/licenses/MIT + (2) SPDX-License-Identifier: MIT + (3) SPDX-FileCopyrightText : Copyright (C) 1999-2024 Arash Partow - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 04 - DOWNLOADS & UPDATES] The most recent version of the C++ Mathematical Expression Toolkit Library including all updates and tests can be found at the following locations: - (a) Download: https://www.partow.net/programming/exprtk/index.html - (b) Repository: https://github.com/ArashPartow/exprtk - https://github.com/ArashPartow/exprtk-extras + (1) Download: https://www.partow.net/programming/exprtk/index.html + (2) Mirror Repository: https://github.com/ArashPartow/exprtk + https://github.com/ArashPartow/exprtk-extras - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 05 - INSTALLATION] The header file exprtk.hpp should be placed in a project or system include path (e.g: /usr/include/). - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 06 - COMPILATION] +The ExprTk package contains the ExprTk header, a set of simple +examples and a benchmark and unit test suite. The following is a list +of commands to build the various components: + (a) For a complete build: make clean all (b) For a PGO build: make clean pgo (c) To strip executables: make strip_bin (d) Execute valgrind check: make valgrind_check - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 07 - COMPILER COMPATIBILITY] ExprTk has been built error and warning free using the following set of C++ compilers: (*) GNU Compiler Collection (3.5+) - (*) Intel C++ Compiler (8.x+) (*) Clang/LLVM (1.1+) + (*) Microsoft Visual Studio C++ Compiler (7.1+) + (*) Intel C++ Compiler (8.x+) + (*) AMD Optimizing C++ Compiler (1.2+) + (*) Nvidia C++ Compiler (19.x+) (*) PGI C++ (10.x+) - (*) Microsoft Visual Studio C++ Compiler (8.1+) + (*) Circle C++ (circa: b81c37d2bb227c) (*) IBM XL C/C++ (9.x+) (*) C++ Builder (XE4+) - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 08 - BUILT-IN OPERATIONS & FUNCTIONS] @@ -425,18 +439,18 @@ of C++ compilers: | | matches respectively. | | | (eg: x ilike y or 'a1B2c3D4e5F6g7H' ilike 'a?d*h') | +----------+---------------------------------------------------------+ -| [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: | | | 1. x[1:4] == 'bcde' | -| | 2. x[ :5] == x[:10 / 2] == 'abcdef' | +| | 2. x[ :4] == x[:8 / 2] == 'abcde' | | | 3. x[2 + 1: ] == x[3:] =='defgh' | | | 4. x[ : ] == x[:] == 'abcdefgh' | -| | 5. x[4/2:3+2] == x[2:5] == 'cdef' | +| | 5. x[4/2:3+1] == x[2:4] == 'cde' | | | | | | Note: Both r0 and r1 are assumed to be integers, where | | | r0 <= r1. They may also be the result of an expression, | | | in the event they have fractional components truncation | -| | will be performed. (eg: 1.67 --> 1) | +| | shall be performed. (eg: 1.67 --> 1) | +----------+---------------------------------------------------------+ | := | Assign the value of x to y. Where y is a mutable string | | | or string range and x is either a string or a string | @@ -477,8 +491,8 @@ of C++ compilers: | | being actioned. | | | eg: | | | 1. 'abc'[] == 3 | -| | 2. var max_str_length := max(s0[],s1[],s2[],s3[]) | -| | 3. ('abc' + 'xyz')[] == 6 | +| | 2. var max_str_length := max(s0[], s1[], s2[], s3[]) | +| | 3. ('abc' + 'd')[] == 6 | | | 4. (('abc' + 'xyz')[1:4])[] == 4 | +----------+---------------------------------------------------------+ @@ -519,30 +533,30 @@ of C++ compilers: | | eg: | | | switch | | | { | -| | case x > (y + z) : 2 * x / abs(y - z); | -| | case x < 3 : sin(x + y); | -| | default : 1 + x; | +| | case x > (y + z) : 2 * x / abs(y - z); | +| | case x < 3 : sin(x + y); | +| | default : 1 + x; | | | } | +----------+---------------------------------------------------------+ | while | The structure will repeatedly evaluate the internal | | | statement(s) 'while' the condition is true. The final | -| | statement in the final iteration will be used as the | +| | statement in the final iteration shall be used as the | | | return value of the loop. | | | eg: | | | while ((x -= 1) > 0) | | | { | -| | y := x + z; | -| | w := u + y; | +| | y := x + z; | +| | w := u + y; | | | } | +----------+---------------------------------------------------------+ | repeat/ | The structure will repeatedly evaluate the internal | | until | statement(s) 'until' the condition is true. The final | -| | statement in the final iteration will be used as the | +| | statement in the final iteration shall be used as the | | | return value of the loop. | | | eg: | | | repeat | -| | y := x + z; | -| | w := u + y; | +| | y := x + z; | +| | w := u + y; | | | until ((x += 1) > 100) | +----------+---------------------------------------------------------+ | for | The structure will repeatedly evaluate the internal | @@ -553,8 +567,8 @@ of C++ compilers: | | eg: | | | for (var x := 0; (x < n) and (x != y); x += 1) | | | { | -| | y := y + x / 2 - z; | -| | w := u + y; | +| | y := y + x / 2 - z; | +| | w := u + y; | | | } | +----------+---------------------------------------------------------+ | break | Break terminates the execution of the nearest enclosed | @@ -566,12 +580,12 @@ of C++ compilers: | | eg: | | | while ((i += 1) < 10) | | | { | -| | if (i < 5) | -| | j -= i + 2; | -| | else if (i % 2 == 0) | -| | break; | -| | else | -| | break[2i + 3]; | +| | if (i < 5) | +| | j -= i + 2; | +| | else if (i % 2 == 0) | +| | break; | +| | else | +| | break[2i + 3]; | | | } | +----------+---------------------------------------------------------+ | continue | Continue results in the remaining portion of the nearest| @@ -579,9 +593,9 @@ of C++ compilers: | | eg: | | | for (var i := 0; i < 10; i += 1) | | | { | -| | if (i < 5) | -| | continue; | -| | j -= i + 2; | +| | if (i < 5) | +| | continue; | +| | j -= i + 2; | | | } | +----------+---------------------------------------------------------+ | return | Return immediately from within the current expression. | @@ -628,7 +642,7 @@ of C++ compilers: | | 2. max_size := max(v0[],v1[],v2[],v3[]) | +----------+---------------------------------------------------------+ -Note: In the tables above, the symbols x, y, z, w, u and v where +Note01: In the tables above, the symbols x, y, z, w, u and v where appropriate may represent any of one the following: 1. Literal numeric/string value @@ -638,7 +652,7 @@ appropriate may represent any of one the following: 5. A string 6. An expression comprised of [1], [2] or [3] (eg: 2 + x / vec[3]) - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 09 - FUNDAMENTAL TYPES] ExprTk supports three fundamental types which can be used freely in @@ -670,7 +684,7 @@ can be assigned and concatenated to one another, they can also be manipulated via sub-ranges using the range definition syntax. Strings however can not interact with scalar or vector types. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 10 - COMPONENTS] There are three primary components, that are specialised upon a given @@ -698,6 +712,7 @@ types a symbol table can handle: (f) Functions (g) Vararg functions + During the compilation process if an expression is found to require any of the elements noted above, the expression's associated symbol_table will be queried for the element and if present a @@ -706,9 +721,51 @@ 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 +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 +current values assigned to the variables shall be used. + + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + double x = 0; + double y = 0; + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + std::string expression_string = "x * y + 3"; + + symbol_table.add_variable("x",x); + symbol_table.add_variable("y",y); + + expression.register_symbol_table(symbol_table); + + parser.compile(expression_string,expression); + + x = 1.0; + y = 2.0; + expression.value(); // 1 * 2 + 3 + + x = 3.7; + expression.value(); // 3.7 * 2 + 3 + + y = -9.0; + expression.value(); // 3.7 * -9 + 3 + + // 'x * -9 + 3' for x in range of [0,100) in steps of 0.0001 + for (x = 0.0; x < 100.0; x += 0.0001) + { + expression.value(); // x * -9 + 3 + } + + +Note02: Any variable reference provided to a given symbol_table +instance, must have a lifetime at least as long as the lifetime 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 @@ -721,94 +778,145 @@ those references are subsequently invalidated resulting in various forms of undefined behaviour. typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; symbol_table_t symbol_table; - expression_t expression; + expression_t expression; + + std::deque y {1.1, 2.2, 3.3}; + std::vector z {4.4, 5.5, 6.6}; + double* w = new double(123.456); { double x = 123.4567; symbol_table.add_variable("x", x); } // Reference to variable x has been invalidated - std::deque 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 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"; + const std::string expression_string = "x + y / z * w"; // Compilation of expression will succeed - parser.compile(expression_str,expression); + parser.compile(expression_string,expression); expression.value(); - // Evaluation will result in undefined behaviour + // Evaluation will result in undefined behaviour + // due to 'x' and 'w' having been destroyed. symbol_table.get_variable("x")->ref() = 135.791; - // Assignment will result in undefined behaviour + // 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 -current values assigned to the variables will be used. +A compiled expression that references variables from a symbol_table is +dependent on that symbol_table instance and the variables it holds +being valid. typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; - typedef exprtk::parser parser_t; symbol_table_t symbol_table; expression_t expression; - parser_t parser; - double x = 0; - double y = 0; + double x = 123.456; - std::string expression_string = "x * y + 3"; - symbol_table.add_variable("x",x); - symbol_table.add_variable("y",y); + symbol_table.add_variable("x", x); - expression.register_symbol_table(symbol_table); + const std::string expression_string = "(x + 1) / 2"; + // Compilation of the expression will succeed parser.compile(expression_string,expression); - x = 1.0; - y = 2.0; - expression.value(); // 1 * 2 + 3 + // Clear all variables from symbol_table + symbol_table.clear(); - x = 3.7; - expression.value(); // 3.7 * 2 + 3 + expression.value(); + // Evaluation will result in undefined behaviour + // because the reference to 'x' having been destroyed + // during the clearing of the symbol_table + + +In the above example, an expression is compiled that references +variable "x". As part of the compilation process the node holding the +variable "x" is obtained from the symbol_table and embedded in the AST +of the expression - in short the expression is now referencing the +node that holds the variable "x". The following diagram depicts the +dependencies between the variable x, the symbol table and the +expression: + + +--[Symbol Table]--+ + | | + | +- ------+ | + | | x-node | | + | +-----A--+ | +--[Expression]--+ + +---|---|----------+ | +---------+ | + v | | | A.S.T | | + | +--------<--------[.] | | + +-----+ | +---------+ | + | +----------------+ + +-v-[variable]---+ + | x: 123.456 | + +----------------+ + + +When the clear method is called on the symbol table the X-Node is +destroyed, so now the expression is referencing a node that has been +destroyed. From this point onwards any attempts to reference the +expression instance will result in undefined behaviour. Simply put the +above example violates the requirement that the lifetime of any +objects referenced by expressions should exceed the lifetime of the +expression instance. - y = -9.0; - expression.value(); // 3.7 * -9 + 3 + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + + symbol_table_t symbol_table; + expression_t expression; + + double x = 123.456; + + symbol_table.add_variable("x", x); + + const std::string expression_string = "(x + 1) / 2"; + + // Compilation of the expression will succeed + parser.compile(expression_string,expression); + + expression.value(); + + // Release the expression and its dependents + expression.release(); + + // Clear all variables from symbol_table + symbol_table.clear(); + + expression.value(); + // Will return null_node value of NaN - // 'x * -9 + 3' for x in range of [0,100) in steps of 0.0001 - for (x = 0.0; x < 100.0; x += 0.0001) - { - expression.value(); // x * -9 + 3 - } +In the above example the expression is released before the associated +symbol_table is cleared of its variables, which resolves the undefined +behaviour issue noted in the previous example. -Note: It is possible to register multiple symbol_tables with a single -expression object. In the event an expression has multiple symbol -tables, and where there exists conflicts between symbols, the +Note03: It is possible to register multiple symbol_tables with a +single expression object. In the event an expression has multiple +symbol tables, and where there exists conflicts between symbols, the compilation stage will resolve the conflicts based on the order of registration of the symbol_tables to the expression. For a more -expansive discussion please review section [17 - Hierarchies Of -Symbol Tables] +expansive discussion please review section [17 - Hierarchies Of Symbol +Tables] typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; @@ -840,13 +948,16 @@ The symbol table supports adding references to external instances of types that can be accessed within expressions via the following methods: - 1. bool add_variable (const std::string& name, scalar_t&) - 2. bool add_constant (const std::string& name, const scalar_t&) - 3. bool add_stringvar(const std::string& name, std::string&) - 4. bool add_vector (const std::string& name, vector_type&) + 1. bool add_variable (const std::string& name, scalar_t& ) + 2. bool add_constant (const std::string& name, const scalar_t& ) + 3. bool add_stringvar (const std::string& name, std::string& ) + 4. bool add_vector (const std::string& name, vector_type& ) + 5. bool add_function (const std::string& name, function_t& ) + 6. bool create_stringvar(const std::string& name,const std::string&) + 7. bool create_variable (const std::string& name, const T& ) -Note: The 'vector' type must be comprised from a contiguous array of +Note04: The 'vector' type must be comprised from a contiguous array of scalars with a size that is larger than zero. The vector type itself can be any one of the following: @@ -868,10 +979,21 @@ a false result due to one or more of the following reasons: 6. The symbol_table instance is in an invalid state +Note05: The symbol_table has a method called clear, which when invoked +will clear all variables, vectors, strings and functions registered +with the symbol_table instance. If this method is to be called, then +one must make sure that all compiled expression instances that +reference variables belonging to that symbol_table instance are +released (aka call release method on expression) before calling the +clear method on the symbol_table instance, otherwise undefined +behaviours will occur. + A further property of symbol tables is that they can be classified at -instantiation as either being mutable (by default) or immutable. The -following demonstrates construction of an immutable symbol table -instance: +instantiation as either being mutable (by default) or immutable. This +property determines if variables, vectors or strings registered with +the symbol table can undergo modifications within expressions that +reference them. The following demonstrates construction of an +immutable symbol table instance: symbol_table_t immutable_symbol_table (symbol_table_t::symtab_mutability_type::e_immutable); @@ -886,14 +1008,38 @@ the mutability constraint are the following assignment operators: 1. Assignment: := 2. Assign operation: +=, -=, *=, /= , %= + const std::string expression_str = "x += x + 123.456"; + + symbol_table_t immutable_symbol_table + (symbol_table_t::symtab_mutability_type::e_immutable); + + T x = 0.0; + + immutable_symbol_table.add_variable("x" , x); + + expression_t expression; + expression.register_symbol_table(immutable_symbol_table); + + parser_t parser; + + parser.compile(expression_str, expression); + // Compile error because of assignment to variable x + + +In the above example, variable x is registered to an immutable symbol +table, making it an immutable variable within the context of any +expressions that reference it. The expression string being compiled +uses the addition assignment operator which will modify the value of +variable x. The compilation process detects this semantic violation +and proceeds to halt compilation and return the appropriate error. -The main reason for this functionality is that, one may want the -immutability properties that come with constness of a variable such as -scalars, vectors and strings, but not necessarily the accompanying -compile time const-folding optimisations, that would result in the -value of the variables being retrieved only once at compile time, -causing external updates to the variables to not be part of the -expression evaluation. +One of the main reasons for this functionality is that, one may want +the immutability properties that come with constness of a variable +such as scalars, vectors and strings, but not necessarily the +accompanying compile time const-folding optimisations, that would +result in the value of the variables being retrieved only once at +compile time, causing external updates to the variables to not be part +of the expression evaluation. symbol_table_t immutable_symbol_table (symbol_table_t::symtab_mutability_type::e_immutable); @@ -906,10 +1052,10 @@ expression evaluation. immutable_symbol_table.add_constant("y" , 123.0); expression_t expression; - expression.register_symbol_table(immutabile_symbol_table); + expression.register_symbol_table(immutable_symbol_table); parser_t parser; - parser.compile(expression_str, expression) + parser.compile(expression_str, expression); for (; x < 10.0; ++x) { @@ -924,8 +1070,8 @@ constant and X is a normal variable. Both are registered with a symbol table that is immutable. The expression when compiled will result in the "(y + y)" part being const-folded at compile time to the literal value of 246. Whereas the current value of X, being updated via the -for-loop, externally to the expression and the symbol table will be -available to the expression upon each evaluation. +for-loop, externally to the expression and the symbol table shall be +observable to the expression upon each evaluation. (2) Expression @@ -953,9 +1099,9 @@ Expression: z := (x + y^-2.345) * sin(pi / min(w - 7.3,v)) / \ ___/ \___ Variable(x) [Exponentiation] / \ ______/ \______ Constant(pi) [Binary-Function(min)] - / \ ____/ \____ - Variable(y) [Negation] / \ - | / Variable(v) + / \ ____/ \___ + Variable(y) [Negation] / \ + | / Variable(v) Constant(2.345) / / [Subtraction] @@ -964,7 +1110,7 @@ Expression: z := (x + y^-2.345) * sin(pi / min(w - 7.3,v)) Variable(w) Constant(7.3) -The above denoted AST will be evaluated in the following order: +The above denoted AST shall be evaluated in the following order: (01) Load Variable (z) (10) Load Constant (7.3) (02) Load Variable (x) (11) Subtraction (09 & 10) @@ -990,16 +1136,17 @@ of them and returning a value based on some arbitrary calculation: ResultType foo(InputType x, InputType y, InputType z, InputType w) { - w = 2 * x^y + z; // Side-Effect - return abs(x - y) / z; // Return Result + w = 2 * x^y + z; // Side-Effect + return abs(x - y) / z; // Return Result } Given the above definition the following is a functionally equivalent version using ExprTk: - const std::string foo_str = " w := 2 * x^y + z; " - " abs(x - y) / z; "; + const std::string foo_str = + " w := 2 * x^y + z; " + " abs(x - y) / z; "; T x, y, z, w; @@ -1031,8 +1178,7 @@ error status code, with a more detailed description of the error(s) and its location within the input provided by the 'get_error' interface. - -Note: The exprtk::expression and exprtk::symbol_table components are +Note06: The exprtk::expression and exprtk::symbol_table components are reference counted entities. Copy constructing or assigning to or from either component will result in a shallow copy and a reference count increment, rather than a complete replication. Furthermore the @@ -1042,14 +1188,14 @@ various C++ standard library containers and adaptors such as std::vector, std::map, std::stack etc. The following is an example of two unique expressions, after having -being instantiated and compiled, one expression is assigned to the +been instantiated and compiled, one expression is assigned to the other. The diagrams depict their initial and post assignment states, including which control block each expression references and their associated reference counts. - exprtk::expression e0; // constructed expression, eg: x + 1 - exprtk::expression e1; // constructed expression, eg: 2z + y + exprtk::expression e0; // constructed expression, eg: x + 1 + exprtk::expression e1; // constructed expression, eg: 2z + y +-----[ e0 cntrl block]----+ +-----[ e1 cntrl block]-----+ | 1. Expression Node 'x+1' | | 1. Expression Node '2z+y' | @@ -1089,7 +1235,7 @@ The prescribed method for cloning an expression is to compile it from its string form. Doing so will allow the 'user' to properly consider the exact source of user defined variables and functions. -Note: The exprtk::parser is a non-copyable and non-thread safe +Note07: The exprtk::parser is a non-copyable and non-thread safe component, and should only be shared via either a reference, a shared pointer or a std::ref mechanism, and considerations relating to synchronisation taken into account where appropriate. The parser @@ -1108,7 +1254,7 @@ std::vector. +--> ~.~.~.~.~.~.~.~.~.~ ->--+ | +-----------------------+ | Expressions in | | Expressions as - string form A V exprtk::expression + string form ^ V exprtk::expression | | instances [s0:'x+1']--->--+ | | +-[e0: x+1] | | | | @@ -1117,13 +1263,17 @@ std::vector. [s2:'sin(k+w)']-+ +-[e2: sin(k+w)] - const std::string expression_str[3] - = { "x + 1", "2x + y", "sin(k + w)" }; + const std::string expression_str[3] = + { + "x + 1", + "2x + y", + "sin(k + w)" + }; std::vector expression_list; - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; symbol_table_t symbol_table; expression.register_symbol_table(symbol_table); @@ -1143,7 +1293,7 @@ std::vector. e.value(); } - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 11 - COMPILATION OPTIONS] The exprtk::parser when being instantiated takes as input a set of @@ -1153,14 +1303,15 @@ commutative and strength reduction options are enabled is as follows: typedef exprtk::parser::settings_t settings_t; - std::size_t compile_options = settings_t::e_joiner + - settings_t::e_commutative_check + - settings_t::e_strength_reduction; + const std::size_t compile_options = + settings_t::e_joiner + + settings_t::e_commutative_check + + settings_t::e_strength_reduction; parser_t parser(compile_options); -Currently seven types of compile time options are supported, and +Currently eight types of compile time options are supported, and enabled by default. The options and their explanations are as follows: (1) Replacer @@ -1171,11 +1322,12 @@ enabled by default. The options and their explanations are as follows: (6) Commutative Check (7) Strength Reduction Check (8) Stack And Node Depth Check + (9) Vector Size Check (1) Replacer (e_replacer) Enable replacement of specific tokens with other tokens. For example -the token "true" of type symbol will be replaced with the numeric +the token "true" of type symbol shall be replaced with the numeric token of value one. (a) (x < y) == true ---> (x < y) == 1 @@ -1244,7 +1396,7 @@ such transformations: (e) 5foo(x,y) ---> 5 * foo(x,y) (f) foo(x,y)6 + 1 ---> foo(x,y) * 6 + 1 (g) (4((2x)3)) ---> 4 * ((2 * x) * 3) - (h) w(x) + (y)z ---> w * x + y * z + (h) w / (x - y)z ---> w / (x - y) * z (7) Strength Reduction Check (e_strength_reduction) @@ -1254,18 +1406,20 @@ predominantly involve transforming sub-expressions into other forms that are algebraically equivalent yet less costly to compute. The following are examples of the various transformations that can occur: - (a) (x / y) / z ---> x / (y * z) - (b) (x / y) / (z / w) ---> (x * w) / (y * z) - (c) (2 * x) - (2 * y) ---> 2 * (x - y) - (d) (2 / x) / (3 / y) ---> (2 / 3) / (x * y) - (e) (2 * x) * (3 * y) ---> (2 * 3) * (x * y) + (a) (x / y) / z ---> x / (y * z) + (b) (x / y) / (z / w) ---> (x * w) / (y * z) + (c) (2 * x) - (2 * y) ---> 2 * (x - y) + (d) (2 / x) / (3 / y) ---> (2 / 3) / (x * y) + (e) (2 * x) * (3 * y) ---> 6 * (x * y) + (f) (2 * x) * (2 - 4 / 2) ---> 0 + (g) (3 - 6 / 2) / (2 * x) ---> 0 + (h) avg(x,y,z) * (2 - 4 / 2) ---> 0 -Note: -When using strength reduction in conjunction with expressions whose -inputs or sub-expressions may result in values nearing either of the -bounds of the underlying numeric type (eg: double), there may be the -possibility of a decrease in the precision of results. +Note08: When using strength reduction in conjunction with expressions +whose inputs or sub-expressions may result in values nearing either of +the bounds of the underlying numeric type (eg: double), there may be +the possibility of a decrease in the precision of results. In the following example the given expression which represents an attempt at computing the average between x and y will be transformed @@ -1295,10 +1449,10 @@ grow, and may result in potential stackoverflow issues as denoted above. ExprTk provides a set of checks that prevent both of the above denoted -problems at compile time. These check rely on two specific limits -being set on the parser instance, these limits are: +problems at compile time. These checks rely on two specific limits +being set on the parser settings instance, these limits are: - 1. max_stack_depth (default: 400) + 1. max_stack_depth (default: 400 ) 2. max_node_depth (default: 10000) @@ -1306,23 +1460,48 @@ The following demonstrates how these two parser parameters can be set: parser_t parser; - parser.set_max_stack_depth(100); - parser.set_max_node_depth(200); + parser.settings().set_max_stack_depth(100); + parser.settings().set_max_node_depth(200); -In the above code, during parsing if the stack depth reaches or +In the above code, during parsing if the stack depth reaches or exceeds 100 levels, the parsing process will immediately halt and return with a failure. Similarly, during synthesizing the AST nodes, if the compilation process detects an AST tree depth exceeding 200 levels the parsing process will halt and return a parsing failure. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(9) Vector Size Check +When defining an expression local vector, ExprTk uses a default max +vector size of two billion elements. One may want to limit the max +vector size to be either smaller or larger than the specified default +value. The max size value can be changed via the parser settings. + + parser_t parser; + + parser.settings().set_max_local_vector_size(1000000); + + std::string expression1 = "var v[1e6] := [123]"; + std::string expression2 = "var v[1e9] := [123]"; + + expression_t expression; + + parser.compile(expression1, expression); // compilation success + parser.compile(expression2, expression); // compilation error + + +In the above code, the max local vector size is set to one million +elements. During compilation of an expression if there is a vector +definition where the vector size exceeds the max vector size a +compilation error shall be emitted. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 12 - EXPRESSION STRUCTURES] Exprtk supports mathematical expressions in numerous forms based on a simple imperative programming model. This section will cover the following topics related to general structure and programming of -expression using ExprTk: +expressions using ExprTk: (1) Multi-Statement Expressions (2) Statements And Side-Effects @@ -1331,7 +1510,7 @@ expression using ExprTk: (1) Multi-Statement Expressions -Expressions in ExprTk can be comprised of one more statements, which +Expressions in ExprTk can be comprised of one or more statements, which may sometimes be called sub-expressions. The following are two examples of expressions stored in std::string variables, the first a single statement and the second a multi-statement expression: @@ -1389,18 +1568,18 @@ returned. In the following example, the return value of the expression will be 11, which is the sum of the variable 'x' and the final value computed -within the loop body on its last iteration: +within the loop body upon its last iteration: var x := 1; x + for (var i := x; i < 10; i += 1) { - i / 2; - i + 1; + i / 2; + i + 1; } (2) Statements And Side-Effects -Statements themselves may have side effects, which in-turn effect the +Statements themselves may have side effects, which in-turn affect the proceeding statements in multi-statement expressions. A statement is said to have a side-effect if it causes the state of @@ -1439,30 +1618,30 @@ noted: +-+----------------------+------------------------------+ -Note: In example 6 from the above set, it is assumed the user defined -function foo has been registered as having a side-effect. By default -all user defined functions are assumed to have side-effects, unless -they are configured in their constructors to not have side-effects -using the 'disable_has_side_effects' free function. For more -information review Section 15 - User Defined Functions sub-section 7 +Note09: In example 6 from the above set, it is assumed the user +defined function foo has been registered as having a side-effect. By +default all user defined functions are assumed to have side-effects, +unless they are configured in their constructors to not have side- +effects using the 'disable_has_side_effects' free function. For more +information review Section 15 - User Defined Functions sub-section 7 Function Side-Effects. At this point we can see that there will be expressions composed of -certain kinds of statements that when executed will not effect the +certain kinds of statements that when executed will not affect the nature of the expression's result. These statements are typically -called 'dead code'. These statements though not effecting the final +called 'dead code'. These statements though not affecting the final result will still be executed and as such they will consume processing time that could otherwise be saved. As such ExprTk attempts to detect and remove such statements from expressions. The 'Dead Code Elimination' (DCE) optimisation process, which is enabled by default, will remove any statements that are determined to -not have a side effect in a multi-statement expression, excluding the +not have a side-effect in a multi-statement expression, excluding the final or last statement. By default the final statement in an expression will always be present regardless of its side-effect status, as it is the statement whose -value will be used as the result of the expression. +value shall be used as the result of the expression. In order to further explain the actions taken during the DCE process, lets review the following expression: @@ -1494,7 +1673,7 @@ follows: (3) Conditional Statements (If-Then-Else) -ExprTk support two forms of conditional branching or otherwise known +ExprTk supports two forms of conditional branching or otherwise known as if-statements. The first form, is a simple function based conditional statement, that takes exactly three input expressions: condition, consequent and alternative. The following is an example @@ -1504,7 +1683,7 @@ expression that utilises the function based if-statement. In the example above, if the condition 'y < z' is true, then the -consequent 'y + 1' will be evaluated, its value will be returned and +consequent 'y + 1' will be evaluated, its value shall be returned and subsequently assigned to the variable 'x'. Otherwise the alternative '2 * z' will be evaluated and its value will be returned. This is essentially the simplest form of an if-then-else statement. A simple @@ -1532,11 +1711,11 @@ will return a quiet NaN value as its result. Example 2: x := if (y < z) { - y + 3 - } + y + 3 + }; The two example expressions above are equivalent. If the condition -'y < z' is true, the 'x' variable will be assigned the value of the +'y < z' is true, the 'x' variable shall be assigned the value of the consequent 'y + 3', otherwise it will be assigned the value of quiet NaN. As previously discussed, if-statements are value returning constructs, and if not properly terminated using a semi-colon, will @@ -1564,38 +1743,38 @@ conditional statement with a semi-colon as follows: (b) If-Then-Else Statement The second variation of the if-statement is to allow for the use of -Else and If-Else cascading statements. Examples of such statements are +Else and Else-If cascading statements. Examples of such statements are as follows: - Example 1: Example 2: Example 3: - if (x < y) if (x < y) if (x > y + 1) - z := x + 3; { y := abs(x - z); - else y := z + x; else - y := x - z; z := x + 3; { - } y := z + x; - else z := x + 3; - y := x - z; }; - - - Example 4: Example 5: Example 6: - if (2 * x < max(y,3)) if (x < y) if (x < y or (x + z) > y) - { z := x + 3; { - y := z + x; else if (2y != z) z := x + 3; - z := x + 3; { y := x - z; - } z := x + 3; } - else if (2y - z) y := x - z; else if (abs(2y - z) >= 3) - y := x - z; } y := x - z; - else else - x * x; { + Example 1: Example 2: Example 3: + if (x < y) if (x < y) if (x > y + 1) + z := x + 3; { y := abs(x - z); + else y := z + x; else + y := x - z; z := x + 3; { + } y := z + x; + else z := x + 3; + y := x - z; }; + + + Example 4: Example 5: Example 6: + if (2 * x < max(y,3)) if (x < y) if (x < y or (x + z) > y) + { z := x + 3; { + y := z + x; else if (2y != z) z := x + 3; + z := x + 3; { y := x - z; + } z := x + 3; } + else if (2y - z) y := x - z; else if (abs(2y - z) >= 3) + y := x - z; } y := x - z; + else else + x * x; { z := abs(x * x); x * y * z; - }; + }; In the case where there is no final else statement and the flow through the conditional arrives at this final point, the same rules apply to this form of if-statement as to the previous. That is a quiet -NaN will be returned as the result of the if-statement. Furthermore +NaN shall be returned as the result of the if-statement. Furthermore the same requirements of terminating the statement with a semi-colon apply. @@ -1668,12 +1847,12 @@ correctly optimise such expressions for a given architecture. $f98(x,y,z,w) | (x == y) ? z : w $f99(x,y,z,w) | x*sin(y)+z*cos(w) - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 13 - VARIABLE, VECTOR & STRING DEFINITION] ExprTk supports the definition of expression local variables, vectors and strings. The definitions must be unique as shadowing is not -allowed and object life-times are based on scope. Definitions use the +allowed and object lifetimes are based on scope. Definitions use the following general form: var := ; @@ -1692,6 +1871,9 @@ zero. The following are examples of variable definitions: (c) Initialise z to the expression var z := if (max(1, x + y) > 2, w, v); + (d) Initialise const literal n + var n := 12 / 3; + (2) Vector Definition Vectors are arrays of a common numeric type. The elements in a vector @@ -1704,30 +1886,37 @@ zero. The following are examples of vector definitions: (b) Initialise all values to zero var x[3] := {}; - (c) Initialise all values to given expression - var x[3] := [123 + 3y + sin(w / z)]; + (c) Initialise all values to given value or expression + var x[3] := [ 42 ]; + var y[x[]] := [ 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 }; + (d) Initialise all values iota style + var v[4] := [ 0 : +1]; // 0, 1, 2, 3 + var v[5] := [-3 : -2]; // -3, -5, -7, -9, -11 - (e) Initialise the first three (all) values - var x[3] := { 1, 2, 3 }; + (e) Initialise the first two values, all other elements to zero + var x[3] := { (1 + x[2]) / x[], (sin(y[0] / x[]) + 3) / x[] }; - (f) Initialise vector from a vector + (f) Initialise the first three (all) values + const var size := 3; + var x[size] := { 1, 2, 3 }; + + (g) Initialise vector from a vector var x[4] := { 1, 2, 3, 4 }; var y[3] := x; + var w[5] := { 1, 2 }; // 1, 2, 0, 0, 0 - (g) Initialise vector from a smaller vector + (h) Initialise vector from a smaller vector var x[3] := { 1, 2, 3 }; var y[5] := x; // 1, 2, 3, ??, ?? - (h) Non-initialised vector + (i) Non-initialised vector var x[3] := null; // ?? ?? ?? - (i) Error as there are too many initialisers + (j) Error as there are too many initialisers var x[3] := { 1, 2, 3, 4 }; - (j) Error as a vector of size zero is not allowed. + (k) Error as a vector of size zero is not allowed. var x[0]; @@ -1769,7 +1958,7 @@ examples of string variable definitions: Variable and vector definitions have a return value. In the case of variable definitions, the value to which the variable is initialised will be returned. Where as for vectors, the value of the first element -(eg: v[0]) will be returned. +(eg: v[0]) shall be returned. 8 == ((var x := 7;) + 1) 4 == (var y[3] := {4, 5, 6};) @@ -1794,7 +1983,7 @@ vector expression can be assigned to a variable. x := y + 1; -Note: During the expression compilation phase, tokens are classified +Note10: During the expression compilation phase, tokens are classified based on the following priorities: (a) Reserved keywords or operators (+, -, and, or, etc) @@ -1804,7 +1993,7 @@ based on the following priorities: (e) Symbol table functions (f) Unknown symbol resolver based variables - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 14 - VECTOR PROCESSING] ExprTk provides support for various forms of vector oriented @@ -1827,20 +2016,22 @@ with vectors: abs, acos, acosh, asin, asinh, atan, atanh, ceil, cos, cosh, cot, csc, deg2grad, deg2rad, erf, erfc, exp, expm1, floor, frac, grad2deg, log, log10, log1p, log2, rad2deg, round, sec, - sgn, sin, sinc, sinh, sqrt, swap, tan, tanh, trunc + sgn, sin, sinc, sinh, sqrt, swap, tan, tanh, trunc, + thresholding (g) Aggregate and Reduce operations: avg, max, min, mul, dot, dotk, sum, sumk, count, all_true, all_false, any_true, any_false (h) Transformation operations: - copy, rotate-left/right, shift-left/right, sort, nth_element + copy, diff, reverse, rotate-left/right, shift-left/right, sort, + nth_element (i) BLAS-L1: axpy, axpby, axpyz, axpbyz, axpbz -Note: When one of the above described operations is being performed +Note11: When one of the above described operations is being performed between two vectors, the operation will only span the size of the smallest vector. The elements of the larger vector outside of the range will not be included. The operation itself will be processed -element-wise over values the smaller of the two ranges. +element-wise over values of the smaller of the two ranges. The following simple example demonstrates the vector processing capabilities by computing the dot-product of the vectors v0 and v1 and @@ -1860,11 +2051,11 @@ the previously mentioned dot-product computation expression: for (var i := 0; i < min(v0[],v1[]); i += 1) { - v0dotv1 += (v0[i] * v1[i]); + v0dotv1 += (v0[i] * v1[i]); } -Note: When the aggregate or reduction operations denoted above are +Note12: When the aggregate or reduction operations denoted above are used in conjunction with a vector or vector expression, the return value is not a vector but rather a single value. @@ -1885,7 +2076,7 @@ that is passed. The following example attempts to evaluate the sum of elements of the external user defined vector within a typical yet trivial expression: - std::string reduce_program = " sum(2 * v + 1) "; + const std::string reduce_program = " sum(2 * v + 1) "; std::vector v0 { T(1.1), T(2.2), ..... , T(99.99) }; @@ -1951,7 +2142,54 @@ evaluated as normal. sum += expression.value(); } - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Another useful feature of exprtk::vector_view is that all such vectors +can have their sizes modified (or "resized"). The resizing of the +associated vectors can happen either between or during evaluations. + + std::vector v = { 1, 2, 3, 4, 5, 6, 7, 8 }; + exprtk::vector_view view = exprtk::make_vector_view(v,v.size()); + + symbol_table_t symbol_table; + symbol_table.add_vector("v",view); + + const std::string expression_string = "v[]"; + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + parser.compile(expression_string, expression); + + for (std::size_t i = 1; i <= v.size(); ++i) + { + vv.set_size(i); + expression.value(); + } + + +In the example above, a vector_view is instantiated with a std::vector +instance with eight elements and registered to the given symbol_table. +An expression is then compiled, which in this case simply returns the +size of the vector at that point in time. The expression is evaluated +eight times (size of vector times), where upon each iteration the size +of the vector is changed with values ranging from one to eight. + +Note13: When modifying the size of a vector, the new size must be at +least one or larger and must not exceed the original size of the +vector_view when it was instantiated. + +Note14: The lifetime of any parser, symbol_table or expression +instance must not exceed that of any vector_view instance that has +been registered with it. Furthermore the lifetime of a vector_view +must not exceed that of the underlying vector instance it is +associated with. + +Note15: In a multi-threaded context the rebase function should not be +called during associated expression evaluation, as this will lead to +undefined behaviour (eg: torn reads and writes). + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 15 - USER DEFINED FUNCTIONS] ExprTk provides a means whereby custom functions can be defined and @@ -1962,7 +2200,7 @@ inputs but will always return a single value of the underlying numeric type. During expression compilation when required the reference to the -function will be obtained from the associated symbol_table and be +function shall be obtained from the associated symbol_table and be embedded into the expression. There are five types of function interface: @@ -1987,12 +2225,12 @@ expects to handle. The following example defines a 3 parameter function called 'foo': template - struct foo : public exprtk::ifunction + struct foo final : public exprtk::ifunction { foo() : exprtk::ifunction(3) {} - T operator()(const T& v1, const T& v2, const T& v3) + T operator()(const T& v1, const T& v2, const T& v3) override { return T(1) + (v1 * v2) / T(v3); } @@ -2006,9 +2244,9 @@ specialised upon type T to facilitate parameter passing. The following example defines a vararg function called 'boo': template - struct boo : public exprtk::ivararg_function + struct boo final : public exprtk::ivararg_function { - inline T operator()(const std::vector& arglist) + inline T operator()(const std::vector& arglist) override { T result = T(0); @@ -2045,7 +2283,7 @@ will persist after the function call has completed. The following example defines a generic function called 'too': template - struct too : public exprtk::igeneric_function + struct too final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -2053,7 +2291,7 @@ example defines a generic function called 'too': too() {} - inline T operator()(parameter_list_t parameters) + inline T operator()(parameter_list_t parameters) override { for (std::size_t i = 0; i < parameters.size(); ++i) { @@ -2081,8 +2319,8 @@ are three type enumerations: eg: 'AString', s0, 'AString'[x:y], s1[1 + x:] + 'AString' -Each of the parameters can be accessed using its designated view. A -typical loop for processing the parameters is as follows: +Each of the parameters can be accessed using its designated view. +A typical loop for processing the parameters is as follows: inline T operator()(parameter_list_t parameters) { @@ -2156,7 +2394,7 @@ The following example demonstrates a simple generic function implementation with a user specified parameter sequence: template - struct moo : public exprtk::igeneric_function + struct moo final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -2165,7 +2403,7 @@ implementation with a user specified parameter sequence: : exprtk::igeneric_function("SVTT") {} - inline T operator()(parameter_list_t parameters) + inline T operator()(parameter_list_t parameters) override { ... } @@ -2180,11 +2418,11 @@ parameters in the following sequence: (3) Scalar (4) Scalar -Note: The 'Z' or no parameter option may not be used in conjunction +Note16: The 'Z' or no parameter option may not be used in conjunction with any other type option in a parameter sequence. When incorporated -in the parameter sequence list, the no parameter option indicates that -the function may be invoked without any parameters being passed. For -more information refer to the section: 'Zero Parameter Functions' +in the parameter sequence list, the 'No Parameter' option indicates +that the function may be invoked without any parameters being passed. +For more information refer to the section: 'Zero Parameter Functions' (4) igeneric_function II @@ -2202,9 +2440,9 @@ The following example defines a generic function named 'toupper' with the string return type function operator being explicitly overridden: template - struct toupper : public exprtk::igeneric_function + struct toupper final : public exprtk::igeneric_function { - typedef exprtk::igeneric_function igenfunct_t + typedef exprtk::igeneric_function igenfunct_t; typedef typename igenfunct_t::generic_type generic_t; typedef typename igenfunct_t::parameter_list_t parameter_list_t; typedef typename generic_t::string_view string_t; @@ -2214,11 +2452,11 @@ the string return type function operator being explicitly overridden: {} inline T operator()(std::string& result, - parameter_list_t parameters) + parameter_list_t parameters) override { result.clear(); - string_t string(params[0]); + string_t string(parameters[0]); for (std::size_t i = 0; i < string.size(); ++i) { @@ -2244,9 +2482,9 @@ the toupper function registered as the symbol 'toupper' is as follows: "'ABCDEF' == toupper('aBc') + toupper('DeF')" -Note: When adding a string type returning generic function to a symbol -table the 'add_function' is invoked. The example below demonstrates -how this can be done: +Note17: When adding a string type returning generic function to a +symbol table the 'add_function' is invoked. The example below +demonstrates how this can be done: toupper tu; @@ -2255,7 +2493,7 @@ how this can be done: symbol_table.add_function("toupper",tu); -Note: Two further refinements to the type checking facility are the +Note18: Two further refinements to the type checking facility are the possibilities of a variable number of common types which can be accomplished by using a wildcard '*' and a special 'any type' which is done using the '?' character. It should be noted that the wildcard @@ -2263,7 +2501,7 @@ operator is associated with the previous type in the sequence and implies one or more of that type. template - struct zoo : public exprtk::igeneric_function + struct zoo final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -2272,7 +2510,7 @@ implies one or more of that type. : exprtk::igeneric_function("SVT*V?") {} - inline T operator()(parameter_list_t parameters) + inline T operator()(parameter_list_t parameters) override { ... } @@ -2322,7 +2560,7 @@ simple and efficient dispatch to a specific implementation for that particular parameter sequence can be performed. template - struct roo : public exprtk::igeneric_function + struct roo final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -2332,7 +2570,7 @@ particular parameter sequence can be performed. {} inline T operator()(const std::size_t& ps_index, - parameter_list_t parameters) + parameter_list_t parameters) override { ... } @@ -2360,7 +2598,7 @@ depending on the input parameter sequence with which the function is invoked. template - struct foo : public exprtk::igeneric_function + struct foo final : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; @@ -2375,7 +2613,7 @@ invoked. // Scalar value returning invocations inline T operator()(const std::size_t& ps_index, - parameter_list_t parameters) + parameter_list_t parameters) override { ... } @@ -2383,7 +2621,7 @@ invoked. // String value returning invocations inline T operator()(const std::size_t& ps_index, std::string& result, - parameter_list_t& parameters) + parameter_list_t& parameters) override { ... } @@ -2401,7 +2639,7 @@ are defined as follows: The parameter sequence definitions are identical to the previously -define igeneric_function, with the exception of the inclusion of the +defined igeneric_function, with the exception of the inclusion of the return type - which can only be either a scalar T or a string S. @@ -2412,38 +2650,91 @@ returning a single scalar value and consuming up to six parameters as input. All composited functions are registered with a symbol table, allowing -them to call other functions that have been registered with the symbol -table instance. Furthermore the functions can be recursive in nature -due to the inherent function prototype forwarding that occurs during -construction. The following example defines, by using two different -methods, composited functions and implicitly registering the functions -with the denoted symbol table. +them to call other functions and use variables that have been +registered with the symbol table instance. Furthermore the functions +can be recursive in nature due to the inherent function prototype +forwarding that occurs during construction. The following example +defines, by using two different methods, composited functions and +implicitly registering the functions with the denoted symbol table. typedef exprtk::symbol_table symbol_table_t; typedef exprtk::function_compositor compositor_t; typedef typename compositor_t::function function_t; + T avogadro = T(6.022e23); + symbol_table_t symbol_table; + symbol_table.add_constant("avogadro", avogadro); + compositor_t compositor(symbol_table); - // define function koo0(v1,v2) { ... } - compositor - .add( - function_t( - "koo0", - " 1 + cos(v1 * v2) / 3;", - "v1","v2")); + // Define function koo0(v1, v2) { ... } + compositor.add( + function_t("koo0"), + .vars("v1", "v2") + .expression + ( + " 1 + cos(v1 * v2) / avogadro; " + )); + + // Define function koo1(x, y, z) { ... } + compositor.add( + function_t() + .name("koo1") + .var("x").var("y").var("z") + .expression + ( + "1 + koo0(x * y, 3) / z;" + )); + + +A function compositor can also be instantiated without a symbol_table. +When this is the case an internal symbol_table is used for holding the +references to the composited functions. + + compositor_t compositor; + + // Define function koo2(v1, v2) { ... } + compositor.add( + function_t("koo2"), + .vars("v1", "v2", "v3") + .expression + ( " abs(v1 * v2) / v3; " )); + + +When wanting to reference functions from the compositor above in an +expression, the compositor's symbol_table will need to be registered +with the expression prior to compilation, as is demonstrated in the +following code: + + expression_t expression; + . + . + expression.register_symbol_table(compositor.symbol_table()); + + +In the situation where more than one symbol table's contents will be +required by the functions being composited, then those symbol tables +can be registered as auxiliary symbol tables with the compositor: + + symbol_table_t global_symbol_table; + symbol_table_t local_symbol_table; + . + . + . + compositor_t compositor; + + compositor.add_auxiliary_symtab(global_symbol_table); + compositor.add_auxiliary_symtab(local_symbol_table ); - // define function koo1(x,y,z) { ... } - compositor - .add(function_t() - .name("koo1") - .var("x").var("y").var("z") - .expression("1 + cos(x * y) / z;")); +Note19: In the event, that two or more symbol tables contain similarly +named variables, vectors, strings or functions, the order of +registration with the compositor shall determine the symbol table from +which the target symbol will be referenced. -(6) Using Functions In Expressions +(7) Using Functions In Expressions For the above denoted custom and composited functions to be used in an expression, an instance of each function needs to be registered with a symbol_table that has been associated with the expression instance. @@ -2467,26 +2758,27 @@ The following demonstrates how all the pieces are put together: symbol_table.add_function("boo",b); symbol_table.add_function("too",t); - symbol_table.add_function("toupper", - tu, - symbol_table_t::e_ft_strfunc); + symbol_table + .add_function("toupper", tu, symbol_table_t::e_ft_strfunc); - compositor - .add(function_t() - .name("koo") - .var("v1") - .var("v2") - .expression("1 + cos(v1 * v2) / 3;")); + compositor.add( + function_t("koo") + .var("v1") + .var("v2") + .expression + ( + "1 + cos(v1 * v2) / 3;" + )); expression_t expression; expression.register_symbol_table(symbol_table); - std::string expression_str = - " if (foo(1,2,3) + boo(1) > boo(1/2,2/3,3/4,4/5)) " - " koo(3,4); " - " else " - " too(2 * v1 + v2 / 3, 'abcdef'[2:4], 3.3); " - " "; + const std::string expression_str = + " if (foo(1,2,3) + boo(1) > boo(1/2, 2/3, 3/4, 4/5)) " + " koo(3,4); " + " else " + " too(2 * v1 + v2 / 3, 'abcdef'[2:4], 3.3); " + " "; parser_t parser; parser.compile(expression_str,expression); @@ -2494,31 +2786,31 @@ The following demonstrates how all the pieces are put together: expression.value(); -(7) Function Side-Effects +(8) Function Side-Effects All function calls are assumed to have side-effects by default. This assumption implicitly disables constant folding optimisations when all parameters being passed to the function are deduced as being constants at compile time. If it is certain that the function being registered does not have any -side effects and can be correctly constant folded where appropriate, +side-effects and can be correctly constant folded where appropriate, then during the construction of the function the side-effect trait of the function can be disabled. template - struct foo : public exprtk::ifunction + struct foo final : public exprtk::ifunction { foo() : exprtk::ifunction(3) { exprtk::disable_has_side_effects(*this); } - T operator()(const T& v1, const T& v2, const T& v3) + T operator()(const T& v1, const T& v2, const T& v3) override { ... } }; -(8) Zero Parameter Functions +(9) Zero Parameter Functions When either an ifunction, ivararg_function or igeneric_function derived type is defined with zero number of parameters, there are two calling conventions within expressions that are allowed. For a @@ -2530,28 +2822,28 @@ as follows: By default the zero parameter trait is disabled. In order to enable -it, a process similar to that of enabling of the side effect trait is +it, a process similar to that of enabling of the side-effect trait is carried out: template - struct foo : public exprtk::ivararg_function + struct foo final : public exprtk::ivararg_function { foo() { exprtk::enable_zero_parameters(*this); } - inline T operator()(const std::vector& arglist) + inline T operator()(const std::vector& arglist) override { ... } }; -Note: For the igeneric_function type, there also needs to be a 'Z' +Note20: For the igeneric_function type, there also needs to be a 'Z' parameter sequence defined in order for the zero parameter trait to properly take effect otherwise a compilation error will occur. -(9) Free Functions +(10) Free Functions The ExprTk symbol table supports the registration of free functions and lambdas (anonymous functors) for use in expressions. The basic requirements are similar to those found in ifunction derived user @@ -2561,16 +2853,21 @@ a return type that is also scalar. Furthermore such functions will by default be assumed to have side-effects and hence will not participate in constant folding optimisations. -In the following example, a two input parameter free function named -'compute1', and a three input parameter lambda named 'compute2' will -be registered with the given symbol_table instance: +In the following example, a one input parameter free function named +'compute1', a two input parameter template free function named +'compute2' and a three input parameter lambda named 'compute3' will be +registered with the given symbol_table instance: + double compute1(double v0) + { + return 2.0 * std::abs(v0); + } - double compute1(double v0, double v1) + template + T compute2(T v0, T v1) { return 2.0 * v0 + v1 / 3.0; } - . . . @@ -2580,13 +2877,30 @@ be registered with the given symbol_table instance: symbol_table_t symbol_table; symbol_table.add_function("compute1", compute1); + symbol_table.add_function("compute2", compute2); symbol_table.add_function( - "compute2", + "compute3", [](double v0, double v1, double v2) -> double { return v0 / v1 + v2; }); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Note21: Similar to variables registered with symbol_table instances, +for any of the following function providers: + + 1. ifunction + 2. ivararg_function + 3. igeneric_function + 4. function_compositor + 5. Free function + 7. Lambda + + +Their instance lifetimes must exceed the symbol_tables and expressions +they are registered with. In the event that is not the case, the +expected result shall be undefined behaviour. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 16 - EXPRESSION DEPENDENTS] Any expression that is not a literal (aka constant) will have @@ -2633,8 +2947,8 @@ dependents of the given expression: typedef typename parser_t:: dependent_entity_collector::symbol_t symbol_t; - std::string expression_string = - "z := abs(x + sin(2 * pi / y))"; + const std::string expression_string = + "z := abs(x + sin(2 * pi / y))"; T x,y,z; @@ -2648,7 +2962,7 @@ dependents of the given expression: expression_t expression; expression.register_symbol_table(symbol_table); - //Collect only variable and function symbols + // Collect only variable and function symbols parser.dec().collect_variables() = true; parser.dec().collect_functions() = true; @@ -2663,7 +2977,7 @@ dependents of the given expression: for (std::size_t i = 0; i < symbol_list.size(); ++i) { - symbol_t& symbol = symbol_list[i]; + const symbol_t& symbol = symbol_list[i]; switch (symbol.second) { @@ -2675,9 +2989,9 @@ dependents of the given expression: } -Note: The 'symbol_t' type is a std::pair comprising of the symbol name -(std::string) and the associated type of the symbol as denoted by the -cases in the switch statement. +Note22: The 'symbol_t' type is a std::pair comprising of the symbol +name (std::string) and the associated type of the symbol as denoted by +the cases in the switch statement. Having particular symbols (variable or function) present in an expression is one form of dependency. Another and just as interesting @@ -2694,17 +3008,17 @@ associated assignments: (5) None x + y + z -Note: In expression 4, both variables 'w' and 'z' are denoted as being -assignments even though only one of them can ever be modified at the -time of evaluation. Furthermore the determination of which of the two -variables the modification will occur upon can only be known with +Note23: In expression 4, both variables 'w' and 'z' are denoted as +being assignments even though only one of them can ever be modified at +the time of evaluation. Furthermore the determination of which of the +two variables the modification will occur upon can only be known with certainty at evaluation time and not beforehand, hence both are listed as being candidates for assignment. The following builds upon the previous example demonstrating the usage of the DEC in determining the 'assignments' of the given expression: - //Collect assignments + // Collect assignments parser.dec().collect_assignments() = true; if (!parser.compile(expression_string,expression)) @@ -2729,10 +3043,10 @@ of the DEC in determining the 'assignments' of the given expression: } -Note: The assignments will only consist of variable types and as such -will not contain symbols denoting functions. +Note24: The assignments will only consist of variable types and as +such will not contain symbols denoting functions. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 17 - HIERARCHIES OF SYMBOL TABLES] Most situations will only require a single symbol_table instance to be @@ -2745,7 +3059,7 @@ variables from a large set of potential variables, functions or constants, it becomes evident that grouping variables into layers of symbol_tables will simplify and streamline the overall process. -A suggested hierarchy of symbol tables is as follows: +A recommended hierarchy of symbol tables is the following: (a) Global constant value symbol table (b) Global non side-effect functions symbol table @@ -2768,10 +3082,10 @@ variables are: (b) Global non side-effect functions symbol table This symbol table will contain only user defined functions that will -not incur any side-effects that are visible to any of the expressions -that invoke them. These functions will be thread-safe or threading -invariant and will not maintain any form of state between invocations. -Examples of such functions are: +not incur any side-effects that are observable to any of the +expressions that invoke them. These functions shall be thread-safe or +threading invariant and will not maintain any form of state between +invocations. Examples of such functions are: (1) calc_volume_of_sphere(r) (2) distance(x0,y0,x1,y1) @@ -2810,8 +3124,8 @@ own instances of those variables. Examples of such variables could be: (2) customer_name -The following is a diagram depicting the possible version of the -denoted symbol table hierarchies. In the diagram there are two unique +The following is a diagram depicting a possible variant of the denoted +symbol table hierarchies. In the diagram there are two unique expressions, each of which have a reference to the Global constant, functions and variables symbol tables and an exclusive reference to a local symbol table. @@ -2891,7 +3205,7 @@ then compiled and later on evaluated: expression .register_symbol_table(glbl_variable_symbol_table); - std::string expression_str = + const std::string expression_str = "abs(temp_inside - temp_outside) + 2 * speed_of_light / x"; parser_t parser; @@ -2908,7 +3222,7 @@ then compiled and later on evaluated: .... } - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 18 - UNKNOWN UNKNOWNS] In this section we will discuss the process of handling expressions @@ -3009,6 +3323,9 @@ component. typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; + T x = T(123.456); + T y = T(789.123); + symbol_table_t unknown_var_symbol_table; symbol_table_t symbol_table; @@ -3022,7 +3339,7 @@ component. parser_t parser; parser.enable_unknown_symbol_resolver(); - std::string expression_str = "x + abs(y / 3k) * z + 2"; + const std::string expression_str = "x + abs(y / 3k) * z + 2"; parser.compile(expression_str,expression); @@ -3043,7 +3360,7 @@ after which the expression itself can be evaluated. unknown_var_symbol_table.get_variable_list(variable_list); - for (auto& var_name : variable_list) + for (const auto& var_name : variable_list) { T& v = unknown_var_symbol_table.variable_ref(var_name); @@ -3055,7 +3372,7 @@ after which the expression itself can be evaluated. expression.value(); -Note: As previously mentioned the default USR will automatically +Note25: As previously mentioned the default USR will automatically assume any unknown symbol to be a valid scalar variable, and will then proceed to add said symbol as a variable to the primary symbol_table of the associated expression during the compilation process. However a @@ -3083,14 +3400,14 @@ simple user defined USR: typedef exprtk::parser parser_t; template - struct my_usr : public parser_t::unknown_symbol_resolver + struct my_usr final : public parser_t::unknown_symbol_resolver { typedef typename parser_t::unknown_symbol_resolver usr_t; bool process(const std::string& unknown_symbol, typename usr_t::usr_symbol_type& st, T& default_value, - std::string& error_message) + std::string& error_message) override { if (0 != unknown_symbol.find("var_")) { @@ -3107,6 +3424,9 @@ simple user defined USR: ... + T x = T(123.456); + T y = T(789.123); + symbol_table_t unknown_var_symbol_table; symbol_table_t symbol_table; @@ -3128,25 +3448,25 @@ simple user defined USR: In the example above, a user specified USR is defined, and is -registered with the parser enabling the USR functionality. Then when -an unknown symbol is encountered during the compilation process, the -USR's process method will be invoked. The USR in the example will only -'accept' unknown symbols that have a prefix of 'var_' as being valid -variables, all other unknown symbols will result in a compilation -error being raised. +registered with the parser enabling the USR functionality. +Subsequently during the compilation process when an unknown symbol is +encountered, the USR's process method will be invoked. The USR in the +example will only 'accept' unknown symbols that have a prefix of +'var_' as being valid variables, all other unknown symbols will result +in a compilation error being raised. In the example above the callback of the USR that is invoked during the unknown symbol resolution process only allows for scalar variables to be defined and resolved - as that is the simplest and most common form. -There is also an extended version of the callback that can be +There is a further extended version of the callback that can be overridden that will allow for more control and choice over the type of symbol being resolved. The following is an example definition of said extended callback: template - struct my_usr : public parser_t::unknown_symbol_resolver + struct my_usr final : public parser_t::unknown_symbol_resolver { typedef typename parser_t::unknown_symbol_resolver usr_t; @@ -3154,9 +3474,9 @@ said extended callback: : usr_t(usr_t::e_usrmode_extended) {} - virtual bool process(const std::string& unknown_symbol, - symbol_table_t& symbol_table, - std::string& error_message) + bool process(const std::string& unknown_symbol, + symbol_table_t& symbol_table, + std::string& error_message) override { bool result = false; @@ -3199,14 +3519,14 @@ table will now have the previously detected unknown symbol registered, it will be correctly resolved and the general parsing processing can then resume as per normal. -Note: In order to have the USR's extended mode callback be invoked It -is necessary to pass the e_usrmode_extended enum value during the +Note26: In order to have the USR's extended mode callback be invoked +it is necessary to pass the e_usrmode_extended enum value during the constructor of the user defined USR. -Note: The primary symbol table for an expression is the first symbol +Note27: 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 +Note28: 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 @@ -3216,15 +3536,15 @@ the following are required: (*) e_usr_variable_type (*) e_usr_constant_type -Note: For a successful symbol resolution using the extended USR all of -the following are required: +Note29: 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] The parser can be configured via its settings instance to either allow @@ -3253,17 +3573,17 @@ The list of available base functions is as follows: The above mentioned base functions can be either enabled or disabled 'all' at once, as is demonstrated below: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - parser.settings().disable_all_base_functions(); + parser.settings().disable_all_base_functions(); - parser + parser .compile("2 * abs(2 - 3)",expression); // compilation failure - parser.settings().enable_all_base_functions(); + parser.settings().enable_all_base_functions(); - parser + parser .compile("2 * abs(2 - 3)",expression); // compilation success @@ -3271,21 +3591,21 @@ One can also enable or disable specific base functions. The following example demonstrates the disabling of the trigonometric functions 'sin' and 'cos': - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - parser.settings() + parser.settings() .disable_base_function(settings_t::e_bf_sin) .disable_base_function(settings_t::e_bf_cos); - parser + parser .compile("(sin(x) / cos(x)) == tan(x)",expression); // failure - parser.settings() + parser.settings() .enable_base_function(settings_t::e_bf_sin) .enable_base_function(settings_t::e_bf_cos); - parser + parser .compile("(sin(x) / cos(x)) == tan(x)",expression); // success @@ -3302,24 +3622,24 @@ The list of available control flow structures is as follows: The above mentioned control flow structures can be either enabled or disabled 'all' at once, as is demonstrated below: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - std::string program = - " var x := 0; " - " for (var i := 0; i < 10; i += 1) " - " { " - " x += i; " - " } "; + const std::string program = + " var x := 0; " + " for (var i := 0; i < 10; i += 1) " + " { " + " x += i; " + " } "; - parser.settings().disable_all_control_structures(); + parser.settings().disable_all_control_structures(); - parser + parser .compile(program,expression); // compilation failure - parser.settings().enable_all_control_structures(); + parser.settings().enable_all_control_structures(); - parser + parser .compile(program,expression); // compilation success @@ -3327,26 +3647,26 @@ One can also enable or disable specific control flow structures. The following example demonstrates the disabling of the for-loop control flow structure: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - std::string program = - " var x := 0; " - " for (var i := 0; i < 10; i += 1) " - " { " - " x += i; " - " } "; + const std::string program = + " var x := 0; " + " for (var i := 0; i < 10; i += 1) " + " { " + " x += i; " + " } "; - parser.settings() + parser.settings() .disable_control_structure(settings_t::e_ctrl_for_loop); - parser + parser .compile(program,expression); // failure - parser.settings() + parser.settings() .enable_control_structure(settings_t::e_ctrl_for_loop); - parser + parser .compile(program,expression); // success @@ -3359,17 +3679,17 @@ The list of available logical operators is as follows: The above mentioned logical operators can be either enabled or disabled 'all' at once, as is demonstrated below: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - parser.settings().disable_all_logic_ops(); + parser.settings().disable_all_logic_ops(); - parser + parser .compile("1 or not(0 and 1)",expression); // compilation failure - parser.settings().enable_all_logic_ops(); + parser.settings().enable_all_logic_ops(); - parser + parser .compile("1 or not(0 and 1)",expression); // compilation success @@ -3377,19 +3697,19 @@ One can also enable or disable specific logical operators. The following example demonstrates the disabling of the 'and' logical operator: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - parser.settings() + parser.settings() .disable_logic_operation(settings_t::e_logic_and); - parser + parser .compile("1 or not(0 and 1)",expression); // failure - parser.settings() + parser.settings() .enable_logic_operation(settings_t::e_logic_and); - parser + parser .compile("1 or not(0 and 1)",expression); // success @@ -3402,17 +3722,17 @@ The list of available arithmetic operators is as follows: The above mentioned arithmetic operators can be either enabled or disabled 'all' at once, as is demonstrated below: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - parser.settings().disable_all_arithmetic_ops(); + parser.settings().disable_all_arithmetic_ops(); - parser + parser .compile("1 + 2 / 3",expression); // compilation failure - parser.settings().enable_all_arithmetic_ops(); + parser.settings().enable_all_arithmetic_ops(); - parser + parser .compile("1 + 2 / 3",expression); // compilation success @@ -3420,19 +3740,19 @@ One can also enable or disable specific arithmetic operators. The following example demonstrates the disabling of the addition '+' arithmetic operator: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - parser.settings() + parser.settings() .disable_arithmetic_operation(settings_t::e_arith_add); - parser + parser .compile("1 + 2 / 3",expression); // failure - parser.settings() + parser.settings() .enable_arithmetic_operation(settings_t::e_arith_add); - parser + parser .compile("1 + 2 / 3",expression); // success @@ -3445,17 +3765,17 @@ The list of available inequality operators is as follows: The above mentioned inequality operators can be either enabled or disabled 'all' at once, as is demonstrated below: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - parser.settings().disable_all_inequality_ops(); + parser.settings().disable_all_inequality_ops(); - parser + parser .compile("1 < 3",expression); // compilation failure - parser.settings().enable_all_inequality_ops(); + parser.settings().enable_all_inequality_ops(); - parser + parser .compile("1 < 3",expression); // compilation success @@ -3463,19 +3783,19 @@ One can also enable or disable specific inequality operators. The following example demonstrates the disabling of the less-than '<' inequality operator: - parser_t parser; - expression_t expression; + parser_t parser; + expression_t expression; - parser.settings() + parser.settings() .disable_inequality_operation(settings_t::e_ineq_lt); - parser + parser .compile("1 < 3",expression); // failure - parser.settings() + parser.settings() .enable_inequality_operation(settings_t::e_ineq_lt); - parser + parser .compile("1 < 3",expression); // success @@ -3488,24 +3808,24 @@ The list of available assignment operators is as follows: The above mentioned assignment operators can be either enabled or disabled 'all' at once, as is demonstrated below: - parser_t parser; - expression_t expression; - symbol_table_t symbol_table; + T x = T(0); - T x = T(0); + parser_t parser; + expression_t expression; + symbol_table_t symbol_table; - symbol_table.add_variable("x",x); + symbol_table.add_variable("x",x); - expression.register_symbol_table(symbol_table); + expression.register_symbol_table(symbol_table); - parser.settings().disable_all_assignment_ops(); + parser.settings().disable_all_assignment_ops(); - parser + parser .compile("x := 3",expression); // compilation failure - parser.settings().enable_all_assignment_ops(); + parser.settings().enable_all_assignment_ops(); - parser + parser .compile("x := 3",expression); // compilation success @@ -3513,68 +3833,68 @@ One can also enable or disable specific assignment operators. The following example demonstrates the disabling of the '+=' addition assignment operator: - parser_t parser; - expression_t expression; - symbol_table_t symbol_table; + T x = T(0); - T x = T(0); + parser_t parser; + expression_t expression; + symbol_table_t symbol_table; - symbol_table.add_variable("x",x); + symbol_table.add_variable("x",x); - expression.register_symbol_table(symbol_table); + expression.register_symbol_table(symbol_table); - parser.settings() + parser.settings() .disable_assignment_operation(settings_t::e_assign_addass); - parser + parser .compile("x += 3",expression); // failure - parser.settings() + parser.settings() .enable_assignment_operation(settings_t::e_assign_addass); - parser + parser .compile("x += 3",expression); // success -Note: In the event of a base function being disabled, one can redefine -the base function using the standard custom function definition -process. In the following example the 'sin' function is disabled then -redefined as a function taking degree input. +Note30: In the event of a base function being disabled, one can +redefine the base function using the standard custom function +definition process. In the following example the 'sin' function is +disabled then redefined as a function taking degree input. - template - struct sine_deg : public exprtk::ifunction - { - sine_deg() : exprtk::ifunction(1) {} + template + struct sine_deg final : public exprtk::ifunction + { + sine_deg() : exprtk::ifunction(1) {} - inline T operator()(const T& v) - { - const T pi = exprtk::details::numeric::constant::pi; - return std::sin((v * T(pi)) / T(180)); - } - }; + inline T operator()(const T& v) override + { + const T pi = exprtk::details::numeric::constant::pi; + return std::sin((v * T(pi)) / T(180)); + } + }; ... - typedef exprtk::symbol_table symbol_table_t; - typedef exprtk::expression expression_t; - typedef exprtk::parser parser_t; + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; - typedef typename parser_t::settings_store settings_t; + typedef typename parser_t::settings_store settings_t; - sine_deg sine; + sine_deg sine; - symbol_table.add_reserved_function("sin",sine); + symbol_table.add_reserved_function("sin",sine); - expression_t expression; + expression_t expression; - expression.register_symbol_table(symbol_table); + expression.register_symbol_table(symbol_table); - parser_t parser; + parser_t parser; - parser.settings() - .disable_base_function(settings_t::e_bf_sin); + parser.settings() + .disable_base_function(settings_t::e_bf_sin); - parser.compile("1 + sin(30)",expression); + parser.compile("1 + sin(30)",expression); In the example above, the custom 'sin' function is registered with the @@ -3584,7 +3904,7 @@ provided symbol names when calling the standard 'add_function' method. Normally if a user specified symbol name conflicts with any of the ExprTk reserved words, the add_function call will fail. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 20 - EXPRESSION RETURN VALUES] ExprTk expressions can return immediately from any point by utilising @@ -3592,21 +3912,21 @@ the return call. Furthermore the return call can be used to transfer out multiple return values from within the expression. If an expression evaluation exits using a return point, the result of -the call to the 'value' method will be NaN, and it's expected that the -return values will be available from the results_context. +the call to the 'value' method will be NaN, and it is expected that +the return values will be available from the results_context. In the following example there are three return points in the expression. If neither of the return points are hit, then the expression will return normally. - std::string expression_string = - " if (x < y) " - " return [x + 1,'return-call 1']; " - " else if (x > y) " - " return [y / 2, y + 1, 'return-call 2']; " - " else if (equal(x,y)) " - " x + y; " - " return [x, y, x + y, x - y, 'return-call 3'] "; + const std::string expression_string = + " if (x < y) " + " return [x + 1,'return-call 1']; " + " else if (x > y) " + " return [y / 2, y + 1, 'return-call 2']; " + " else if (equal(x,y)) " + " x + y; " + " return [x, y, x + y, x - y, 'return-call 3'] "; typedef exprtk::symbol_table symbol_table_t; typedef exprtk::expression expression_t; @@ -3628,7 +3948,7 @@ expression will return normally. T result = expression.value(); - if (expression.results().count()) + if (expression.return_invoked()) { typedef exprtk::results_context results_context_t; typedef typename results_context_t::type_store_t type_t; @@ -3658,9 +3978,60 @@ expression will return normally. } -Note: Processing of the return results is similar to that of the +In the above example, there are three possible "return" points and one +regular result. Only one of the four paths can ever be realised. Hence +it is necessary to capture the result of the expression value method +call. In the event, the call to return_invoked is not true then the +non-return code path was executed and the result of the evaluation +will be the result of the expression's value method. + +Note31: Processing of the return results is similar to that of the generic function call parameters. +The results_context provides getter methods for each of the possible +return types (scalar, vector and string) and can be used as follows: + + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + const std::string expression_str = + " if (x > y) " + " return [1]; " + " else " + " return [ x, x + y, 2 * v, s + 'world' ]; "; + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + symbol_table.add_variable ("x", x); + symbol_table.add_variable ("y", y); + symbol_table.add_variable ("z", z); + symbol_table.add_vector ("v", v); + symbol_table.add_stringvar("s", s); + + parser.compile(expression_str, expression); + + expression.value(); + + typedef exprtk::results_context results_context_t; + const results_context_t& results = expression.results(); + + if (results.count() == 4) + { + T result_x0; + T result_x1; + std::string result_s; + std::vector result_v; + + results.get_scalar(0, result_x0); + results.get_scalar(1, result_x1); + results.get_string(3, result_s ); + results.get_vector(2, result_v ); + } + + It is however recommended that if there is to be only a single flow of execution through the expression, that the simpler approach of registering external variables of appropriate type be used. @@ -3675,11 +4046,11 @@ values. typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; - std::string expression_string = - " var x := 123.456; " - " var s := 'ijk'; " - " result0 := x + 78.90; " - " result1 := s + '123' "; + const std::string expression_string = + " var x := 123.456; " + " var s := 'ijk'; " + " result0 := x + 78.90; " + " result1 := s + '123' "; double result0; std::string result1; @@ -3705,17 +4076,79 @@ two result variables are defined to hold the values named result0 and result1 respectively. The first is of scalar type (double), the second is of string type. Once the expression has been evaluated, the two variables will have been updated with the new result values, and can -then be further utilised from within the calling program. +then be further utilised from within the calling host program. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +There will be times when an expression may have multiple exit paths, +where not all the paths will be return-statement based. The following +example builds upon the previous examples, but this time at least one +path is not return based. -[SECTION 21 - COMPILATION ERRORS] -When attempting to compile a malformed or otherwise erroneous ExprTk -expression, the compilation process will result in an error, as is -indicated by the 'compile' method returning a false value. A -diagnostic indicating the first error encountered and its cause can be -obtained by invoking the 'error' method, as is demonstrated in the -following example: + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + double x = 100.0; + double y = 200.0; + + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + symbol_table.add_variable ("x", x); + symbol_table.add_variable ("y", y); + + expression.register_symbol_table(symbol_table); + + const std::string expression_string = + " for (var i := 0; i < 10; i += 1) " + " { " + " if (i > x) " + " { " + " return [x + y, 'return-call 1']; " + " } " + " else if (i > y) " + " { " + " return [x - y, 'return-call 2']; " + " } " + " }; " + " " + " x / y "; + + parser.compile(expression_str, expression); + + const auto result = expression.value(); + + if (expression.return_invoked()) + { + const auto results = expression.results(); + + for (std::size_t i = 0; i < results.count(); ++i) + { + const auto& rtrn_result = results[i]; + . + . + . + } + } + else + { + printf("result: %f\n",result); + } + + +After having called the value method on the expression, calling the +return_invoked method will determine if the expression completed due +to a return statement being invoked or if it finished normally. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[SECTION 21 - COMPILATION ERRORS] +When attempting to compile a malformed or otherwise erroneous ExprTk +expression, the compilation process will result in an error, as is +indicated by the 'compile' method returning a false value. A +diagnostic indicating the first error encountered and its cause can be +obtained by invoking the 'error' method, as is demonstrated in the +following example: if (!parser.compile(expression_string,expression)) { @@ -3733,6 +4166,9 @@ A parser_error object will contain an error diagnostic, an error mode string. The following example demonstrates the enumeration of error(s) in the event of a failed compilation. + typedef exprtk::parser parser_t; + typedef exprtk::parser_error::type error_t; + if (!parser.compile(expression_string,expression)) { for (std::size_t i = 0; i < parser.error_count(); ++i) @@ -3758,7 +4194,6 @@ symbol_table instance and is not a locally defined variable, once compiled the above denoted post compilation error handling code shall produce the following output: - Error: ERR184 - Undefined symbol: 'x' Error[00] Pos:17 Type:[Syntax] Msg: ERR184 - Undefined symbol: 'x' @@ -3777,7 +4212,7 @@ demonstrated by the following example: exprtk::parser_error::update_error(error,program_str); - printf("Error[%02d] at line: %d column: %d\n", + printf("Error[%0lu] at line: %lu column: %lu\n", i, error.line_no, error.column_no); @@ -3787,7 +4222,7 @@ demonstrated by the following example: } -Note: There are five distinct error modes in ExprTk which denote the +Note32: There are five distinct error modes in ExprTk which denote the class of an error. These classes are as follows: (a) Syntax @@ -3827,12 +4262,48 @@ find, within the symbol_table, symbols representing variables or functions, to being unable to create new variables in the symbol_table via the 'unknown symbol resolver' mechanism. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Note33: The function compositor also supports error message handling +similar to how it is done via the parser. The following demonstrates +how after a failed function composition the associated errors can be +enumerated. + + typedef exprtk::function_compositor compositor_t; + typedef typename compositor_t::function function_t; + + compositor_t compositor; + + const bool compositor_result = + compositor.add( + function_t("foobar") + .vars("x","y") + .expression + ( " x + y / z " )); + + if (!compositor_result) + { + printf("Error: %s\n", compositor.error().c_str()); + + for (std::size_t i = 1; i < compositor.error_count(); ++i) + { + typedef exprtk::parser_error::type error_t; + + error_t error = compositor.get_error(i); + + printf("Err No.: %02d Pos: %02d Type: [%14s] Msg: %s\n", + static_cast(i), + static_cast(error.token.position), + exprtk::parser_error::to_str(error.mode).c_str(), + error.diagnostic.c_str()); + } + } + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 22 - RUNTIME LIBRARY PACKAGES] -ExprTk contains a set of simple extensions, that provide -functionalities beyond basic numerical calculations. Currently the -available packages are: +ExprTk includes a range of extensions, that provide functionalities +beyond simple numerical calculations. Currently the available packages +are: +---+--------------------+-----------------------------------+ | # | Package Name | Namespace/Type | @@ -3854,16 +4325,16 @@ file I/O package is made available for the given expression: exprtk::rtl::io::file::package fileio_package; - std::string expression_string = - " var file_name := 'file.txt'; " - " var stream := null; " - " " - " stream := open(file_name,'w'); " - " " - " write(stream,'Hello world....\n'); " - " " - " close(stream); " - " "; + const std::string expression_string = + " var file_name := 'file.txt'; " + " var stream := null; " + " " + " stream := open(file_name,'w'); " + " " + " write(stream,'Hello world....\n'); " + " " + " close(stream); " + " "; symbol_table_t symbol_table; symbol_table.add_package(fileio_package); @@ -3890,19 +4361,20 @@ file I/O package is made available for the given expression: (3) Vector Operations functions: - (a) all_true (b) all_false - (c) any_true (d) any_false - (e) count (f) copy - (g) rotate-left (h) rotate-right - (i) shift-left (j) shift-right - (k) sort (l) nth_element - (m) iota (n) sumk - (o) axpy (p) axpby - (q) axpyz (r) axpbyz - (s) axpbz (t) dot - (u) dotk - - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(a) all_true (b) all_false +(c) any_true (d) any_false +(e) assign (f) count +(g) copy (h) reverse +(i) rotate-left (j) rotate-right +(k) shift-left (l) shift-right +(m) sort (n) nth_element +(o) iota (p) sumk +(q) axpy (r) axpby +(s) axpyz (t) axpbyz +(u) axpbz (v) dot +(w) dotk (x) diff + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [SECTION 23 - HELPERS & UTILS] The ExprTk library provides a series of usage simplifications via @@ -3929,7 +4401,7 @@ expression then the return value of the function will be false, otherwise it will be true. An example use of the given routine is as follows: - std::string expression = "x + abs(y / z)"; + const std::string expression = "x + abs(y / z)"; std::vector variable_list; @@ -3953,7 +4425,7 @@ expression then the return value of the function will be false, otherwise it will be true. An example use of the given routine is as follows: - std::string expression = "x + abs(y / cos(1 + z))"; + const std::string expression = "x + abs(y / cos(1 + z))"; std::deque function_list; @@ -3968,16 +4440,16 @@ follows: printf("An error occurred."); -Note: When either the 'collect_variables' or 'collect_functions' free -functions return true - that does not necessarily indicate the +Note34: When either the 'collect_variables' or 'collect_functions' +free functions return true - that does not necessarily indicate the expression itself is valid. It is still possible that when compiled the expression may have certain 'type' related errors - though it is highly likely that no semantic errors will occur if either return true. -Note: The default interface provided for both the collect_variables +Note35: The default interface provided for both the collect_variables and collect_functions free_functions, assumes that expressions will -only be utilising the ExprTk reserved functions (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 incorporated during the compilation and @@ -3998,7 +4470,7 @@ expression string are passed to the exprtk::collect_functions routine. symbol_table.add_function("foo",foo); - std::string expression = "x + foo(y / cos(1 + z))"; + const std::string expression = "x + foo(y / cos(1 + z))"; std::deque function_list; @@ -4032,7 +4504,7 @@ are as follows: T result = T(0); // No variables overload - std::string no_vars = "abs(1 - (3 / pi)) * 5"; + const std::string no_vars = "abs(1 - (3 / pi)) * 5"; if (!exprtk::compute(no_vars,result)) printf("Failed to compute: %s",no_vars.c_str()); @@ -4040,9 +4512,9 @@ are as follows: printf("Result: %15.5f\n",result); // One variable 'x' overload - T x = 123.456; + T x = T(123.456); - std::string one_var = "abs(x - (3 / pi)) * 5"; + const std::string one_var = "abs(x - (3 / pi)) * 5"; if (!exprtk::compute(one_var, x, result)) printf("Failed to compute: %s",one_var.c_str()); @@ -4050,9 +4522,9 @@ are as follows: printf("Result: %15.5f\n",result); // Two variables 'x' and 'y' overload - T y = 789.012; + T y = T(789.012); - std::string two_var = "abs(x - (y / pi)) * 5"; + const std::string two_var = "abs(x - (y / pi)) * 5"; if (!exprtk::compute(two_var, x, y, result)) printf("Failed to compute: %s",two_var.c_str()); @@ -4060,9 +4532,9 @@ are as follows: printf("Result: %15.5f\n",result); // Three variables 'x', 'y' and 'z' overload - T z = 345.678; + T z = T(345.678); - std::string three_var = "abs(x - (y / pi)) * z"; + const std::string three_var = "abs(x - (y / pi)) * z"; if (!exprtk::compute(three_var, x, y, z, result)) printf("Failed to compute: %s",three_var.c_str()); @@ -4082,7 +4554,7 @@ name in string form. Example usage of the function is as follows: typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; - std::string expression_string = "sqrt(1 - (x^2))"; + const std::string expression_string = "sqrt(1 - (x^2))"; T x = T(0); @@ -4117,7 +4589,7 @@ function is as follows: typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; - std::string expression_string = "sqrt(1 - (x^2))"; + const std::string expression_string = "sqrt(1 - (x^2))"; T x = T(0); @@ -4156,7 +4628,7 @@ is as follows: typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; - std::string expression_string = "sqrt(1 - (x^2))"; + const std::string expression_string = "sqrt(1 - (x^2))"; T x = T(0); @@ -4195,7 +4667,7 @@ is as follows: typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; - std::string expression_string = "sqrt(1 - (x^2))"; + const std::string expression_string = "sqrt(1 - (x^2))"; T x = T(0); @@ -4220,9 +4692,635 @@ is as follows: x = T(45.6); T derivative2 = exprtk::third_derivative(expression, "x"); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[SECTION 24 - RUNTIME CHECKS] +The ExprTk library provides the ability to perform runtime checks +during expression evaluation so as to ensure memory access violations +errors are caught and handled without causing further issues. The +checks typically cover: + + 1. Vector access and handling + 2. String access and handling + 3. Loop iteration checks + 4. Compilation checkpointing + 5. Assert statements + + +(1) Vector Access Runtime Checks +Expressions that contain vectors where elements of the vectors may be +accessed using indexes that can only be determined at runtime may +result in memory access violations when the index is out of the +vector's bound. Some examples of problematic expressions are as +follows: + + 1. vec[i] + 2. vec[i + j] + 3. vec[i + 10] + 4. vec[i + vec[]] := x + y + 5. vec[i + j] <=> vec[i] + 6. vec[i + j] := (vec1 + vec2)[i + j] + + +In the above expressions, it is assumed that the values used in the +index operator may either exceed the vector bounds or precede the +vector's start, In short, the indexes may not necessarily be within +the range [0,vec[]). + +ExprTk provides the ability to inject a runtime check at the point of +index evaluation and handle situations where the index violates the +vector's bounds. This capability is done by registering a user- +implemented Vector Access Runtime Check (VARTC) to the parser before +expression compilation. Initially a VARTC can be defined as follows: + + struct my_vector_access_rtc final : + public exprtk::vector_access_runtime_check + { + bool handle_runtime_violation(violation_context& context) + override + { + // Handling of the violation + return ...; + } + }; + + +Then an instance of the VARTC can be registered with a parser instance +as follows: + + my_vector_access_rtc vartc; + + exprtk::symbol_table symbol_table; + + T i; + T x; + T y; + std::vector vec = { 0, 1, 2, 3, 4 }; + + symbol_table.add_variable("i" , i ); + symbol_table.add_variable("x" , x ); + symbol_table.add_variable("y" , y ); + symbol_table.add_vector ("vec", vec); + + exprtk::expression expression; + exprtk::parser parser; + + parser.register_vector_access_runtime_check(vartc); + + std::string expression = "vec[i + vec[]] := x + y"; + + parser.compile(expression_str, expression); + + try + { + expression.value(); + } + catch (std::runtime_error& rte) + { + printf("Exception: %s\n", rte.what()); + } + + +Note36: The lifetime of any parser or expression instance must not +exceed that of any VARTC instance that has been registered with it. + +When a vector access violation occurs, the registered VARTC instance's +handle_runtime_violation method will be invoked, coupled with it a +violation_context shall be provided that will contain the following +members: + + 1. base_ptr: Of type void*, which points to the first element + of the vector. The base_ptr can also be used as a key to + determine the vector upon which the access violation has + occurred. + + 2. end_ptr : Of type void*, which points to one position after + the last element of the vector + + 3. access_ptr: Of type void*, points to the memory location + which is the base_ptr offset by the derived index value. + + 4. type_size: Size of the vector's element type in bytes. This + value can be used to determine the number of elements in + the vector based on the base_ptr and end_ptr. + + +The implementation of the handle_runtime_violation method can at this +point perform various actions such as: + + 1. Log the violation + 2. Throw an exception (eg: std::runtime_error) + 3. Remedy the access_ptr to allow for the evaluation to continue + + +Note37: When employing option [3], handle_runtime_violation needs to +return true, otherwise the caller will assume an unhandled access +violation and default to using the base_ptr. + +It is recommended, at the very least, to throw an exception when +handling vector access violations and to only consider option [3] when +the the ramifications of changing the access_ptr are well understood. + +The following are simple examples of how the handle_runtime_violation +can be implemented. + +Example 1: Log the access violation to stdout and then throw a runtime +error exception: + + bool handle_runtime_violation(violation_context& context) override + { + printf("ERROR - Runtime vector access violation. " + "base: %p end: %p access: %p typesize: %lu\n", + context.base_ptr , + context.end_ptr , + context.access_ptr, + context.type_size); + + throw std::runtime_error("Runtime vector access violation."); + return false; + } + + +Example 2: Handle the access violation by resetting the access pointer +to the last value in the vector. + + bool handle_runtime_violation(violation_context& context) override + { + context.access_ptr = + static_cast(context.end_ptr) - context.type_size; + return true; + } + + +Note38: The return value of true in the above handler method signals +the caller to continue the vector access using the updated access_ptr. + + +(2) String Access Runtime Checks +Expressions that contain strings where elements or substrings of the +strings may be accessed using indexes that can only be determined at +runtime may result in memory access violations when the index or range +is out of the string's bound. Examples of problematic expressions are +as follows: + + 1. s[i : j + k] + 2. s[i : j + k][-x : y] + 3. (s1 + s2)[i : j + k] + 4. '01234'[5 + i] + 5. s += s[i : j + k] + 6. s[i : j + k] := 'chappy days'[1 : ] + + +To enable string access runtime checks all one needs to do is simply +use the following define before the ExprTk header is included or as +part of the compilation define parameters: + + exprtk_enable_range_runtime_checks + + +When the above define is used, and a string related runtime access +violation occurs a std::runtime_error exception will be thrown. The +following demonstrates the general flow of handling the access +violation: + + parser.compile(expression_string, expression) + . + . + try + { + expression.value(); + } + catch (std::runtime_error& rte) + { + printf("Exception: %s\n", rte.what()); + } + + +(3) Loop Iteration Checks +Expressions that contain loop structures (eg: for/while/repeat et al) +can be problematic from a usage point of view due to the difficulty in +determining the following: + + 1. Will the loop ever complete (aka is this an infinite loop?) + 2. Maximum loop execution time + + +ExprTk provides the ability to inject a runtime check within loop +conditionals, and to have the result of the check either signal the +loop to continue or for the check to raise a loop violation error. + +The process involves instantiating a user defined loop_runtime_check +(LRTC), registering the instance with a exprtk::parser instance and +specifying which loop types the check is to performed upon. The +following code demonstrates a how custom LRTC can be instantiated and +registered with the associated parser: + + typedef exprtk::parser parser_t; + typedef exprtk::loop_runtime_check loop_runtime_check_t; + + my_loop_rtc loop_rtc; + loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops; + loop_runtime_check.max_loop_iterations = 100000; + + parser_t parser; + + parser.register_loop_runtime_check(loop_rtc); + + +The following is an example of how one could derive from and implement +a custom loop_runtime_check: + + struct my_loop_rtc final : exprtk::loop_runtime_check + { + + bool check() override + { + // + return ... + } + + void handle_runtime_violation + (const exprtk::violation_context&) override + { + throw std::runtime_error("Loop runtime violation."); + } + }; + + +In the above code, if either the check method returns false or the +loop iteration count exceeds the max_loop_iterations value, the +handle_runtime_violation method will be invoked, coupled with it a +violation_context shall be provided that will contain the following +members: + + 1. loop: Of type loop_types. This value denotes the type of + loop that triggered the violation (e_for_loop, e_while_loop, + e_repeat_until_loop). + + 2. violation: Of type type. This value denotes the type of + violation (e_iteration_count, e_timeout) + + 3. iteration_count: Of type uint64_t. The number of iterations + that the triggering loop has executed since the start of the + expression. + + +Note39: The lifetime of any parser or expression instance must not +exceed that of any LRTC instance that has been registered with it. + +The following is an example implementation of an LRTC that +supports loop timeout violations: + + struct timeout_loop_rtc final : exprtk::loop_runtime_check + { + using time_point_t = + std::chrono::time_point; -[SECTION 24 - BENCHMARKING] + std::size_t iterations_ = 0; + time_point_t timeout_tp_; + + bool check() override + { + if (std::chrono::steady_clock::now() >= timeout_tp_) + { + // handle_runtime_violation shall be invoked + return false; + } + + return true; + } + + void handle_runtime_violation + (const exprtk::violation_context&) override + { + throw std::runtime_error("Loop timed out"); + } + + void set_timeout_time(const time_point_t& timeout_tp) + { + timeout_tp_ = timeout_tp; + } + }; + + +In the above code, the check method shall be invoked on each iteration +of the associated loop. Within the method the current time is compared +to the setup timeout time-point, in the event the current time exceeds +the timeout, the method returns false, triggering the violation, which +in turn will result in the handle_runtime_violation being invoked. + +The following code demonstrates how the above defined LRTC can be used +to ensure that at the very least the loop portion(s) of an expression +will never exceed a given amount of execution time. + + typedef exprtk::parser parser_t; + typedef exprtk::loop_runtime_check loop_runtime_check_t; + + my_loop_rtc loop_rtc; + loop_rtc.loop_set = loop_runtime_check_t::e_all_loops; + loop_rtc.max_loop_iterations = 100000; + + parser_t parser; + + parser.register_loop_runtime_check(loop_rtc); + . + . + . + . + using std::chrono; + const auto max_duration = seconds(25); + + try + { + loop_rtc.set_timeout_time(steady_clock::now() + max_duration); + expression.value(); + + loop_rtc.set_timeout_time(steady_clock::now() + max_duration); + expression.value(); + + loop_rtc.set_timeout_time(steady_clock::now() + max_duration); + expression.value(); + + } + catch(std::runtime_error& exception) + { + printf("Exception: %s\n",exception.what()); + } + + +(4) Compilation Process Checkpointing +When compiling an expression, one may require the compilation process +to periodically checkpoint its internal state, subsequently at the +checkpoint one can then make the decision to continue the compilation +process or to immediately terminate and return. + +The following are reasons one may want to checkpoint the compilation +process: + + 1. Determine if the compilation process has run for far too long + 2. Determine if the current stack frame size exceeds a limit + 3. Enforce an external termination request + + +ExprTk provides the ability to inject a checkpoint into the +compilation process that will be evaluated periodically. This +capability is achieved by registering a user-implemented compilation +check (CCK) to the parser before expression compilation. Initially a +CCK can be defined as follows: + + struct compilation_timeout_check final : + public exprtk::compilation_check + { + bool continue_compilation(compilation_context& context) + override + { + // Determine if compilation should continue + return ...; + } + }; + + +An example checkpoint use-case could be that we do not want the +compilation process to take longer than a maximum defined period, eg: +five seconds. The associated compilation check implementation could be +as follows: + + struct my_compilation_timeout_check final : + public exprtk::compilation_check + { + + bool continue_compilation(compilation_context& context) + override + { + static constexpr std::size_t max_iters_per_check = 1000; + + if (++iterations_ >= max_iters_per_check) + { + if (std::chrono::steady_clock::now() >= timeout_tp_) + { + context.error_message = "Compilation has timed-out"; + return false; + } + + iterations_ = 0; + } + + return true; + } + + using time_point_t = std::chrono::time_point; + + void set_timeout_time(const time_point_t& timeout_tp) + { + timeout_tp_ = timeout_tp; + } + + std::size_t iterations_ = 0; + time_point_t timeout_tp_; + }; + + +Usage of the above defined compilation check will require registering +the check with the parser, setting up the expiry time and then +proceeding to compile the expression. The following is a general +outline of what will be needed: + + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + expression_t expression; + + my_compilation_timeout_check compilation_timeout_check; + + parser_t parser; + parser. + register_compilation_timeout_check(compilation_timeout_check); + + const auto max_duration = std::chrono::seconds(5); + const auto timeout_tp = + std::chrono::steady_clock::now() + max_duration; + + compilation_timeout_check.set_timeout_time(timeout_tp); + + if (!parser.compile(large_expression_string, expression)) + { + printf("Error: %s\t\n", parser.error().c_str()); + return; + } + + +(5) Assert statements +ExprTk supports the use of assert statements to verify pre and post +conditions during the evaluation of expressions. The assert statements +are only active when a user defined assert handler is registered with +the parser before expression compilation, otherwise they are compiled +out, this is similar to how asserts are included/excluded in C++ +coupled with the definition of NDEBUG. The assert syntax has three +variations as described below: + + assert(x + y > i); + assert(x + y > i, 'assert statement 1'); + assert(x + y > i, 'assert statement 1', 'ASSERT01'); + + +The three assert statement input parameters are as follows: + + 1. assert condition (mandatory) + 2. assert message (optional) + 3. assert id (optional) + + +The assert condition is essentially a boolean statement that is +expected to be true during evaluation. The other two parameters of +assert message and ID are string values that are intended to provide +feedback to the handler and to ensure the uniqueness of assert +statement respectively. The three parameters denoted above and the +offset of the assert statement from the beginning of the expression +are placed inside assert_context that is provided as part of the +assert_check handler. A user defined assert_check handler can be +defined as follows: + + struct my_assert_handler final : public exprtk::assert_check + { + void handle_assert(const assert_context& ctxt) override + { + printf("condition: [%s] \n", ctxt.condition.c_str()); + printf("message: [%s] \n", ctxt.message .c_str()); + printf("id: [%s] \n", ctxt.id .c_str()); + printf("offset: [%lu]\n", ctxt.offet ); + // throw std::runtime_error(.....); + } + }; + + +Once the assert_check handler has been registered with the parser, +expressions that contain assert statements will have their asserts +compiled in as part final evaluable expression instance: + + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + const std::string program = + " var x := 4; " + " " + " for (var i := 0; i < 10; i += 1) " + " { " + " assert(i < x, 'assert statement 1'); " + " } "; + + my_assert_handler handler; + + expression_t expression; + parser_t parser; + + parser.register_assert_check(handler); + parser.compile(program, expression); + + +(6) Runtime Check Overheads +All of the above mentioned runtime checks will incur an execution time +overhead during the evaluation of expressions. This is an unfortunate +but necessary side-effect of the process when runtime safety is of +concern. + +A recommendation to consider, that is not demonstrated above, is that +in the check method of the LRTC, one should not evaluate the timeout +condition on every call to check (aka on every loop iteration). +Instead a counter should be maintained and incremented on each call +and when the counter exceeds some predefined amount (eg: 10000 +iterations), then the timeout based check can be preformed. The +reasoning here is that incrementing an integer should be far less +expensive than computing the current "now" time-point. + + +(7) Runtime Check Limitations +The available RTC mechanisms in ExprTk are limited to implementing +said checks only within ExprTk based syntax sections of an expression. +The RTCs will not be active within user defined functions, or +composited functions that have been compiled with parser instances +that don't have the same set of RTC configurations enabled. + + +(8) Runtime Handlers +When implementing stateful run-time check handlers one must be careful +to ensure the handler is setup correctly or reset between calls to the +expression::value or parser::compile methods. + +The following example code utilises the compilation timeout RTC and +expression loop duration RTC examples from above to demonstrate the +need to reset the internal state of the various handlers before +compilation and valuation processes are invoked, as not doing so will +affect the ability for the next expression in the list to either be +correctly compiled or evaluated due to the potential of erroneous +timeouts occurring. + + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + my_compilation_timeout_check compilation_timeout_check; + + my_loop_rtc loop_rtc; + loop_rtc.loop_set = loop_runtime_check_t::e_all_loops; + loop_rtc.max_loop_iterations = 100000; + + parser_t parser; + parser.register_loop_runtime_check(loop_rtc); + parser. + register_compilation_timeout_check(compilation_timeout_check); + + const auto compile_timeout_tp = []() + { + const auto max_duration = std::chrono::seconds(5); + return std::chrono::steady_clock::now() + max_duration; + }; + + const auto loop_timeout_tp = []() + { + const auto max_duration = std::chrono::seconds(10); + return std::chrono::steady_clock::now() + max_duration; + }; + + const std::vector expressions = + { + "x + y / 2", + "sin(x) / cos(y) + 1", + "clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1)" + }; + + for (const auto& expr_str : expressions) + { + // Reset the timeout for the compilation RTC + compilation_timeout_check + .set_timeout_time(compile_timeout_tp()); + + expression_t expression; + + if (!parser.compile(large_expression_string, expression)) + { + printf("Error: %s\t\n", parser.error().c_str()); + continue; + } + + try + { + // Reset the timeout for the loop duration RTC + loop_rtc.set_timeout_time(loop_timeout_tp()); + + expression.value(); + } + catch(std::runtime_error& exception) + { + printf("Exception: %s\n Expression: %s\n", + exception.what(), + expr_str.c_str()); + } + } + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[SECTION 25 - BENCHMARKING] As part of the ExprTk package there is an expression benchmark utility named 'exprtk_benchmark'. The utility attempts to determine expression evaluation speed (or rate of evaluations - evals per second), by @@ -4364,9 +5462,9 @@ mentioned modification to the expression. As can be seen the new form of the expression using the 'exp' function reduces the evaluation time by over 50%, in other words increases the evaluation rate by two fold. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -[SECTION 25 - EXPRTK NOTES] +[SECTION 26 - EXPRTK NOTES] The following is a list of facts and suggestions one may want to take into account when using ExprTk: @@ -4378,13 +5476,25 @@ into account when using ExprTk: ExprTk is an LL(2) type grammar and is processed using a recursive descent parsing algorithm. - (02) Supported types are float, double, long double and MPFR/GMP. + (02) Supported types are float, double, long double and MPFR/GMP. + Generally any user defined numerical type that supports all the + basic floating point arithmetic operations: -,+,*,/,^,% etc; + unary and binary operations: sin,cos,min,max,equal etc and any + other ExprTk dependent operations can be used to specialise the + various components: expression, parser and symbol_table. - (03) Standard mathematical operator precedence is applied (BEDMAS). + (03) Standard arithmetic operator precedence is applied (BEDMAS). In + general C, Pascal or Rust equivalent unary, binary, logical and + equality/inequality operator precedence rules apply. + eg: a == b and c > d + 1 ---> (a == b) and (c > (d + 1)) + x - y <= z / 2 ---> (x - y) <= (z / 2) + a - b / c * d^2^3 ---> a - ((b / c) * d^(2^3)) (04) Results of expressions that are deemed as being 'valid' are to exist within the set of Real numbers. All other results will be - of the value: Not-A-Number (NaN). + of the value: Not-A-Number (NaN). However this may not + necessarily be a requirement for user defined numerical types, + eg: complex number type. (05) Supported user defined types are numeric and string variables, numeric vectors and functions. @@ -4397,18 +5507,19 @@ into account when using ExprTk: 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_]) + 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. (09) The life-time of objects registered with or created from a - specific symbol-table must span at least the life-time of the - compiled expressions which utilise objects, such as variables, - of that symbol-table, otherwise the result will be undefined - behavior. + specific symbol-table must span at least the lifetime of the + symbol table instance and all compiled expressions which + utilise objects, such as variables, strings, vectors, function + compositor functions and functions of that symbol-table, + otherwise the result will be undefined behaviour. - (10) Equal and not_equal are normalised-epsilon equality routines, + (10) Equal and not_equal are normalised-epsilon equality routines, which use epsilons of 0.0000000001 and 0.000001 for double and float types respectively. @@ -4419,7 +5530,7 @@ into account when using ExprTk: tabs, new-lines, control-feed et al. ('\n', '\r', '\t', '\b', '\v', '\f') - (13) Strings may be comprised of any combination of letters, digits + (13) Strings may be comprised of any combination of letters, digits special characters including (~!@#$%^&*()[]|=+ ,./?<>;:"`~_) or hexadecimal escaped sequences (eg: \0x30) and must be enclosed with single-quotes. @@ -4434,8 +5545,8 @@ into account when using ExprTk: (16) Where appropriate constant folding optimisations may be applied. (eg: The expression '2 + (3 - (x / y))' becomes '5 - (x / y)') - (17) If the strength reduction compilation option has been enabled, - then where applicable strength reduction optimisations may be + (17) If the strength reduction compilation option has been enabled, + then where applicable strength reduction optimisations may be applied. (18) String processing capabilities are available by default. To @@ -4451,7 +5562,7 @@ into account when using ExprTk: (21) User defined functions by default are assumed to have side effects. As such an "all constant parameter" invocation of such functions wont result in constant folding. If the function has - no side effects then that can be noted during the constructor + no side-effects then that can be noted during the constructor of the ifunction allowing it to be constant folded where appropriate. @@ -4478,10 +5589,11 @@ into account when using ExprTk: (25) The following are examples of compliant floating point value representations: - (1) 12345 (5) -123.456 - (2) +123.456e+12 (6) 123.456E-12 - (3) +012.045e+07 (7) .1234 - (4) 123.456f (8) -321.654E+3L + (01) 12345 (06) -123.456 + (02) +123.456e+12 (07) 123.456E-12 + (03) +012.045e+07 (08) .1234 + (04) 1234. (09) -56789. + (05) 123.456f (10) -321.654E+3L (26) Expressions may contain any of the following comment styles: @@ -4509,16 +5621,16 @@ into account when using ExprTk: symbol table using any of the reserved words will result in a failure. - abs, acos, acosh, and, asin, asinh, atan, atan2, atanh, avg, - break, case, ceil, clamp, continue, cosh, cos, cot, csc, - default, deg2grad, deg2rad, else, equal, erfc, erf, exp, - expm1, false, floor, for, frac, grad2deg, hypot, iclamp, if, - ilike, in, inrange, in, like, log, log10, log1p, log2, logn, - mand, max, min, mod, mor, mul, nand, ncdf, nor, not, - not_equal, not, null, or, pow, rad2deg, repeat, return, + abs, acos, acosh, and, asin, asinh, assert, atan, atan2, + atanh, avg, break, case, ceil, clamp, continue, cosh, cos, + cot, csc, default, deg2grad, deg2rad, else, equal, erfc, + erf, exp, expm1, false, floor, for, frac, grad2deg, hypot, + iclamp, if, ilike, in, inrange, in, like, log, log10, log1p, + log2, logn, mand, max, min, mod, mor, mul, nand, ncdf, nor, + not, not_equal, not, null, or, pow, rad2deg, repeat, return, root, roundn, round, sec, sgn, shl, shr, sinc, sinh, sin, sqrt, sum, swap, switch, tanh, tan, true, trunc, until, var, - while, xnor, xor, xor + while, xnor, xor (29) Every valid ExprTk statement is a "value returning" expression. Unlike some languages that limit the types of expressions that @@ -4542,7 +5654,7 @@ into account when using ExprTk: ) { (x + y) / (x - y); - } + }; (30) It is recommended when prototyping expressions that the ExprTk REPL be utilised, as it supports all the features available in @@ -4550,7 +5662,7 @@ into account when using ExprTk: and dependency dumps etc which allows for rapid coding/prototyping and debug cycles without the hassle of having to recompile test programs with expressions that have - been hard-coded. It's also a good source of truth for how the + been hard-coded. It is also a good source of truth for how the library's various features can be applied. (31) For performance considerations, one should assume the actions @@ -4568,16 +5680,30 @@ into account when using ExprTk: string form of the expression and compile the expression at run-time on the target. - (33) Before jumping in and using ExprTk, do take the time to peruse + (33) The correctness and robustness of the ExprTk library is + maintained by having a comprehensive suite of unit tests and + functional tests all of which are run using sanitizers (ASAN, + UBSAN, LSAN, MSAN, TSAN). Additionally, continuous fuzz-testing + provided by Google OSS Fuzz, and static analysis via Synopsis + Coverity. + + (34) The library name ExprTk is pronounced "Ex-Pee-Ar-Tee-Kay" or + simply "Mathematical Expression Toolkit" + + + (35) For general support, inquires or bug/issue reporting: + https://www.partow.net/programming/exprtk/index.html#support + + (36) Before jumping in and using ExprTk, do take the time to peruse the documentation and all of the examples, both in the main and the extras distributions. Having an informed general view of what can and can't be done, and how something should be done with ExprTk, will likely result in a far more productive and enjoyable programming experience. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -[SECTION 26 - SIMPLE EXPRTK EXAMPLE] +[SECTION 27 - SIMPLE EXPRTK EXAMPLE] The following is a simple yet complete example demonstrating typical usage of the ExprTk Library. The example instantiates a symbol table object, adding to it three variables named x, y and z, and a custom @@ -4602,11 +5728,11 @@ to stdout. #include "exprtk.hpp" template -struct myfunc : public exprtk::ifunction +struct myfunc final : public exprtk::ifunction { myfunc() : exprtk::ifunction(2) {} - T operator()(const T& v1, const T& v2) + T operator()(const T& v1, const T& v2) override { return T(1) + (v1 * v2) / T(3); } @@ -4619,8 +5745,8 @@ int main() typedef exprtk::parser parser_t; typedef exprtk::parser_error::type error_t; - std::string expression_str = - "z := 2 myfunc([4 + sin(x / pi)^3],y ^ 2)"; + const std::string expression_string = + "z := 2 myfunc([4 + sin(x / pi)^3],y ^ 2)"; double x = 1.1; double y = 2.2; @@ -4640,14 +5766,14 @@ int main() parser_t parser; - if (!parser.compile(expression_str,expression)) + if (!parser.compile(expression_string,expression)) { // A compilation error has occurred. Attempt to // print all errors to stdout. printf("Error: %s\tExpression: %s\n", parser.error().c_str(), - expression_str.c_str()); + expression_string.c_str()); for (std::size_t i = 0; i < parser.error_count(); ++i) { @@ -4664,7 +5790,7 @@ int main() static_cast(error.token.position), exprtk::parser_error::to_str(error.mode).c_str(), error.diagnostic.c_str(), - expression_str.c_str()); + expression_string.c_str()); } return 1; @@ -4680,9 +5806,9 @@ int main() } --- snip --- - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -[SECTION 27 - BUILD OPTIONS] +[SECTION 28 - BUILD OPTIONS] When building ExprTk there are a number of defines that will enable or disable certain features and capabilities. The defines can either be part of a compiler command line switch or scoped around the include to @@ -4774,9 +5900,9 @@ This define will enable run-time checks pertaining to vector indexing operations used in any of the vector-to-vector and vector-to-scalar operations. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -[SECTION 28 - FILES] +[SECTION 29 - FILES] The source distribution of ExprTk is comprised of the following set of files: @@ -4804,10 +5930,89 @@ files: (21) exprtk_simple_example_17.cpp (22) exprtk_simple_example_18.cpp (23) exprtk_simple_example_19.cpp - - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -[SECTION 29 - LANGUAGE STRUCTURE] + (24) exprtk_simple_example_20.cpp + (25) exprtk_simple_example_21.cpp + (26) exprtk_simple_example_22.cpp + (27) exprtk_simple_example_23.cpp + (28) exprtk_simple_example_24.cpp + + +Details for each of the above examples can be found here: + + https://www.partow.net/programming/exprtk/index.html#examples + + +Various extended and advanced examples using ExprTk are available +via the following: + + (00) exprtk_american_option_binomial_model.cpp + (01) exprtk_binomial_coefficient.cpp + (02) exprtk_bsm_benchmark.cpp + (03) exprtk_calc.cpp + (04) exprtk_collatz.cpp + (05) exprtk_compilation_timeout.cpp + (06) exprtk_degree_trigonometry_example.cpp + (07) exprtk_exprgen.cpp + (08) exprtk_extract_dependents.cpp + (09) exprtk_e_10kdigits.cpp + (10) exprtk_factorize_fermat.cpp + (11) exprtk_factorize_pollard.cpp + (12) exprtk_fizzbuzz.cpp + (13) exprtk_funcall_benchmark.cpp + (14) exprtk_game_of_life.cpp + (15) exprtk_gcd.cpp + (16) exprtk_gnuplot.cpp + (17) exprtk_gnuplot_multi.cpp + (18) exprtk_groups_examples.cpp + (19) exprtk_immutable_symbol_table_example.cpp + (20) exprtk_import_packages.cpp + (21) exprtk_instruction_primer.cpp + (22) exprtk_jump_diffusion_process.cpp + (23) exprtk_loop_timeout_rtc.cpp + (24) exprtk_magic_square.cpp + (25) exprtk_mandelbrot.cpp + (26) exprtk_max_subarray_sum.cpp + (27) exprtk_maze_generator.cpp + (28) exprtk_miller_rabin_primality_test.cpp + (29) exprtk_montecarlo_e.cpp + (30) exprtk_montecarlo_option_pricing_model.cpp + (31) exprtk_montecarlo_pi.cpp + (32) exprtk_naive_primes.cpp + (33) exprtk_normal_random_marsaglia_method.cpp + (34) exprtk_nqueens_problem.cpp + (35) exprtk_nthroot_bisection.cpp + (36) exprtk_ornstein_uhlenbeck_process.cpp + (37) exprtk_pascals_triangle.cpp + (38) exprtk_pi_10kdigits.cpp + (39) exprtk_prime_sieve.cpp + (40) exprtk_prime_sieve_vectorized.cpp + (41) exprtk_pythagorean_triples.cpp + (42) exprtk_recursive_fibonacci.cpp + (43) exprtk_repl.cpp + (44) exprtk_riddle.cpp + (45) exprtk_rtc_overhead.cpp + (46) exprtk_sudoku_solver.cpp + (47) exprtk_sumofprimes.cpp + (48) exprtk_symtab_functions.cpp + (49) exprtk_testgen.cpp + (50) exprtk_tower_of_hanoi.cpp + (51) exprtk_truthtable_gen.cpp + (52) exprtk_vectorized_binomial_model.cpp + (53) exprtk_vectornorm.cpp + (54) exprtk_vector_benchmark.cpp + (55) exprtk_vector_benchmark_multithreaded.cpp + (56) exprtk_vector_resize_example.cpp + (57) exprtk_vector_resize_inline_example.cpp + (58) exprtk_wiener_process_pi.cpp + + +Details for each of the above examples can be found here: + + https://partow.net/programming/exprtk/index.html#variousexamples + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[SECTION 30 - LANGUAGE STRUCTURE] The following are the various language structures available within ExprTk and their structural representations.