From 6aa4e5917ed56a3e7d3b48cd289bd936aace1db2 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Sat, 10 Sep 2016 13:15:59 +1000 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) https://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 265 ++++++++++++++++++++++++++++++------------------ exprtk_test.cpp | 66 +++++++++++- readme.txt | 9 +- 3 files changed, 234 insertions(+), 106 deletions(-) diff --git a/exprtk.hpp b/exprtk.hpp index dcec627..dc5e775 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -2996,6 +2996,8 @@ namespace exprtk { public: + using lexer::token_inserter::insert; + commutative_inserter() : lexer::token_inserter(2) {} @@ -3228,6 +3230,8 @@ namespace exprtk { public: + using lexer::token_scanner::operator(); + bracket_checker() : token_scanner(1), state_(true) @@ -3311,6 +3315,8 @@ namespace exprtk { public: + using lexer::token_scanner::operator(); + numeric_checker() : token_scanner (1), current_index_(0) @@ -3444,6 +3450,8 @@ namespace exprtk public: + using lexer::token_scanner::operator(); + sequence_validator() : lexer::token_scanner(2) { @@ -5338,12 +5346,18 @@ namespace exprtk switch (operation_) { case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); + case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); + case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) return arg1; else return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); - default : return std::numeric_limits::quiet_NaN(); + + default : { + exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); + return std::numeric_limits::quiet_NaN(); + } } } @@ -14827,6 +14841,8 @@ namespace exprtk struct freefunc1 : public exprtk::ifunction { + using exprtk::ifunction::operator(); + freefunc1(ff1_functor ff) : exprtk::ifunction(1), f(ff) {} inline T operator()(const T& v0) { return f(v0); } @@ -14835,6 +14851,8 @@ namespace exprtk struct freefunc2 : public exprtk::ifunction { + using exprtk::ifunction::operator(); + freefunc2(ff2_functor ff) : exprtk::ifunction(2), f(ff) {} inline T operator()(const T& v0, const T& v1) { return f(v0,v1); } @@ -14843,6 +14861,8 @@ namespace exprtk struct freefunc3 : public exprtk::ifunction { + using exprtk::ifunction::operator(); + freefunc3(ff3_functor ff) : exprtk::ifunction(3), f(ff) {} inline T operator()(const T& v0, const T& v1, const T& v2) { return f(v0,v1,v2); } @@ -14851,6 +14871,8 @@ namespace exprtk struct freefunc4 : public exprtk::ifunction { + using exprtk::ifunction::operator(); + freefunc4(ff4_functor ff) : exprtk::ifunction(4), f(ff) {} inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3) { return f(v0,v1,v2,v3); } @@ -14859,6 +14881,8 @@ namespace exprtk struct freefunc5 : public exprtk::ifunction { + using exprtk::ifunction::operator(); + freefunc5(ff5_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) { return f(v0,v1,v2,v3,v4); } @@ -14867,6 +14891,8 @@ namespace exprtk struct freefunc6 : public exprtk::ifunction { + using exprtk::ifunction::operator(); + freefunc6(ff6_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) { return f(v0,v1,v2,v3,v4,v5); } @@ -15258,7 +15284,7 @@ namespace exprtk static const std::size_t lut_size = 256; // Symbol Table Holder - struct st_holder + struct control_block { struct st_data { @@ -15304,17 +15330,17 @@ namespace exprtk std::vector*> free_function_list_; }; - st_holder() + control_block() : ref_count(1), data_(new st_data) {} - st_holder(st_data* data) + control_block(st_data* data) : ref_count(1), data_(data) {} - ~st_holder() + ~control_block() { if (data_ && (0 == ref_count)) { @@ -15323,6 +15349,11 @@ namespace exprtk } } + static control_block* create() + { + return new control_block; + } + std::size_t ref_count; st_data* data_; }; @@ -15330,45 +15361,45 @@ namespace exprtk public: symbol_table() - : holder_(new st_holder) + : control_block_(control_block::create()) { clear(); } ~symbol_table() { - if (holder_) + if (control_block_) { - if (0 == --holder_->ref_count) + if (0 == --control_block_->ref_count) { clear(); - delete holder_; + delete control_block_; } } } symbol_table(const symbol_table& st) { - holder_ = st.holder_; - holder_->ref_count++; + control_block_ = st.control_block_; + control_block_->ref_count++; } inline symbol_table& operator=(const symbol_table& st) { if (this != &st) { - if (holder_) + if (control_block_) { - if (0 == --holder_->ref_count) + if (0 == --control_block_->ref_count) { - delete holder_; + delete control_block_; } - holder_ = 0; + control_block_ = 0; } - holder_ = st.holder_; - holder_->ref_count++; + control_block_ = st.control_block_; + control_block_->ref_count++; } return *this; @@ -15376,7 +15407,7 @@ namespace exprtk inline bool operator==(const symbol_table& st) { - return (this == &st) || (holder_ == st.holder_); + return (this == &st) || (control_block_ == st.control_block_); } inline void clear_variables(const bool delete_node = true) @@ -16090,7 +16121,7 @@ namespace exprtk inline bool valid() const { // Symbol table sanity check. - return holder_ && holder_->data_; + return control_block_ && control_block_->data_; } inline void load_from(const symbol_table& st) @@ -16206,19 +16237,19 @@ namespace exprtk return true; } - typedef typename st_holder::st_data local_data_t; + typedef typename control_block::st_data local_data_t; inline local_data_t& local_data() { - return *(holder_->data_); + return *(control_block_->data_); } inline const local_data_t& local_data() const { - return *(holder_->data_); + return *(control_block_->data_); } - st_holder* holder_; + control_block* control_block_; friend class parser; }; @@ -16235,7 +16266,7 @@ namespace exprtk typedef details::vector_holder* vector_holder_ptr; typedef std::vector > symtab_list_t; - struct expression_holder + struct control_block { enum data_type { @@ -16269,7 +16300,7 @@ namespace exprtk typedef std::vector local_data_list_t; typedef results_context results_context_t; - expression_holder() + control_block() : ref_count(0), expr (0), results (0), @@ -16277,7 +16308,7 @@ namespace exprtk return_invoked(&retinv_null) {} - expression_holder(expression_ptr e) + control_block(expression_ptr e) : ref_count(1), expr (e), results (0), @@ -16285,7 +16316,7 @@ namespace exprtk return_invoked(&retinv_null) {} - ~expression_holder() + ~control_block() { if (expr && details::branch_deletable(expr)) { @@ -16324,6 +16355,24 @@ namespace exprtk } } + static inline control_block* create(expression_ptr e) + { + return new control_block(e); + } + + static inline void destroy(control_block*& cntrl_blck) + { + if (cntrl_blck) + { + if (0 == --cntrl_blck->ref_count) + { + delete cntrl_blck; + } + + cntrl_blck = 0; + } + } + std::size_t ref_count; expression_ptr expr; local_data_list_t local_data_list; @@ -16337,34 +16386,34 @@ namespace exprtk public: expression() - : expression_holder_(0) + : control_block_(0) { set_expression(new details::null_node()); } expression(const expression& e) - : expression_holder_(e.expression_holder_), + : control_block_(e.control_block_), symbol_table_list_(e.symbol_table_list_) { - expression_holder_->ref_count++; + control_block_->ref_count++; } inline expression& operator=(const expression& e) { if (this != &e) { - if (expression_holder_) + if (control_block_) { - if (0 == --expression_holder_->ref_count) + if (0 == --control_block_->ref_count) { - delete expression_holder_; + delete control_block_; } - expression_holder_ = 0; + control_block_ = 0; } - expression_holder_ = e.expression_holder_; - expression_holder_->ref_count++; + control_block_ = e.control_block_; + control_block_->ref_count++; symbol_table_list_ = e.symbol_table_list_; } @@ -16379,40 +16428,26 @@ namespace exprtk inline bool operator!() const { return ( - (0 == expression_holder_ ) || - (0 == expression_holder_->expr) + (0 == control_block_ ) || + (0 == control_block_->expr) ); } inline expression& release() { - if (expression_holder_) - { - if (0 == --expression_holder_->ref_count) - { - delete expression_holder_; - } - - expression_holder_ = 0; - } + control_block::destroy(control_block_); return *this; } ~expression() { - if (expression_holder_) - { - if (0 == --expression_holder_->ref_count) - { - delete expression_holder_; - } - } + control_block::destroy(control_block_); } inline T value() const { - return expression_holder_->expr->value(); + return control_block_->expr->value(); } inline T operator()() const @@ -16449,8 +16484,8 @@ namespace exprtk inline const results_context_t& results() const { - if (expression_holder_->results) - return (*expression_holder_->results); + if (control_block_->results) + return (*control_block_->results); else { static const results_context_t null_results; @@ -16460,7 +16495,7 @@ namespace exprtk inline bool return_invoked() const { - return (*expression_holder_->return_invoked); + return (*control_block_->return_invoked); } private: @@ -16474,15 +16509,15 @@ namespace exprtk { if (expr) { - if (expression_holder_) + if (control_block_) { - if (0 == --expression_holder_->ref_count) + if (0 == --control_block_->ref_count) { - delete expression_holder_; + delete control_block_; } } - expression_holder_ = new expression_holder(expr); + control_block_ = control_block::create(expr); } } @@ -16490,13 +16525,13 @@ namespace exprtk { if (expr) { - if (expression_holder_) + if (control_block_) { - expression_holder_-> + control_block_-> local_data_list.push_back( - typename expression::expression_holder:: + typename expression::control_block:: data_pack(reinterpret_cast(expr), - expression_holder::e_expr)); + control_block::e_expr)); } } } @@ -16505,13 +16540,13 @@ namespace exprtk { if (vec_holder) { - if (expression_holder_) + if (control_block_) { - expression_holder_-> + control_block_-> local_data_list.push_back( - typename expression::expression_holder:: + typename expression::control_block:: data_pack(reinterpret_cast(vec_holder), - expression_holder::e_vecholder)); + control_block::e_vecholder)); } } } @@ -16520,55 +16555,55 @@ namespace exprtk { if (data) { - if (expression_holder_) + if (control_block_) { - typename expression_holder::data_type dt = expression_holder::e_data; + typename control_block::data_type dt = control_block::e_data; switch (data_mode) { - case 0 : dt = expression_holder::e_data; break; - case 1 : dt = expression_holder::e_vecdata; break; - case 2 : dt = expression_holder::e_string; break; + case 0 : dt = control_block::e_data; break; + case 1 : dt = control_block::e_vecdata; break; + case 2 : dt = control_block::e_string; break; } - expression_holder_-> + control_block_-> local_data_list.push_back( - typename expression::expression_holder:: + typename expression::control_block:: data_pack(reinterpret_cast(data),dt,size)); } } } - inline const typename expression_holder::local_data_list_t& local_data_list() + inline const typename control_block::local_data_list_t& local_data_list() { - if (expression_holder_) + if (control_block_) { - return expression_holder_->local_data_list; + return control_block_->local_data_list; } else { - static typename expression_holder::local_data_list_t null_local_data_list; + static typename control_block::local_data_list_t null_local_data_list; return null_local_data_list; } } inline void register_return_results(results_context_t* rc) { - if (expression_holder_ && rc) + if (control_block_ && rc) { - expression_holder_->results = rc; + control_block_->results = rc; } } inline void set_retinvk(bool* retinvk_ptr) { - if (expression_holder_) + if (control_block_) { - expression_holder_->return_invoked = retinvk_ptr; + control_block_->return_invoked = retinvk_ptr; } } - expression_holder* expression_holder_; + control_block* control_block_; symtab_list_t symbol_table_list_; friend class parser; @@ -16583,27 +16618,27 @@ namespace exprtk static inline bool is_constant(const expression& expr) { - return details::is_constant_node(expr.expression_holder_->expr); + return details::is_constant_node(expr.control_block_->expr); } static inline bool is_variable(const expression& expr) { - return details::is_variable_node(expr.expression_holder_->expr); + return details::is_variable_node(expr.control_block_->expr); } static inline bool is_unary(const expression& expr) { - return details::is_unary_node(expr.expression_holder_->expr); + return details::is_unary_node(expr.control_block_->expr); } static inline bool is_binary(const expression& expr) { - return details::is_binary_node(expr.expression_holder_->expr); + return details::is_binary_node(expr.control_block_->expr); } static inline bool is_function(const expression& expr) { - return details::is_function(expr.expression_holder_->expr); + return details::is_function(expr.control_block_->expr); } }; @@ -22163,6 +22198,7 @@ namespace exprtk bool single_value_initialiser = false; bool vec_to_vec_initialiser = false; + bool null_initialisation = false; if (!token_is(token_t::e_rsqrbracket)) { @@ -22239,19 +22275,25 @@ namespace exprtk else return error_node(); } + // Are we dealing with a null initialisation vector definition? + else if (token_is(token_t::e_symbol,"null")) + null_initialisation = true; } - if (0 == initialiser) + if (!null_initialisation) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR140 - Expected '{' as part of vector initialiser list")); + if (0 == initialiser) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR140 - Expected '{' as part of vector initialiser list")); - return error_node(); + return error_node(); + } + else + vec_to_vec_initialiser = true; } - else - vec_to_vec_initialiser = true; } else if (!token_is(token_t::e_rcrlbracket)) { @@ -22385,7 +22427,9 @@ namespace exprtk expression_node_ptr result = error_node(); - if (vec_to_vec_initialiser) + if (null_initialisation) + result = expression_generator_(T(0.0)); + else if (vec_to_vec_initialiser) result = expression_generator_( details::e_assign, node_allocator_.allocate(vec_holder), @@ -32912,6 +32956,8 @@ namespace exprtk public: + using ifunction::operator(); + polynomial() : ifunction((N+2 <= 20) ? (N + 2) : std::numeric_limits::max()) { @@ -33114,6 +33160,8 @@ namespace exprtk typedef std::pair lvarref_t; typedef std::vector lvr_vec_t; + using exprtk::ifunction::operator(); + base_func(const std::size_t& pc = 0) : exprtk::ifunction(pc), local_var_stack_size(0), @@ -33165,7 +33213,8 @@ namespace exprtk { expression = expr; - typedef typename expression_t::expression_holder::local_data_list_t ldl_t; + typedef typename expression_t::control_block::local_data_list_t ldl_t; + ldl_t ldl = expr.local_data_list(); std::vector index_list; @@ -33318,6 +33367,8 @@ namespace exprtk struct func_0param : public base_func { + using exprtk::ifunction::operator(); + func_0param() : base_func(0) {} inline T operator()() @@ -33344,6 +33395,8 @@ namespace exprtk struct func_1param : public base_func { + using exprtk::ifunction::operator(); + func_1param() : base_func(1) {} inline T operator()(type v0) @@ -33358,6 +33411,8 @@ namespace exprtk struct func_2param : public base_func { + using exprtk::ifunction::operator(); + func_2param() : base_func(2) {} inline T operator()(type v0, type v1) @@ -33372,6 +33427,8 @@ namespace exprtk struct func_3param : public base_func { + using exprtk::ifunction::operator(); + func_3param() : base_func(3) {} inline T operator()(type v0, type v1, type v2) @@ -33386,6 +33443,8 @@ namespace exprtk struct func_4param : public base_func { + using exprtk::ifunction::operator(); + func_4param() : base_func(4) {} inline T operator()(type v0, type v1, type v2, type v3) @@ -33400,6 +33459,8 @@ namespace exprtk struct func_5param : public base_func { + using exprtk::ifunction::operator(); + func_5param() : base_func(5) {} inline T operator()(type v0, type v1, type v2, type v3, type v4) @@ -33414,6 +33475,8 @@ namespace exprtk struct func_6param : public base_func { + using exprtk::ifunction::operator(); + func_6param() : base_func(6) {} inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5) diff --git a/exprtk_test.cpp b/exprtk_test.cpp index 8878f5a..10dba03 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -3193,6 +3193,8 @@ inline bool run_test08() template struct myfunc : public exprtk::ifunction { + using exprtk::ifunction::operator(); + myfunc() : exprtk::ifunction(2) {} inline T operator()(const T& v1, const T& v2) @@ -4272,7 +4274,9 @@ inline bool run_test10() "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} })" + "1 == (for (var i := 0; i < 10; i += 1) { ~{break[i += 1]; continue; i += i} })", + + "var x[10^6] := null; var y[10^7] := null; 0 * (min(x) + min(y)) + x[] + y[] == 10^7 + 10^6" }; const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); @@ -4286,6 +4290,7 @@ inline bool run_test10() symbol_table.add_variable("zero",zero); symbol_table.add_variable("one" , one); + symbol_table.add_pi(); bool failed = false; @@ -4548,6 +4553,8 @@ inline bool run_test12() template struct sine_deg : public exprtk::ifunction { + using exprtk::ifunction::operator(); + sine_deg() : exprtk::ifunction(1) {} inline T operator()(const T& v) @@ -4559,6 +4566,8 @@ struct sine_deg : public exprtk::ifunction template struct cosine_deg : public exprtk::ifunction { + using exprtk::ifunction::operator(); + cosine_deg() : exprtk::ifunction(1) {} inline T operator()(const T& v) @@ -4945,6 +4954,8 @@ inline bool run_test15() template struct base_func : public exprtk::ifunction { + using exprtk::ifunction::operator(); + 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); } @@ -5251,6 +5262,8 @@ struct gen_func : public exprtk::igeneric_function typedef typename generic_type::vector_view vector_t; typedef typename generic_type::string_view string_t; + using exprtk::igeneric_function::operator(); + gen_func() : scalar_count(0), vector_count(0), @@ -5301,10 +5314,12 @@ struct gen_func2 : public exprtk::igeneric_function { typedef typename exprtk::igeneric_function::parameter_list_t parameter_list_t; + using exprtk::igeneric_function::operator(); + gen_func2() {} - inline T operator()(parameter_list_t&) + inline T operator()(parameter_list_t) { return T(0); } @@ -5325,6 +5340,8 @@ struct inc_func : public exprtk::igeneric_function typedef typename generic_type::vector_view vector_t; typedef typename generic_type::string_view string_t; + using exprtk::igeneric_function::operator(); + inc_func() {} @@ -5383,6 +5400,8 @@ struct rem_space_and_uppercase : public exprtk::igeneric_function typedef typename igenfunc_t::parameter_list_t parameter_list_t; typedef typename generic_type::string_view string_t; + using exprtk::igeneric_function::operator(); + rem_space_and_uppercase() : igenfunc_t("S",igenfunc_t::e_rtrn_string) {} @@ -5426,6 +5445,8 @@ struct vararg_func : public exprtk::igeneric_function typedef typename generic_type::scalar_view scalar_t; typedef typename generic_type::vector_view vector_t; + using exprtk::igeneric_function::operator(); + vararg_func() : exprtk::igeneric_function("Z|T*|V") {} @@ -7022,6 +7043,47 @@ inline bool run_test19() } } + { + symbol_table_t symbol_table; + + 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", + + "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]; + + parser_t parser; + + for (std::size_t i = 0; i < 2; ++i) + { + e[i].register_symbol_table(symbol_table); + + if (!parser.compile(expression_str[i],e[i])) + { + printf("run_test19() - Error: %s Expression: %s\n", + parser.error().c_str(), + expression_str[i].c_str()); + + return false; + } + + if (T(1) != e[i].value()) + { + printf("run_test19() - erf/erfc computation error %d", + static_cast(i)); + + return false; + } + } + } + return true; } diff --git a/readme.txt b/readme.txt index 3a9d955..6d02b8c 100644 --- a/readme.txt +++ b/readme.txt @@ -1174,10 +1174,13 @@ zero. The following are examples of vector definitions: var x[3] := { 1, 2, 3 }; var y[5] := x; // 1, 2, 3, ??, ?? - (h) Error as there are too many initialisers + (h) Non-initialised vector + var x[3] := null; // ?? ?? ?? + + (i) Error as there are too many initialisers var x[3] := { 1, 2, 3, 4 }; - (i) Error as a vector of size zero is not allowed. + (j) Error as a vector of size zero is not allowed. var x[0]; @@ -2496,7 +2499,7 @@ compiled the above denoted post compilation error handling code shall produce the following output: Error: ERR184 - Undefined symbol: 'x' - Err No.:00 Pos:17 Type:[Syntax] Msg: ERR184 - Undefined symbol: 'x' + Error[00] Pos:17 Type:[Syntax] Msg: ERR184 - Undefined symbol: 'x' For expressions comprised of multiple lines, the error position