diff --git a/exprtk.hpp b/exprtk.hpp index 9faebf0..20a514c 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -656,6 +657,7 @@ namespace exprtk { struct unknown_type_tag {}; struct real_type_tag {}; + struct complex_type_tag {}; struct int_type_tag {}; template @@ -664,6 +666,10 @@ namespace exprtk #define exprtk_register_real_type_tag(T) \ template<> struct number_type { typedef real_type_tag type; }; \ + #define exprtk_register_complex_type_tag(T) \ + template<> struct number_type > \ + { typedef complex_type_tag type; }; \ + #define exprtk_register_int_type_tag(T) \ template<> struct number_type { typedef int_type_tag type; }; \ @@ -671,6 +677,10 @@ namespace exprtk exprtk_register_real_type_tag(long double) exprtk_register_real_type_tag(float ) + exprtk_register_complex_type_tag(double ) + exprtk_register_complex_type_tag(long double) + exprtk_register_complex_type_tag(float ) + exprtk_register_int_type_tag(short ) exprtk_register_int_type_tag(int ) exprtk_register_int_type_tag(long long int ) @@ -797,14 +807,16 @@ namespace exprtk template inline T nequal_impl(const T v0, const T v1, real_type_tag) { + typedef real_type_tag rtg; const T epsilon = epsilon_type::value(); - return (abs_impl(v0 - v1,real_type_tag()) > (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0); + return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0); } inline float nequal_impl(const float v0, const float v1, real_type_tag) { + typedef real_type_tag rtg; const float epsilon = epsilon_type::value(); - return (abs_impl(v0 - v1,real_type_tag()) > (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f; + return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f; } template @@ -4282,6 +4294,12 @@ namespace exprtk return std::not_equal_to()(0.0f,v); } + template + inline bool is_true(const std::complex& v) + { + return std::not_equal_to >()(std::complex(0),v); + } + template inline bool is_true(const expression_node* node) { @@ -10290,10 +10308,9 @@ namespace exprtk typedef expression_node* expression_ptr; typedef results_context results_context_t; - return_envelope_node(expression_ptr body, - results_context_t& rc, bool& rtrn_invoked) + return_envelope_node(expression_ptr body, results_context_t& rc) : results_context_(&rc), - return_invoked_ (rtrn_invoked), + return_invoked_ (false), body_ (body), body_deletable_ (branch_deletable(body_)) {} @@ -10327,10 +10344,15 @@ namespace exprtk return expression_node::e_retenv; } + inline bool* retinvk_ptr() + { + return &return_invoked_; + } + private: results_context_t* results_context_; - bool& return_invoked_; + mutable bool return_invoked_; expression_ptr body_; bool body_deletable_; }; @@ -13603,13 +13625,6 @@ namespace exprtk return new node_type(t1,t2); } - template - inline expression_node* allocate_crr(const T1& t1, T2& t2, T3& t3) const - { - return new node_type(t1,t2,t3); - } - template inline expression_node* allocate_rc(T1& t1, const T2& t2) const @@ -15425,14 +15440,16 @@ namespace exprtk : ref_count(0), expr (0), results (0), - return_invoked(false) + retinv_null(false), + return_invoked(&retinv_null) {} expression_holder(expression_ptr e) : ref_count(1), expr (e), results (0), - return_invoked(false) + retinv_null(false), + return_invoked(&retinv_null) {} ~expression_holder() @@ -15478,7 +15495,8 @@ namespace exprtk expression_ptr expr; local_data_list_t local_data_list; results_context_t* results; - bool return_invoked; + bool retinv_null; + bool* return_invoked; friend class function_compositor; }; @@ -15609,7 +15627,7 @@ namespace exprtk inline bool return_invoked() const { - return (expression_holder_->return_invoked); + return (*expression_holder_->return_invoked); } private: @@ -15703,15 +15721,18 @@ namespace exprtk inline void register_return_results(results_context_t* rc) { - if (rc) + if (expression_holder_ && rc) { expression_holder_->results = rc; } } - inline bool& rtrn_invk_ref() + inline void set_retinvk(bool* retinvk_ptr) { - return expression_holder_->return_invoked; + if (expression_holder_) + { + expression_holder_->return_invoked = retinvk_ptr; + } } expression_holder* expression_holder_; @@ -16109,12 +16130,14 @@ namespace exprtk inline scope_element& get_element(const std::string& var_name, const std::size_t index = std::numeric_limits::max()) { + const std::size_t current_depth = parser_.state_.scope_depth; + for (std::size_t i = 0; i < element_.size(); ++i) { scope_element& se = element_[i]; - if (se.depth > parser_.state_.scope_depth) - return null_element_; + if (se.depth > current_depth) + continue; else if ( (se.name == var_name) && (se.index == index) @@ -16128,15 +16151,17 @@ namespace exprtk inline scope_element& get_active_element(const std::string& var_name, const std::size_t index = std::numeric_limits::max()) { + const std::size_t current_depth = parser_.state_.scope_depth; + for (std::size_t i = 0; i < element_.size(); ++i) { scope_element& se = element_[i]; - if (se.depth > parser_.state_.scope_depth) - return null_element_; + if (se.depth > current_depth) + continue; else if ( - (se.name == var_name) && - (se.index == index) && + (se.name == var_name) && + (se.index == index) && (se.active) ) return se; @@ -17398,15 +17423,19 @@ namespace exprtk if ((0 != e) && (token_t::e_eof == current_token().type)) { + bool* retinvk_ptr = 0; + if (state_.return_stmt_present) { dec_.return_present_ = true; e = expression_generator_ - .return_envelope(e,results_context_,expr.rtrn_invk_ref()); + .return_envelope(e,results_context_,retinvk_ptr); } expr.set_expression(e); + expr.set_retinvk(retinvk_ptr); + register_local_vars(expr); register_return_results(expr); @@ -24166,11 +24195,16 @@ namespace exprtk inline expression_node_ptr return_envelope(expression_node_ptr body, results_context_t* rc, - bool& return_invoked) + bool*& return_invoked) { typedef details::return_envelope_node alloc_type; - return node_allocator_->allocate_crr(body,(*rc),return_invoked); + expression_node_ptr result = node_allocator_-> + allocate_cr(body,(*rc)); + + return_invoked = static_cast(result)->retinvk_ptr(); + + return result; } inline expression_node_ptr vector_element(const std::string& symbol, @@ -31465,6 +31499,52 @@ namespace exprtk : name_(n) {} + function(const std::string& name, + const std::string& expression) + : name_(name), + expression_(expression) + {} + + function(const std::string& name, + const std::string& expression, + const std::string& v0) + : name_(name), + expression_(expression) + { + v_.push_back(v0); + } + + function(const std::string& name, + const std::string& expression, + const std::string& v0, const std::string& v1) + : name_(name), + expression_(expression) + { + v_.push_back(v0); v_.push_back(v1); + } + + function(const std::string& name, + const std::string& expression, + const std::string& v0, const std::string& v1, + const std::string& v2) + : name_(name), + expression_(expression) + { + v_.push_back(v0); v_.push_back(v1); + v_.push_back(v2); + } + + function(const std::string& name, + const std::string& expression, + const std::string& v0, const std::string& v1, + const std::string& v2, const std::string& v3) + : name_(name), + expression_(expression) + { + v_.push_back(v0); v_.push_back(v1); + v_.push_back(v2); v_.push_back(v3); + } + inline function& name(const std::string& n) { name_ = n; @@ -31685,6 +31765,11 @@ namespace exprtk } } + inline virtual T value(expression_t& e) + { + return e.value(); + } + expression_t expression; varref_t v; lvr_vec_t lv; @@ -31702,7 +31787,7 @@ namespace exprtk inline T operator()() { - return base_func::expression.value(); + return this->value(base_func::expression); } }; @@ -31716,7 +31801,7 @@ namespace exprtk { base_func::pre(); base_func::update(v0); - T result = base_func::expression.value(); + T result = this->value(base_func::expression); base_func::post(); return result; } @@ -31730,7 +31815,7 @@ namespace exprtk { base_func::pre(); base_func::update(v0,v1); - T result = base_func::expression.value(); + T result = this->value(base_func::expression); base_func::post(); return result; } @@ -31744,7 +31829,7 @@ namespace exprtk { base_func::pre(); base_func::update(v0,v1,v2); - T result = base_func::expression.value(); + T result = this->value(base_func::expression); base_func::post(); return result; } @@ -31758,7 +31843,7 @@ namespace exprtk { base_func::pre(); base_func::update(v0,v1,v2,v3); - T result = base_func::expression.value(); + T result = this->value(base_func::expression); base_func::post(); return result; } @@ -31772,7 +31857,7 @@ namespace exprtk { base_func::pre(); base_func::update(v0,v1,v2,v3,v4); - T result = base_func::expression.value(); + T result = this->value(base_func::expression); base_func::post(); return result; } @@ -31786,12 +31871,49 @@ namespace exprtk { base_func::pre(); base_func::update(v0,v1,v2,v3,v4,v5); - T result = base_func::expression.value(); + T result = this->value(base_func::expression); base_func::post(); return result; } }; + static T return_value(expression_t& e) + { + typedef exprtk::results_context results_context_t; + typedef typename results_context_t::type_store_t type_t; + typedef typename type_t::scalar_view scalar_t; + + T result = e.value(); + + if ( + e.return_invoked() && + (e.results().count() >= 1) && + (type_t::e_scalar == e.results()[0].type) + ) + { + result = scalar_t(e.results()[0])(); + } + + 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); \ + } \ + }; \ + + def_fp_retval(0) + def_fp_retval(1) + def_fp_retval(2) + def_fp_retval(3) + def_fp_retval(4) + def_fp_retval(5) + def_fp_retval(6) + template class Sequence> inline bool add(const std::string& name, @@ -31857,89 +31979,14 @@ namespace exprtk return add(f.name_,f.expression_,f.v_); } - inline bool add(const std::string& name, - const std::string& expression) - { - const std::size_t n = 0; - std::vector v(n); - return add(name,expression,v); - } - - inline bool add(const std::string& name, - const std::string& expression, - const std::string& v0) - { - const std::size_t n = 1; - std::vector v(n); - v[0] = v0; - return add(name,expression,v); - } - - inline bool add(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1) - { - const std::size_t n = 2; - std::vector v(n); - v[0] = v0; v[1] = v1; - return add(name,expression,v); - } - - inline bool add(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1, const std::string& v2) - { - const std::size_t n = 3; - std::vector v(n); - v[0] = v0; v[1] = v1; v[2] = v2; - return add(name,expression,v); - } - - inline bool add(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1, const std::string& v2, - const std::string& v3) - { - const std::size_t n = 4; - std::vector v(n); - v[0] = v0; v[1] = v1; - v[2] = v2; v[3] = v3; - return add(name,expression,v); - } - - inline bool add(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1, const std::string& v2, - const std::string& v3, const std::string& v4) - { - const std::size_t n = 5; - std::vector v(n); - v[0] = v0; v[1] = v1; - v[2] = v2; v[3] = v3; - v[4] = v4; - return add(name,expression,v); - } - - inline bool add(const std::string& name, - const std::string& expression, - const std::string& v0, const std::string& v1, const std::string& v2, - const std::string& v3, const std::string& v4, const std::string& v5) - { - const std::size_t n = 5; - std::vector v(n); - v[0] = v0; v[1] = v1; - v[2] = v2; v[3] = v3; - v[4] = v4; v[5] = v5; - return add(name,expression,v); - } - private: template class Sequence> bool compile_expression(const std::string& name, const std::string& expression, - const Sequence& input_var_list) + const Sequence& input_var_list, + bool return_present = false) { expression_t compiled_expression; symbol_table_t local_symbol_table; @@ -31947,7 +31994,13 @@ namespace exprtk local_symbol_table.load_from(symbol_table_); local_symbol_table.add_constants(); - if (!forward(name,input_var_list.size(),local_symbol_table)) + if (!valid(name,input_var_list.size())) + return false; + + if (!forward(name, + input_var_list.size(), + local_symbol_table, + return_present)) return false; compiled_expression.register_symbol_table(local_symbol_table); @@ -31974,6 +32027,13 @@ namespace exprtk return false; } + if (!return_present && parser_.dec().return_present()) + { + remove(name,input_var_list.size()); + + return compile_expression(name,expression,input_var_list,true); + } + expr_map_[name] = compiled_expression; exprtk::ifunction& ifunc = (*(fp_map_[input_var_list.size()])[name]); @@ -31981,7 +32041,7 @@ namespace exprtk return symbol_table_.add_function(name,ifunc); } - inline bool symbol_used(const std::string& symbol) + inline bool symbol_used(const std::string& symbol) const { return ( symbol_table_.is_variable (symbol) || @@ -31992,46 +32052,42 @@ namespace exprtk ); } - inline bool forward(const std::string& name, const std::size_t& arg_count, symbol_table_t& sym_table) + inline bool valid(const std::string& name, + const std::size_t& arg_count) const { if (arg_count > 6) return false; else if (symbol_used(name)) return false; - else - { - if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) - return false; - - switch (arg_count) - { - case 0 : (fp_map_[arg_count])[name] = new func_0param(); break; - case 1 : (fp_map_[arg_count])[name] = new func_1param(); break; - case 2 : (fp_map_[arg_count])[name] = new func_2param(); break; - case 3 : (fp_map_[arg_count])[name] = new func_3param(); break; - case 4 : (fp_map_[arg_count])[name] = new func_4param(); break; - case 5 : (fp_map_[arg_count])[name] = new func_5param(); break; - case 6 : (fp_map_[arg_count])[name] = new func_6param(); break; - } - - exprtk::ifunction& ifunc = (*(fp_map_[arg_count])[name]); - - return sym_table.add_function(name,ifunc); - } + else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) + return false; + return true; } - template class Sequence> - inline void remove(const std::string& name, const Sequence& v) + inline bool forward(const std::string& name, + const std::size_t& arg_count, + symbol_table_t& sym_table, + const bool ret_present = false) { - symbol_table_.remove_function(name); - - for (std::size_t i = 0; i < v.size(); ++i) + switch (arg_count) { - symbol_table_.remove_variable(v[i]); + #define case_stmt(N) \ + case N : (fp_map_[arg_count])[name] = \ + (!ret_present) ? static_cast \ + (new func_##N##param) : \ + static_cast \ + (new func_##N##param_retval) ; \ + break; \ + + case_stmt(0) case_stmt(1) case_stmt(2) + case_stmt(3) case_stmt(4) case_stmt(5) + case_stmt(6) + #undef case_stmt } - remove(name,v.size()); + exprtk::ifunction& ifunc = (*(fp_map_[arg_count])[name]); + + return sym_table.add_function(name,ifunc); } inline void remove(const std::string& name, const std::size_t& arg_count) @@ -32049,11 +32105,12 @@ namespace exprtk typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); if (fp_map_[arg_count].end() != fp_itr) - return; - else + { delete fp_itr->second; + fp_map_[arg_count].erase(fp_itr); + } - fp_map_[arg_count].erase(fp_itr); + symbol_table_.remove_function(name); } private: diff --git a/exprtk_simple_example_04.cpp b/exprtk_simple_example_04.cpp index 22dfca9..8ff7817 100644 --- a/exprtk_simple_example_04.cpp +++ b/exprtk_simple_example_04.cpp @@ -28,11 +28,14 @@ void fibonacci() typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; typedef exprtk::function_compositor compositor_t; + typedef typename compositor_t::function function_t; compositor_t compositor; compositor - .add("fibonacci", + .add( + function_t( + "fibonacci", " var w := 0; " " var y := 0; " " var z := 1; " @@ -49,7 +52,7 @@ void fibonacci() " z " " }; " " } ", - "x"); + "x")); T x = T(0); diff --git a/exprtk_simple_example_08.cpp b/exprtk_simple_example_08.cpp index 96411bc..b214966 100644 --- a/exprtk_simple_example_08.cpp +++ b/exprtk_simple_example_08.cpp @@ -29,6 +29,7 @@ void composite() typedef exprtk::parser parser_t; typedef exprtk::parser_error::type error_t; typedef exprtk::function_compositor compositor_t; + typedef typename compositor_t::function function_t; compositor_t compositor; @@ -40,8 +41,13 @@ void composite() symbol_table.add_variable("x",x); symbol_table.add_variable("y",y); - compositor.add("f","sin(x / pi)","x"); // f(x) = sin(x / pi) - compositor.add("g","3*[f(x) + f(y)]","x","y"); // g(x,y) = 3[f(x) + f(y)] + compositor + .add( + function_t("f","sin(x / pi)","x")); // f(x) = sin(x / pi) + + compositor + .add( + function_t("g","3*[f(x) + f(y)]","x","y")); // g(x,y) = 3[f(x) + f(y)] std::string expression_string = "g(1 + f(x),f(y) / 2)"; diff --git a/exprtk_simple_example_09.cpp b/exprtk_simple_example_09.cpp index 0544696..e7f9839 100644 --- a/exprtk_simple_example_09.cpp +++ b/exprtk_simple_example_09.cpp @@ -28,6 +28,7 @@ void primes() typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; typedef exprtk::function_compositor compositor_t; + typedef typename compositor_t::function function_t; T x = T(0); @@ -40,43 +41,53 @@ void primes() //Mode 1 - if statement based compositor - .add("is_prime_impl1", + .add( + function_t( + "is_prime_impl1", "if(y == 1,true, " " if(0 == (x % y),false, " " is_prime_impl1(x,y - 1)))", - "x","y"); + "x","y")); compositor - .add("is_prime1", + .add( + function_t( + "is_prime1", "if(frac(x) != 0, false, " " if(x <= 0, false, " " is_prime_impl1(x,min(x - 1,trunc(sqrt(x)) + 1))))", - "x"); + "x")); //Mode 2 - switch statement based compositor - .add("is_prime_impl2", + .add( + function_t( + "is_prime_impl2", "switch " "{ " " case y == 1 : true; " " case (x % y) == 0 : false; " " default : is_prime_impl2(x,y - 1);" "} ", - "x","y"); + "x","y")); compositor - .add("is_prime2", + .add( + function_t( + "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"); + "x")); //Mode 3 - switch statement and while-loop based compositor - .add("is_prime_impl3", + .add( + function_t( + "is_prime_impl3", "while (y > 0) " "{ " " switch " @@ -86,17 +97,19 @@ void primes() " default : y := y - 1; " " } " "} ", - "x","y"); + "x","y")); compositor - .add("is_prime3", + .add( + function_t( + "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"); + "x")); std::string expression_str1 = "is_prime1(x)"; std::string expression_str2 = "is_prime2(x)"; diff --git a/exprtk_simple_example_10.cpp b/exprtk_simple_example_10.cpp index 2272026..76c5150 100644 --- a/exprtk_simple_example_10.cpp +++ b/exprtk_simple_example_10.cpp @@ -29,6 +29,7 @@ void newton_sqrt() typedef exprtk::expression expression_t; typedef exprtk::parser parser_t; typedef exprtk::function_compositor compositor_t; + typedef typename compositor_t::function function_t; T x = T(0); @@ -40,7 +41,9 @@ void newton_sqrt() compositor_t compositor(symbol_table); compositor - .add("newton_sqrt", + .add( + function_t( + "newton_sqrt", " switch " " { " " case x < 0 : -inf; " @@ -57,7 +60,7 @@ void newton_sqrt() " until ((z -= 1) <= 0); " " }; " " } ", - "x"); + "x")); std::string expression_str = "newton_sqrt(x)"; diff --git a/exprtk_test.cpp b/exprtk_test.cpp index 58521f2..2cfeda8 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -5719,28 +5719,28 @@ inline bool run_test19() compositor_t compositor; // f(x) = x + 2 - compositor.add("f","x + 2","x"); + compositor.add(function_t("f","x + 2","x")); // g(x) = x^2-3 - compositor.add("g","x^2 - 3","x"); + compositor.add(function_t("g","x^2 - 3","x")); // fof(x) = f(f(x)) - compositor.add("fof","f(f(x))","x"); + compositor.add(function_t("fof","f(f(x))","x")); // gog(x) = g(g(x)) - compositor.add("gog","g(g(x))","x"); + compositor.add(function_t("gog","g(g(x))","x")); // fog(x) = f(g(x)) - compositor.add("fog","f(g(x))","x"); + compositor.add(function_t("fog","f(g(x))","x")); // gof(x) = g(f(x)) - compositor.add("gof","g(f(x))","x"); + compositor.add(function_t("gof","g(f(x))","x")); // fogof(x) = f(g(f(x))) - compositor.add("fogof","f(g(f(x)))","x"); + compositor.add(function_t("fogof","f(g(f(x)))","x")); // gofog(x) = g(f(g(x))) - compositor.add("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(); @@ -5798,6 +5798,7 @@ inline bool run_test19() } const std::size_t rounds = 100; + for (std::size_t r = 0; r < rounds; ++r) { T x = T(1); @@ -5811,29 +5812,44 @@ inline bool run_test19() // f0() = 6 compositor - .add("f0"," 3 * 2"); + .add( + function_t("f0") + .expression("3 * 2")); // f1(x) = 5 * (f0 + x) compositor - .add("f1","5 * (f0 + x)","x"); + .add( + function_t("f1") + .var("x") + .expression("5 * (f0 + x)")); // f2(x,y) = 7 * (f1(x) + f1(y)) compositor - .add("f2","7 * (f1(x) + f1(y))","x","y"); + .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("f3","9 * (f2(x,y) + f2(y,z) + f2(x,z))","x","y","z"); + .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("f4","11 * (f3(x,y,z) + f3(y,z,w) + f3(z,w,x))","x","y","z","w"); + .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("f5", - "13 * (f4(x,y,z,w) + f4(y,z,w,u) + f4(z,w,u,x) + f4(w,u,x,y))", - "x","y","z","w","u"); + .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 @@ -5887,6 +5903,8 @@ inline bool run_test19() T(2122700580) }; + bool failure = true; + for (std::size_t i = 0; i < expr_str_list_size; ++i) { expression_t expression; @@ -5898,7 +5916,8 @@ inline bool run_test19() parser.error().c_str(), expr_str_list[i].c_str()); - return false; + failure = true; + continue; } T result = expression.value(); @@ -5910,9 +5929,13 @@ inline bool run_test19() result_list[i], result); - return false; + failure = true; + continue; } } + + if (!failure) + return false; } { @@ -5921,41 +5944,51 @@ inline bool run_test19() compositor_t compositor; compositor - .add("is_prime_impl1", + .add( + function_t( + "is_prime_impl1", "if (y == 1,true, " " if (0 == (x % y),false, " " is_prime_impl1(x,y - 1))) ", - "x","y"); + "x","y")); compositor - .add("is_prime1", + .add( + function_t( + "is_prime1", "if (frac(x) != 0, false, " " if (x <= 0, false, " " is_prime_impl1(x,min(x - 1,trunc(sqrt(x)) + 1)))) ", - "x"); + "x")); compositor - .add("is_prime_impl2", + .add( + function_t( + "is_prime_impl2", "switch " "{ " " case y == 1 : true; " " case (x % y) == 0 : false; " " default : is_prime_impl2(x,y - 1);" "} ", - "x","y"); + "x","y")); compositor - .add("is_prime2", + .add( + function_t( + "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"); + "x")); compositor - .add("is_prime_impl3", + .add( + function_t( + "is_prime_impl3", "while (y > 0) " "{ " " switch " @@ -5965,20 +5998,24 @@ inline bool run_test19() " default : y := y - 1; " " } " "} ", - "x","y"); + "x","y")); compositor - .add("is_prime3", + .add( + function_t( + "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"); + "x")); compositor - .add("is_prime_impl4", + .add( + function_t( + "is_prime_impl4", "switch " "{ " " case 1 == x : false; " @@ -5998,17 +6035,19 @@ inline bool run_test19() " } " " }; " "} ", - "x","y"); + "x","y")); compositor - .add("is_prime4", + .add( + function_t( + "is_prime4", "switch " "{ " " case x <= 0 : false; " " case frac(x) != 0 : false; " " default : is_prime_impl4(x,min(x - 1,trunc(sqrt(x)) + 1));" "} ", - "x"); + "x")); symbol_table_t& symbol_table = compositor.symbol_table(); symbol_table.add_constants(); @@ -6126,24 +6165,30 @@ inline bool run_test19() compositor_t compositor; compositor - .add("fibonacci1", + .add( + function_t( + "fibonacci1", "if (x == 0,0, " " if (x == 1,1, " " fibonacci1(x - 1) + fibonacci1(x - 2)))", - "x"); + "x")); compositor - .add("fibonacci2", + .add( + function_t( + "fibonacci2", "switch " "{ " " case x == 0 : 0; " " case x == 1 : 1; " " default : fibonacci2(x - 1) + fibonacci2(x - 2);" "} ", - "x"); + "x")); compositor - .add("fibonacci_impl3", + .add( + function_t( + "fibonacci_impl3", "switch " "{ " " case x == 0 : 0; " @@ -6157,15 +6202,19 @@ inline bool run_test19() " z " " }; " "} ", - "x","y","z","w"); + "x","y","z","w")); compositor - .add("fibonacci3", + .add( + function_t( + "fibonacci3", "fibonacci_impl3(x,0,1,0)", - "x"); + "x")); compositor - .add("fibonacci_impl4", + .add( + function_t( + "fibonacci_impl4", "switch " "{ " " case x == 0 : 0; " @@ -6179,20 +6228,24 @@ inline bool run_test19() " z " " until (x <= 1); " "} ", - "x","y","z","w"); + "x","y","z","w")); compositor - .add("fibonacci4", + .add( + function_t( + "fibonacci4", "fibonacci_impl4(x,0,1,0)", - "x"); + "x")); compositor - .add("fibonacci5", + .add( + function_t( + "fibonacci5", "if ((x == 0) or (x == 1)) " " x; " "else " " fibonacci5(x - 1) + fibonacci5(x - 2); ", - "x"); + "x")); symbol_table_t& symbol_table = compositor.symbol_table(); symbol_table.add_constants(); @@ -6309,7 +6362,9 @@ inline bool run_test19() compositor_t compositor(symbol_table); compositor - .add("newton_sqrt_impl", + .add( + function_t( + "newton_sqrt_impl", "switch " "{ " " case x < 0 : -inf; " @@ -6326,11 +6381,13 @@ inline bool run_test19() " until ((z -= 1) <= 0); " " }; " "} ", - "x","y","z"); + "x","y","z")); compositor - .add("newton_sqrt", - "newton_sqrt_impl(x,0,0)","x"); + .add( + function_t( + "newton_sqrt", + "newton_sqrt_impl(x,0,0)","x")); std::string expression_str = "newton_sqrt(x)"; @@ -6380,7 +6437,9 @@ inline bool run_test19() compositor_t compositor(symbol_table); compositor - .add("mandelbrot", + .add( + function_t( + "mandelbrot", " var width := 118; " " var height := 41; " " var imag_max := +1; " @@ -6412,7 +6471,7 @@ inline bool run_test19() " break; " " }; " " }; " - " } "); + " } ")); std::string expression_str = "mandelbrot()"; @@ -6447,13 +6506,15 @@ inline bool run_test19() compositor_t compositor(symbol_table); compositor - .add("fooboo", + .add( + function_t( + "fooboo", " var x := input; " " if (x > 0) " " fooboo(x - 1) + x; " " else " " 0; ", - "input"); + "input")); std::string expression_str = "fOoBoO(x)";