From 1e90af47f90ff2cf9b131f6558a0d31bd31e8d60 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Sat, 5 Jul 2014 11:05:02 +1000 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 436 ++++++++++++++++++++++++++++++++++-------------- exprtk_test.cpp | 141 +++++++++++++--- 2 files changed, 426 insertions(+), 151 deletions(-) diff --git a/exprtk.hpp b/exprtk.hpp index 371e260..022d536 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -11358,7 +11358,7 @@ namespace exprtk return true; } - inline type_ptr get(const std::string& symbol_name) + inline type_ptr get(const std::string& symbol_name) const { tm_const_itr_t itr = map.find(symbol_name); if (map.end() == itr) @@ -11671,7 +11671,7 @@ namespace exprtk return 0; } - inline variable_ptr get_variable(const std::string& variable_name) + inline variable_ptr get_variable(const std::string& variable_name) const { if (!valid()) return reinterpret_cast(0); @@ -11682,7 +11682,7 @@ namespace exprtk } #ifndef exprtk_disable_string_capabilities - inline stringvar_ptr get_stringvar(const std::string& string_name) + inline stringvar_ptr get_stringvar(const std::string& string_name) const { if (!valid()) return reinterpret_cast(0); @@ -11693,7 +11693,7 @@ namespace exprtk } #endif - inline function_ptr get_function(const std::string& function_name) + inline function_ptr get_function(const std::string& function_name) const { if (!valid()) return reinterpret_cast(0); @@ -11703,7 +11703,7 @@ namespace exprtk return local_data().function_store.get(function_name); } - inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) + inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const { if (!valid()) return reinterpret_cast(0); @@ -11715,7 +11715,7 @@ namespace exprtk typedef vector_holder_t* vector_holder_ptr; - inline vector_holder_ptr get_vector(const std::string& vector_name) + inline vector_holder_ptr get_vector(const std::string& vector_name) const { if (!valid()) return reinterpret_cast(0); @@ -12119,6 +12119,43 @@ namespace exprtk return holder_ && holder_->data_; } + inline void load_from(const symbol_table& st) + { + std::vector name_list; + + { + st.local_data().function_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + exprtk::ifunction& ifunc = *st.get_function(name_list[i]); + add_function(name_list[i],ifunc); + } + } + + name_list.clear(); + } + + { + std::vector name_list; + + st.local_data().vararg_function_store.get_list(name_list); + + if (!name_list.empty()) + { + for (std::size_t i = 0; i < name_list.size(); ++i) + { + exprtk::ivararg_function& ivafunc = *st.get_vararg_function(name_list[i]); + add_vararg_function(name_list[i],ivafunc); + } + } + + name_list.clear(); + } + } + private: inline bool valid_symbol(const std::string& symbol) const @@ -12246,6 +12283,8 @@ namespace exprtk std::size_t ref_count; expression_ptr expr; local_data_list_t local_data_list; + + friend class function_compositor; }; public: @@ -12406,7 +12445,7 @@ namespace exprtk } } - inline void register_local_data(void* data, const bool vectype = false) + inline void register_local_data(void* data, const std::size_t& size = 0, const bool vectype = false) { if (data) { @@ -12417,12 +12456,13 @@ namespace exprtk typename expression::expression_holder:: data_pack(reinterpret_cast(data), vectype ? expression_holder::e_vecdata : - expression_holder::e_data)); + expression_holder::e_data, + size)); } } } - inline typename expression_holder::local_data_list_t local_data_list() + inline const typename expression_holder::local_data_list_t& local_data_list() { if (expression_holder_) { @@ -12708,6 +12748,7 @@ namespace exprtk index(std::numeric_limits::max()), depth(std::numeric_limits::max()), ref_count(0), + ip_index(0), type (e_none), active(false), data(0), @@ -12717,7 +12758,11 @@ namespace exprtk bool operator < (const scope_element& se) const { - if (depth < se.depth) + if (ip_index < se.ip_index) + return true; + else if (ip_index > se.ip_index) + return false; + else if (depth < se.depth) return true; else if (depth > se.depth) return false; @@ -12734,6 +12779,7 @@ namespace exprtk std::size_t index; std::size_t depth; std::size_t ref_count; + std::size_t ip_index; element_type type; bool active; void* data; @@ -12842,6 +12888,13 @@ namespace exprtk } element_.clear(); + + input_param_cnt_ = 0; + } + + inline std::size_t next_ip_index() + { + return ++input_param_cnt_; } private: @@ -12851,6 +12904,7 @@ namespace exprtk parser_t& parser_; std::vector element_; scope_element null_element_; + std::size_t input_param_cnt_; }; class scope_handler @@ -13403,7 +13457,7 @@ namespace exprtk scoped_vec_delete sdd(*this,arg_list); - do + for (;;) { expression_node_ptr arg = parse_expression(); @@ -13422,10 +13476,16 @@ namespace exprtk else arg_list.push_back(arg); - if (!token_is(token_t::e_eof)) - continue; + if (lexer_.finished()) + break; + else if (token_is(token_t::e_eof,false)) + { + if (lexer_.finished()) + break; + else + next_token(); + } } - while (!lexer_.finished()); result = simplify(arg_list); @@ -15112,7 +15172,11 @@ namespace exprtk tmp_expression_list.push_back(expression_list.back()); expression_list.swap(tmp_expression_list); - return expression_generator_.vararg_function(details::e_multi,expression_list); + + if (1 == expression_list.size()) + return expression_list[0]; + else + return expression_generator_.vararg_function(details::e_multi,expression_list); } inline expression_node_ptr parse_multi_sequence(const std::string& source = "") @@ -16162,6 +16226,10 @@ namespace exprtk { return parse_define_vector_statement(var_name); } + else if (token_is(token_t::e_lcrlbracket,false)) + { + return parse_uninitialised_var_statement(var_name); + } else if (token_is(token_t::e_assign)) { if (0 == (initialisation_expression = parse_expression())) @@ -16255,6 +16323,85 @@ namespace exprtk return expression_generator_(details::e_assign,branch); } + inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) + { + if ( + !token_is(token_t::e_lcrlbracket) || + !token_is(token_t::e_rcrlbracket) + ) + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR128 - Expected a '<>' for uninitialised var definition.")); + + return error_node(); + } + else if (!token_is(token_t::e_eof,false)) + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR129 - Expected ';' after uninitialised variable definition")); + + return error_node(); + } + + variable_node_t* 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_, + "ERR130 - Illegal redefinition of local variable: '" + var_name + "'")); + + return error_node(); + } + else if (scope_element::e_variable == se.type) + { + var_node = se.var_node; + se.active = true; + 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_variable; + nse.depth = scope_depth_; + nse.ip_index = sem_.next_ip_index(); + nse.data = new T(T(0)); + nse.var_node = new variable_node_t(*(T*)(nse.data)); + + if (!sem_.add_element(nse)) + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR131 - Failed to add new local variable '" + var_name + "' to SEM")); + + return error_node(); + } + + var_node = nse.var_node; + + #ifdef exprtk_enable_debugging + printf("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()); + #endif + } + + return expression_generator_(T(0)); + } + inline expression_node_ptr parse_swap_statement() { if (!details::imatch(current_token_.value,"swap")) @@ -16269,7 +16416,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR128 - Expected '(' at start of swap statement")); + "ERR132 - Expected '(' at start of swap statement")); return error_node(); } @@ -16284,7 +16431,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR129 - Expected a symbol for variable or vector element definition")); + "ERR133 - Expected a symbol for variable or vector element definition")); return error_node(); } @@ -16295,7 +16442,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR130 - First parameter to swap is an invalid vector element: '" + var0_name + "'")); + "ERR134 - First parameter to swap is an invalid vector element: '" + var0_name + "'")); return error_node(); } @@ -16323,7 +16470,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR131 - First parameter to swap is an invalid variable: '" + var0_name + "'")); + "ERR135 - First parameter to swap is an invalid variable: '" + var0_name + "'")); return error_node(); } @@ -16336,7 +16483,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR132 - Expected ',' between parameters to swap")); + "ERR136 - Expected ',' between parameters to swap")); return error_node(); } @@ -16348,7 +16495,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR133 - Expected a symbol for variable or vector element definition")); + "ERR137 - Expected a symbol for variable or vector element definition")); return error_node(); } @@ -16359,7 +16506,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR134 - Second parameter to swap is an invalid vector element: '" + var1_name + "'")); + "ERR138 - Second parameter to swap is an invalid vector element: '" + var1_name + "'")); return error_node(); } @@ -16387,7 +16534,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR135 - Second parameter to swap is an invalid variable: '" + var1_name + "'")); + "ERR139 - Second parameter to swap is an invalid variable: '" + var1_name + "'")); return error_node(); } @@ -16400,7 +16547,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR136 - Expected ')' at end of swap statement")); + "ERR140 - Expected ')' at end of swap statement")); return error_node(); } @@ -16487,7 +16634,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR137 - Failed to generate node for vararg function: '" + symbol + "'")); + "ERR141 - Failed to generate node for vararg function: '" + symbol + "'")); return error_node(); } @@ -16504,7 +16651,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR138 - Invalid use of reserved symbol '" + symbol + "'")); + "ERR142 - Invalid use of reserved symbol '" + symbol + "'")); return error_node(); } @@ -16551,7 +16698,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token_, - "ERR139 - Failed to create variable: '" + symbol + "'")); + "ERR143 - Failed to create variable: '" + symbol + "'")); return error_node(); } @@ -16560,7 +16707,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR140 - Undefined variable or function: '" + symbol + "'")); + "ERR144 - Undefined variable or function: '" + symbol + "'")); return error_node(); } @@ -16641,7 +16788,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token_, - "ERR141 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value)); + "ERR145 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value)); return error_node(); } @@ -16666,7 +16813,7 @@ namespace exprtk set_error( make_error(parser_error::e_numeric, current_token_, - "ERR142 - Failed to convert '" + current_token_.value + "' to a number")); + "ERR146 - Failed to convert '" + current_token_.value + "' to a number")); return error_node(); } @@ -16691,7 +16838,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR143 - Expected ')' instead of: '" + current_token_.value + "'")); + "ERR147 - Expected ')' instead of: '" + current_token_.value + "'")); return error_node(); } @@ -16706,7 +16853,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR144 - Expected ']' instead of: '" + current_token_.value + "'")); + "ERR148 - Expected ']' instead of: '" + current_token_.value + "'")); return error_node(); } @@ -16721,7 +16868,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR145 - Expected '}' instead of: '" + current_token_.value + "'")); + "ERR149 - Expected '}' instead of: '" + current_token_.value + "'")); return error_node(); } @@ -16745,7 +16892,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR146 - Premature end of expression[1]")); + "ERR150 - Premature end of expression[1]")); return error_node(); } @@ -16754,7 +16901,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR147 - Premature end of expression[2]")); + "ERR151 - Premature end of expression[2]")); return error_node(); } @@ -23249,24 +23396,24 @@ namespace exprtk { if (se.var_node) { - e.register_local_var (se.var_node); + e.register_local_var(se.var_node); } if (se.data) { - e.register_local_data(se.data); + e.register_local_data(se.data,1); } } else if (scope_element::e_vector == se.type) { if (se.vec_node) { - e.register_local_var (se.vec_node ); + e.register_local_var (se.vec_node); } if (se.data) { - e.register_local_data(se.data,true); + e.register_local_data(se.data,se.size,true); } } @@ -23729,13 +23876,16 @@ namespace exprtk static const std::string x_var("x"); static const std::string y_var("y"); static const std::string z_var("z"); + symbol_table symbol_table; symbol_table.add_constants(); symbol_table.add_variable(x_var,x); symbol_table.add_variable(y_var,y); symbol_table.add_variable(z_var,z); + expression expression; parser parser; + if (parser.compile(expression_string,expression)) { result = expression.value(); @@ -24021,9 +24171,12 @@ namespace exprtk typedef exprtk::ifunction function_t; typedef std::vector varref_t; typedef std::vector var_t; + typedef std::pair lvarref_t; + typedef std::vector lvr_vec_t; base_func(const std::size_t& param_count = 0) : exprtk::ifunction(param_count), + local_var_stack_size(0), stack_depth(0) { v.resize(param_count); @@ -24068,15 +24221,36 @@ namespace exprtk (*v[4]) = v4; (*v[5]) = v5; } - template class Sequence> - inline function_t& setup(expression_t& expr, Sequence vd) + inline function_t& setup(expression_t& expr) { expression = expr; - for (std::size_t i = 0; i < vd.size(); ++i) + + typedef typename expression_t::expression_holder::local_data_list_t ldl_t; + ldl_t ldl = expr.local_data_list(); + + std::vector index_list; + for (std::size_t i = 0; i < ldl.size(); ++i) { - v[i] = vd[i]; + if (ldl[i].size) + index_list.push_back(i); } + + std::size_t input_param_count = 0; + for (std::size_t i = 0; i < index_list.size(); ++i) + { + const std::size_t index = index_list[i]; + if (i < (index_list.size() - v.size())) + { + lv.push_back( + std::make_pair( + reinterpret_cast(ldl[index].pointer), + ldl[index].size)); + local_var_stack_size += ldl[index].size; + } + else + v[input_param_count++] = reinterpret_cast(ldl[index].pointer); + } + clear_stack(); return (*this); } @@ -24085,9 +24259,19 @@ namespace exprtk { if (stack_depth++) { - var_t var_stack(v.size(),T(0)); - copy(v,var_stack); - stack.push_back(var_stack); + if (!v.empty()) + { + var_t var_stack(v.size(),T(0)); + copy(v,var_stack); + param_stack.push_back(var_stack); + } + + if (!lv.empty()) + { + var_t local_var_stack(local_var_stack_size,T(0)); + copy(lv,local_var_stack); + local_stack.push_back(local_var_stack); + } } } @@ -24095,8 +24279,17 @@ namespace exprtk { if (--stack_depth) { - copy(stack.back(),v); - stack.pop_back(); + if (!v.empty()) + { + copy(param_stack.back(),v); + param_stack.pop_back(); + } + + if (!lv.empty()) + { + copy(local_stack.back(),lv); + local_stack.pop_back(); + } } } @@ -24116,6 +24309,40 @@ namespace exprtk } } + void copy(const lvr_vec_t& src_v, var_t& dest_v) + { + typename var_t::iterator itr = dest_v.begin(); + + for (std::size_t i = 0; i < src_v.size(); ++i) + { + lvarref_t vr = src_v[i]; + if (1 == vr.second) + *itr++ = (*vr.first); + else + { + std::copy(vr.first,vr.first + vr.second,itr); + itr += vr.second; + } + } + } + + void copy(const var_t& src_v, lvr_vec_t& dest_v) + { + typename var_t::const_iterator itr = src_v.begin(); + + for (std::size_t i = 0; i < src_v.size(); ++i) + { + lvarref_t vr = dest_v[i]; + if (1 == vr.second) + (*vr.first) = *itr++; + else + { + std::copy(itr,itr + vr.second,vr.first); + itr += vr.second; + } + } + } + inline void clear_stack() { for (std::size_t i = 0; i < v.size(); ++i) @@ -24126,8 +24353,11 @@ namespace exprtk expression_t expression; varref_t v; + lvr_vec_t lv; + std::size_t local_var_stack_size; std::size_t stack_depth; - std::deque stack; + std::deque param_stack; + std::deque local_stack; }; typedef std::map funcparam_t; @@ -24240,46 +24470,24 @@ namespace exprtk if (expr_map_.end() != expr_map_.find(name)) return false; - else if (!forward(name,n)) - return false; - - std::vector > var_transform_list; - for (std::size_t i = 0; i < var_list.size(); ++i) + else if (compile_expression(name,expression,var_list)) { - if (!add_variable(var_list[i],v[i],sv[i])) - { - remove(name,sv); - return false; - } - else - var_transform_list.push_back(std::make_pair(var_list[i],sv[i])); - } - - if (compile_expression(name,expression,var_transform_list)) - { - fp_map_[n][name]->setup(expr_map_[name],v); + fp_map_[n][name]->setup(expr_map_[name]); return true; } else - { - remove(name,sv); return false; - } } public: function_compositor() - : fp_map_(7), - suffix_index_(1), - id_(get_id()) + : fp_map_(7) {} function_compositor(const symbol_table_t& st) : symbol_table_(st), - fp_map_(7), - suffix_index_(1), - id_(get_id()) + fp_map_(7) {} ~function_compositor() @@ -24310,8 +24518,6 @@ namespace exprtk fp_map_[i].clear(); } - - suffix_index_ = 1; } inline bool add(const function& f) @@ -24401,64 +24607,40 @@ namespace exprtk template class Sequence> bool compile_expression(const std::string& name, const std::string& expression, - const Sequence,Allocator>& var_transform_list) + const Sequence& input_var_list) { expression_t compiled_expression; - compiled_expression.register_symbol_table(symbol_table_); + symbol_table_t local_symbol_table; - for (std::size_t i = 0; i < var_transform_list.size(); ++i) + local_symbol_table.load_from(symbol_table_); + local_symbol_table.add_constants(); + + if (!forward(name,input_var_list.size(),local_symbol_table)) + return false; + + compiled_expression.register_symbol_table(local_symbol_table); + + std::string mod_expression; + + for (std::size_t i = 0; i < input_var_list.size(); ++i) { - parser_.remove_replace_symbol(var_transform_list[i].first); - if (!parser_.replace_symbol(var_transform_list[i].first,var_transform_list[i].second)) - return false; + mod_expression += " var " + input_var_list[i] + "{};\n"; } - if (!parser_.compile(expression,compiled_expression)) + mod_expression += "~{" + expression + "};"; + + if (!parser_.compile(mod_expression,compiled_expression)) { + #ifdef exprtk_enable_debugging + printf("Error: %s\n",parser_.error().c_str()); + #endif return false; } - for (std::size_t i = 0; i < var_transform_list.size(); ++i) - { - parser_.remove_replace_symbol(var_transform_list[i].first); - } - expr_map_[name] = compiled_expression; - return true; - } - bool add_variable(const std::string& v, T*& t, std::string& new_var) - { - static const unsigned int max_suffix_index = 1000000000; - while (suffix_index_ < max_suffix_index) - { - new_var = generate_name(v); - if (!symbol_used(new_var)) - { - symbol_table_.create_variable(new_var,T(0)); - t = 0; - t = &symbol_table_.get_variable(new_var)->ref(); - return (0 != t); - } - else - ++suffix_index_; - } - - return false; - } - - std::string generate_name(const std::string v) - { - //eg: x --> function_compositor_1__x_123 - return std::string("function_compositor") + exprtk::details::to_str(id_) + "__" + - v + "_" + - exprtk::details::to_str(static_cast(suffix_index_)); - } - - unsigned int get_id() - { - static unsigned int base_id = 1; - return ++base_id; + exprtk::ifunction& ifunc = (*(fp_map_[input_var_list.size()])[name]); + return symbol_table_.add_function(name,ifunc); } inline bool symbol_used(const std::string& symbol) @@ -24472,7 +24654,7 @@ namespace exprtk ); } - inline bool forward(const std::string& name, const std::size_t& arg_count) + inline bool forward(const std::string& name, const std::size_t& arg_count, symbol_table_t& symbol_table) { if (arg_count > 6) return false; @@ -24493,7 +24675,7 @@ namespace exprtk case 6 : (fp_map_[arg_count])[name] = new func_6param(); break; } exprtk::ifunction& ifunc = (*(fp_map_[arg_count])[name]); - return symbol_table_.add_function(name,ifunc); + return symbol_table.add_function(name,ifunc); } } @@ -24535,8 +24717,6 @@ namespace exprtk parser_t parser_; std::map expr_map_; std::vector fp_map_; - unsigned int suffix_index_; - unsigned int id_; }; template diff --git a/exprtk_test.cpp b/exprtk_test.cpp index f1dcd54..4876f79 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -3281,6 +3281,10 @@ inline bool run_test10() { std::string expression_list[] = { + "var x; 1", + "var x := 1; x", + "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", @@ -4520,28 +4524,64 @@ inline bool run_test19() symbol_table.add_variable("u",u); symbol_table.add_variable("v",v); - expression_t expression; - expression.register_symbol_table(symbol_table); - parser_t parser; - std::string expression_str = "f6(x,y,z,w,u,v) + 2"; + 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(expression_str,expression)) + 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) + }; + + for (std::size_t i = 0; i < expr_str_list_size; ++i) { - printf("run_test19() - Error: %s Expression: %s\n", - parser.error().c_str(), - expression_str.c_str()); - return false; - } + expression_t expression; + expression.register_symbol_table(symbol_table); - 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()); + return false; + } - if (T(2122700582) != result) - { - printf("run_test19() - Error in evaluation! (2) Expression: %s\n", - expression_str.c_str()); - return false; + T result = expression.value(); + + 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); + return false; + } } } @@ -4557,6 +4597,13 @@ inline bool run_test19() " is_prime_impl1(x,y - 1)))", "x","y"); + compositor + .add("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("is_prime_impl2", "switch " @@ -4567,13 +4614,6 @@ inline bool run_test19() "} ", "x","y"); - compositor - .add("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("is_prime2", "switch " @@ -5063,6 +5103,60 @@ inline bool run_test19() } } + { + T x = T(0); + + symbol_table_t symbol_table; + + symbol_table.add_variable("x",x); + + compositor_t compositor(symbol_table); + + compositor + .add("fooboo", + " var x := input; " + " if (x > 0) " + " fooboo(x - 1) + x; " + " else " + " 0; ", + "input"); + + std::string expression_str = "fOoBoO(x)"; + + expression_t expression; + + expression.register_symbol_table(symbol_table); + + parser_t parser; + + if (!parser.compile(expression_str,expression)) + { + printf("run_test19() - Error: %s Expression: %s\n", + parser.error().c_str(), + expression_str.c_str()); + return false; + } + + T sum = T(0); + + for (std::size_t i = 0; i < 100; ++i) + { + x = T(i); + sum += x; + T result = expression.value(); + + if (result != sum) + { + printf("run_test19() - FooBoo(%5.2f) Expected: %5.2f\tResult: %5.2f\n", + x, + sum, + result); + return false; + } + } + + } + return true; } @@ -5205,3 +5299,4 @@ int main() return 0; } +