From ca4933f9c94dec69799e1be61cc576fd043735bc Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Fri, 24 Apr 2015 17:06:08 +1000 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 5 deletions(-) diff --git a/exprtk.hpp b/exprtk.hpp index 98e8eac..9f81820 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -5834,12 +5834,31 @@ namespace exprtk return expression_node::e_switch; } - private: + protected: std::vector arg_list_; std::vector delete_branch_; }; + template + class switch_n_node : public switch_node + { + public: + + typedef expression_node* expression_ptr; + + template class Sequence> + switch_n_node(const Sequence& arg_list) + : switch_node(arg_list) + {} + + inline T value() const + { + return Switch_N::process(switch_node::arg_list_); + } + }; + template class multi_switch_node : public expression_node { @@ -23192,20 +23211,125 @@ namespace exprtk return result; } + struct switch_nodes + { + typedef std::vector arg_list_t; + + #define case_stmt(N) \ + if (is_true(arg[(2 * N)])) return arg[(2 * N) + 1]->value(); + + struct switch_1 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) + return arg.back()->value(); + } + }; + + struct switch_2 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + return arg.back()->value(); + } + }; + + struct switch_3 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) + return arg.back()->value(); + } + }; + + struct switch_4 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) case_stmt(3) + return arg.back()->value(); + } + }; + + struct switch_5 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) case_stmt(3) + case_stmt(4) + return arg.back()->value(); + } + }; + + struct switch_6 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) case_stmt(3) + case_stmt(4) case_stmt(5) + return arg.back()->value(); + } + }; + + struct switch_7 + { + static inline T process(const arg_list_t& arg) + { + case_stmt(0) case_stmt(1) + case_stmt(2) case_stmt(3) + case_stmt(4) case_stmt(5) + case_stmt(6) + return arg.back()->value(); + } + }; + + #undef case_stmt + }; + template class Sequence> inline expression_node_ptr switch_statement(Sequence& arg_list) { - if (!all_nodes_valid(arg_list)) + if (arg_list.empty()) + return error_node(); + else if ( + !all_nodes_valid(arg_list) || + (arg_list.size() < 3) || + ((arg_list.size() % 2) != 1) + ) { details::free_all_nodes(*node_allocator_,arg_list); - return error_node(); } else if (is_constant_foldable(arg_list)) return const_optimize_switch(arg_list); - else - return node_allocator_->allocate >(arg_list); + + switch ((arg_list.size() - 1) / 2) + { + #define case_stmt(N) \ + case N : \ + return node_allocator_-> \ + allocate >(arg_list); \ + + case_stmt(1) + case_stmt(2) + case_stmt(3) + case_stmt(4) + case_stmt(5) + case_stmt(6) + case_stmt(7) + #undef case_stmt + + default : return node_allocator_->allocate >(arg_list); + } } template