From 7fdaf28b12836d1f41930d644f8a83f0cf4958d6 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Mon, 1 Apr 2013 10:56:44 +1100 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 1446 +++++++++++++++++++++++++++++--- exprtk_test.cpp | 2104 ++++++++++++++++++++++++++++------------------- readme.txt | 29 +- 3 files changed, 2601 insertions(+), 978 deletions(-) diff --git a/exprtk.hpp b/exprtk.hpp index cdf2d6b..ec82887 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -225,9 +225,8 @@ namespace exprtk static const std::string reserved_words[] = { - "and", "false", "for", "if", "ilike", "in", "like", "nand", "nor", - "not", "null", "or", "shl", "shr", "true", "while", "xnor", "xor", - "&", "|" + "and", "false", "for", "if", "ilike", "in", "like", "nand", "nor", "not", + "null", "or", "shl", "shr", "true", "while", "xnor", "xor", "&", "|" }; static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); @@ -235,13 +234,13 @@ namespace exprtk static const std::string reserved_symbols[] = { "abs", "acos", "and", "asin", "atan", "atan2", "avg", "ceil", "clamp", - "cos", "cosh", "cot", "csc", "deg2grad", "deg2rad", "equal", "erf", - "erfc", "exp", "false", "floor", "for", "frac", "grad2deg", "hypot", - "if", "ilike", "in", "inrange", "like", "log", "log10", "logn", "log1p", - "max", "min", "mod", "mul", "nand", "nor", "not", "not_equal", "null", - "or", "pow", "rad2deg", "root", "round", "roundn", "sec", "sgn", "shl", - "shr", "sin", "sinh", "sqrt", "sum", "tan", "tanh", "true", "trunc", - "while", "xnor", "xor", "&", "|" + "cos", "cosh", "cot", "csc", "deg2grad", "deg2rad", "equal", "erf", "erfc", + "exp", "false", "floor", "for", "frac", "grad2deg", "hypot", "if", "ilike", + "in", "inrange", "like", "log", "log10", "logn", "log1p", "mand", "max", + "min", "mod", "mor", "mul", "nand", "nor", "not", "not_equal", "null", "or", + "pow", "rad2deg", "root", "round", "roundn", "sec", "sgn", "shl", "shr", "sin", + "sinh", "sqrt", "sum", "tan", "tanh", "true", "trunc", "while", "xnor", "xor", + "&", "|" }; static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); @@ -2737,25 +2736,26 @@ namespace exprtk { enum operator_type { - e_default, e_null , e_add , e_sub , - e_mul , e_div , e_mod , e_pow , - e_atan2 , e_min , e_max , e_avg , - e_sum , e_prod , e_lt , e_lte , - e_eq , e_equal , e_ne , e_nequal , - e_gte , e_gt , e_and , e_nand , - e_or , e_nor , e_xor , e_xnor , - e_shr , e_shl , e_abs , e_acos , - e_asin , e_atan , e_ceil , e_cos , - e_cosh , e_exp , e_floor , e_log , - e_log10 , e_log1p , e_logn , e_neg , - e_pos , e_round , e_roundn , e_root , - e_sqrt , e_sin , e_sinh , e_sec , - e_csc , e_tan , e_tanh , e_cot , - e_clamp , e_inrange, e_sgn , e_r2d , - e_d2r , e_d2g , e_g2d , e_hypot , - e_notl , e_erf , e_erfc , e_frac , - e_trunc , e_assign , e_in , e_like , - e_ilike , + e_default , e_null , e_add , e_sub , + e_mul , e_div , e_mod , e_pow , + e_atan2 , e_min , e_max , e_avg , + e_sum , e_prod , e_lt , e_lte , + e_eq , e_equal , e_ne , e_nequal , + e_gte , e_gt , e_and , e_nand , + e_or , e_nor , e_xor , e_xnor , + e_mand , e_mor , e_scand , e_scor , + e_shr , e_shl , e_abs , e_acos , + e_asin , e_atan , e_ceil , e_cos , + e_cosh , e_exp , e_floor , e_log , + e_log10 , e_log1p , e_logn , e_neg , + e_pos , e_round , e_roundn , e_root , + e_sqrt , e_sin , e_sinh , e_sec , + e_csc , e_tan , e_tanh , e_cot , + e_clamp , e_inrange , e_sgn , e_r2d , + e_d2r , e_d2g , e_g2d , e_hypot , + e_notl , e_erf , e_erfc , e_frac , + e_trunc , e_assign , e_in , e_like , + e_ilike , // Do not add new functions/operators after this point. e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, @@ -2905,9 +2905,6 @@ namespace exprtk case e_equal : return equal(arg0,arg1); case e_nequal : return nequal(arg0,arg1); case e_hypot : return hypot(arg0,arg1); - case e_avg : return (arg0 + arg1)/T(2); - case e_sum : return (arg0 + arg1); - case e_prod : return (arg0 * arg1); case e_shr : return shr(arg0,arg1); case e_shl : return shl(arg0,arg1); default : return std::numeric_limits::quiet_NaN(); @@ -2944,9 +2941,6 @@ namespace exprtk case e_equal : return arg0 == arg1; case e_nequal : return arg0 != arg1; case e_hypot : return hypot(arg0,arg1); - case e_avg : return (arg0 + arg1) >> 1; - case e_sum : return (arg0 + arg1); - case e_prod : return (arg0 * arg1); case e_shr : return arg0 >> arg1; case e_shl : return arg0 << arg1; default : return std::numeric_limits::quiet_NaN(); @@ -2978,29 +2972,29 @@ namespace exprtk { e_none , e_null , e_constant , e_unary , e_binary , e_binary_ext , e_trinary , e_quaternary , - e_quinary , e_senary , e_conditional , e_while , - e_variable , e_stringvar , e_stringconst , e_function , - e_add , e_sub , e_mul , e_div , - e_mod , e_pow , e_lt , e_lte , - e_gt , e_gte , e_eq , e_ne , - e_and , e_nand , e_or , e_nor , - e_xor , e_xnor , e_in , e_like , - e_ilike , e_inranges , e_ipow , e_ipowinv , - e_abs , e_acos , e_asin , e_atan , - e_ceil , e_cos , e_cosh , e_exp , - e_floor , e_log , e_log10 , e_log1p , - e_neg , e_pos , e_round , e_sin , - e_sinh , e_sqrt , e_tan , e_tanh , - e_cot , e_sec , e_csc , e_r2d , - e_d2r , e_d2g , e_g2d , e_notl , - e_sgn , e_erf , e_erfc , e_frac , - e_trunc , e_uvouv , e_vov , e_cov , - e_voc , e_vob , e_bov , e_cob , - e_boc , e_vovov , e_vovoc , e_vocov , - e_covov , e_covoc , e_vovovov , e_vovovoc , - e_vovocov , e_vocovov , e_covovov , e_covocov , - e_vocovoc , e_covovoc , e_vococov , e_sf3ext , - e_sf4ext + e_quinary , e_senary , e_vararg , e_conditional , + e_while , e_variable , e_stringvar , e_stringconst , + e_function , e_vafunction , e_add , e_sub , + e_mul , e_div , e_mod , e_pow , + e_lt , e_lte , e_gt , e_gte , + e_eq , e_ne , e_and , e_nand , + e_or , e_nor , e_xor , e_xnor , + e_in , e_like , e_ilike , e_inranges , + e_ipow , e_ipowinv , e_abs , e_acos , + e_asin , e_atan , e_ceil , e_cos , + e_cosh , e_exp , e_floor , e_log , + e_log10 , e_log1p , e_neg , e_pos , + e_round , e_sin , e_sinh , e_sqrt , + e_tan , e_tanh , e_cot , e_sec , + e_csc , e_r2d , e_d2r , e_d2g , + e_g2d , e_notl , e_sgn , e_erf , + e_erfc , e_frac , e_trunc , e_uvouv , + e_vov , e_cov , e_voc , e_vob , + e_bov , e_cob , e_boc , e_vovov , + e_vovoc , e_vocov , e_covov , e_covoc , + e_vovovov , e_vovovoc , e_vovocov , e_vocovov , + e_covovov , e_covocov , e_vocovoc , e_covovoc , + e_vococov , e_sf3ext , e_sf4ext }; typedef T value_type; @@ -3028,7 +3022,6 @@ namespace exprtk { return e_none; } - }; inline bool is_true(const double v) @@ -3105,6 +3098,18 @@ namespace exprtk return true; } + template class Sequence> + inline bool all_nodes_valid(const Sequence*,Allocator>& b) + { + for (std::size_t i = 0; i < b.size(); ++i) + { + if (0 == b[i]) return false; + } + return true; + } + template inline bool all_nodes_variables(expression_node* (&b)[N]) { @@ -3118,22 +3123,43 @@ namespace exprtk return true; } + template class Sequence> + inline bool all_nodes_variables(Sequence*,Allocator>& b) + { + for (std::size_t i = 0; i < b.size(); ++i) + { + if (0 == b[i]) + return false; + else if (!is_variable_node(b[i])) + return false; + } + return true; + } + template inline void free_all_nodes(NodeAllocator& node_allocator, expression_node* (&b)[N]) { for (std::size_t i = 0; i < N; ++i) { - if (0 != b[i]) - { - if (!is_variable_node(b[i])) - { - node_allocator.free(b[i]); - b[i] = 0; - } - } + free_node(node_allocator,b[i]); } } + template class Sequence> + inline void free_all_nodes(NodeAllocator& node_allocator, Sequence*,Allocator>& b) + { + for (std::size_t i = 0; i < b.size(); ++i) + { + free_node(node_allocator,b[i]); + } + b.clear(); + } + template inline void free_node(NodeAllocator& node_allocator, expression_node*& node) { @@ -3484,9 +3510,6 @@ namespace exprtk case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); case e_min : return std::min(std::min(arg0,arg1),arg2); case e_max : return std::max(std::max(arg0,arg1),arg2); - case e_avg : return (arg0 + arg1 + arg2) / T(3.0); - case e_sum : return (arg0 + arg1 + arg2); - case e_prod : return (arg0 * arg1 * arg2); default : return std::numeric_limits::quiet_NaN(); } } @@ -3535,9 +3558,6 @@ namespace exprtk { case e_min : return std::min(std::min(arg0,arg1),std::min(arg2,arg3)); case e_max : return std::max(std::max(arg0,arg1),std::max(arg2,arg3)); - case e_avg : return (arg0 + arg1 + arg2 + arg3) / T(4.0); - case e_sum : return (arg0 + arg1 + arg2 + arg3); - case e_prod : return (arg0 * arg1 * arg2 * arg3); default : return std::numeric_limits::quiet_NaN(); } } @@ -3589,9 +3609,6 @@ namespace exprtk { case e_min : return std::min(std::min(std::min(arg0,arg1),std::min(arg2,arg3)),arg4); case e_max : return std::max(std::max(std::max(arg0,arg1),std::max(arg2,arg3)),arg4); - case e_avg : return (arg0 + arg1 + arg2 + arg3 + arg4) / T(5.0); - case e_sum : return (arg0 + arg1 + arg2 + arg3 + arg4); - case e_prod : return (arg0 * arg1 * arg2 * arg3 * arg4); default : return std::numeric_limits::quiet_NaN(); } } @@ -3644,9 +3661,6 @@ namespace exprtk { case e_min : return std::min(std::min(std::min(arg0,arg1),std::min(arg2,arg3)),std::min(arg4,arg5)); case e_max : return std::max(std::max(std::max(arg0,arg1),std::max(arg2,arg3)),std::max(arg4,arg5)); - case e_avg : return (arg0 + arg1 + arg2 + arg3 + arg4 + arg5) / T(6.0); - case e_sum : return (arg0 + arg1 + arg2 + arg3 + arg4 + arg5); - case e_prod : return (arg0 * arg1 * arg2 * arg3 * arg4 * arg5); case e_default : default : return std::numeric_limits::quiet_NaN(); } @@ -4134,6 +4148,111 @@ namespace exprtk const T& v3_; }; + template + class vararg_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + template class Sequence> + vararg_node(const Sequence& arglist) + { + arg_list_.resize(arglist.size()); + delete_branch_.resize(arglist.size()); + for (std::size_t i = 0; i < arglist.size(); ++i) + { + if (arglist[i]) + { + arg_list_[i] = arglist[i]; + delete_branch_[i] = static_cast(branch_deletable(arg_list_[i]) ? 1 : 0); + } + else + { + arg_list_.clear(); + delete_branch_.clear(); + return; + } + } + } + + ~vararg_node() + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && delete_branch_[i]) + { + delete arg_list_[i]; + arg_list_[i] = 0; + } + } + } + + inline T value() const + { + if (!arg_list_.empty()) + return VarArgFunction::process(arg_list_); + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vararg; + } + + private: + + std::vector arg_list_; + std::vector delete_branch_; + }; + + template + class vararg_varnode : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + template class Sequence> + vararg_varnode(const Sequence& arglist) + { + arg_list_.resize(arglist.size()); + for (std::size_t i = 0; i < arglist.size(); ++i) + { + if (arglist[i] && is_variable_node(arglist[i])) + { + variable_node* var_node_ptr = dynamic_cast*>(arglist[i]); + arg_list_[i] = (&var_node_ptr->ref()); + } + else + { + arg_list_.clear(); + return; + } + } + } + + inline T value() const + { + if (!arg_list_.empty()) + return VarArgFunction::process(arg_list_); + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vararg; + } + + private: + + std::vector arg_list_; + }; + template class assignment_node : public binary_node { @@ -4159,11 +4278,54 @@ namespace exprtk return result; } } - return std::numeric_limits::quiet_NaN(); } }; + template + class scand_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + scand_node(const operator_type& operation, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(operation,branch0,branch1) + {} + + inline T value() const + { + return ( + (T(0) != binary_node::branch_[0].first->value()) && + (T(0) != binary_node::branch_[1].first->value()) + ) ? T(1) : T(0); + } + }; + + template + class scor_node : public binary_node + { + public: + + typedef expression_node* expression_ptr; + + scor_node(const operator_type& operation, + expression_ptr branch0, + expression_ptr branch1) + : binary_node(operation,branch0,branch1) + {} + + inline T value() const + { + return ( + (T(0) != binary_node::branch_[0].first->value()) || + (T(0) != binary_node::branch_[1].first->value()) + ) ? T(1) : T(0); + } + }; + template class function_N_node : public expression_node { @@ -4493,6 +4655,69 @@ namespace exprtk std::size_t parameter_count_; }; + template + class vararg_function_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + + vararg_function_node(VarArgFunction* func, + const std::vector& arg_list) + : function_(func), + arg_list_(arg_list) + { + value_list_.resize(arg_list.size(),std::numeric_limits::quiet_NaN()); + } + + ~vararg_function_node() + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) + { + delete arg_list_[i]; + arg_list_[i] = 0; + } + } + } + + inline bool operator <(const vararg_function_node& fn) const + { + return this < (&fn); + } + + inline T value() const + { + if (function_) + { + populate_value_list(); + return (*function_)(value_list_); + } + else + return std::numeric_limits::quiet_NaN(); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_vafunction; + } + + private: + + inline void populate_value_list() const + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + value_list_[i] = arg_list_[i]->value(); + } + } + + VarArgFunction* function_; + std::vector arg_list_; + mutable std::vector value_list_; + }; + #define exprtk_def_unary_op(OpName) \ template \ struct OpName##_op \ @@ -4764,6 +4989,515 @@ namespace exprtk static inline details::operator_type operation() { return details::e_inrange; } }; + template + inline T value(details::expression_node* n) + { + return n->value(); + } + + template + inline T value(T* t) + { + return (*t); + } + + template + struct vararg_add_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arglist) + { + if (arglist.size() > 5) + { + T result = T(0); + for (std::size_t i = 0; i < arglist.size(); ++i) + { + result += value(arglist[i]); + } + return result; + } + else + { + switch (arglist.size()) + { + case 0 : return T(0); + case 1 : return process_1(arglist); + case 2 : return process_2(arglist); + case 3 : return process_3(arglist); + case 4 : return process_4(arglist); + case 5 : return process_5(arglist); + default : return std::numeric_limits::quiet_NaN(); + } + } + } + + template + static inline T process_1(const Sequence& arglist) + { + return value(arglist[0]); + } + + template + static inline T process_2(const Sequence& arglist) + { + return value(arglist[0]) + value(arglist[1]); + } + + template + static inline T process_3(const Sequence& arglist) + { + return value(arglist[0]) + value(arglist[1]) + + value(arglist[2]); + } + + template + static inline T process_4(const Sequence& arglist) + { + return value(arglist[0]) + value(arglist[1]) + + value(arglist[2]) + value(arglist[3]); + } + + template + static inline T process_5(const Sequence& arglist) + { + return value(arglist[0]) + value(arglist[1]) + + value(arglist[2]) + value(arglist[3]) + + value(arglist[4]); + } + }; + + template + struct vararg_mul_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arglist) + { + if (arglist.size() > 5) + { + T result = T(value(arglist[0])); + for (std::size_t i = 1; i < arglist.size(); ++i) + { + result *= value(arglist[i]); + } + return result; + } + else + { + switch (arglist.size()) + { + case 0 : return T(0); + case 1 : return process_1(arglist); + case 2 : return process_2(arglist); + case 3 : return process_3(arglist); + case 4 : return process_4(arglist); + case 5 : return process_5(arglist); + default : return std::numeric_limits::quiet_NaN(); + } + } + } + + template + static inline T process_1(const Sequence& arglist) + { + return value(arglist[0]); + } + + template + static inline T process_2(const Sequence& arglist) + { + return value(arglist[0]) * value(arglist[1]); + } + + template + static inline T process_3(const Sequence& arglist) + { + return value(arglist[0]) * value(arglist[1]) * + value(arglist[2]); + } + + template + static inline T process_4(const Sequence& arglist) + { + return value(arglist[0]) * value(arglist[1]) * + value(arglist[2]) * value(arglist[3]); + } + + template + static inline T process_5(const Sequence& arglist) + { + return value(arglist[0]) * value(arglist[1]) * + value(arglist[2]) * value(arglist[3]) * + value(arglist[4]); + } + }; + + template + struct vararg_avg_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arglist) + { + if (arglist.size() > 5) + { + return vararg_add_op::process(arglist) / arglist.size(); + } + else + { + switch (arglist.size()) + { + case 0 : return T(0); + case 1 : return process_1(arglist); + case 2 : return process_2(arglist); + case 3 : return process_3(arglist); + case 4 : return process_4(arglist); + case 5 : return process_5(arglist); + default : return std::numeric_limits::quiet_NaN(); + } + } + } + + template + static inline T process_1(const Sequence& arglist) + { + return value(arglist[0]); + } + + template + static inline T process_2(const Sequence& arglist) + { + return (value(arglist[0]) + value(arglist[1])) / T(2); + } + + template + static inline T process_3(const Sequence& arglist) + { + return (value(arglist[0]) + value(arglist[1]) + value(arglist[2])) / T(3); + } + + template + static inline T process_4(const Sequence& arglist) + { + return (value(arglist[0]) + value(arglist[1]) + + value(arglist[2]) + value(arglist[3])) / T(4); + } + + template + static inline T process_5(const Sequence& arglist) + { + return (value(arglist[0]) + value(arglist[1]) + + value(arglist[2]) + value(arglist[3]) + + value(arglist[4])) / T(5); + } + }; + + template + struct vararg_min_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arglist) + { + if (arglist.size() > 5) + { + T result = T(value(arglist[0])); + for (std::size_t i = 1; i < arglist.size(); ++i) + { + const T v = value(arglist[i]); + if (v < result) + result = v; + } + return result; + } + else + { + switch (arglist.size()) + { + case 0 : return T(0); + case 1 : return process_1(arglist); + case 2 : return process_2(arglist); + case 3 : return process_3(arglist); + case 4 : return process_4(arglist); + case 5 : return process_5(arglist); + default : return std::numeric_limits::quiet_NaN(); + } + } + } + + template + static inline T process_1(const Sequence& arglist) + { + return value(arglist[0]); + } + + template + static inline T process_2(const Sequence& arglist) + { + return std::min(value(arglist[0]),value(arglist[1])); + } + + template + static inline T process_3(const Sequence& arglist) + { + return std::min(std::min(value(arglist[0]),value(arglist[1])),value(arglist[2])); + } + + template + static inline T process_4(const Sequence& arglist) + { + return std::min( + std::min(value(arglist[0]),value(arglist[1])), + std::min(value(arglist[2]),value(arglist[3]))); + } + + template + static inline T process_5(const Sequence& arglist) + { + return std::min( + std::min(std::min(value(arglist[0]),value(arglist[1])), + std::min(value(arglist[2]),value(arglist[3]))), + value(arglist[4])); + } + }; + + template + struct vararg_max_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arglist) + { + if (arglist.size() > 5) + { + T result = T(value(arglist[0])); + for (std::size_t i = 1; i < arglist.size(); ++i) + { + const T v = value(arglist[i]); + if (v > result) + result = v; + } + return result; + } + else + { + switch (arglist.size()) + { + case 0 : return T(0); + case 1 : return process_1(arglist); + case 2 : return process_2(arglist); + case 3 : return process_3(arglist); + case 4 : return process_4(arglist); + case 5 : return process_5(arglist); + default : return std::numeric_limits::quiet_NaN(); + } + } + } + + template + static inline T process_1(const Sequence& arglist) + { + return value(arglist[0]); + } + + template + static inline T process_2(const Sequence& arglist) + { + return std::max(value(arglist[0]),value(arglist[1])); + } + + template + static inline T process_3(const Sequence& arglist) + { + return std::max(std::max(value(arglist[0]),value(arglist[1])),value(arglist[2])); + } + + template + static inline T process_4(const Sequence& arglist) + { + return std::max( + std::max(value(arglist[0]),value(arglist[1])), + std::max(value(arglist[2]),value(arglist[3]))); + } + + template + static inline T process_5(const Sequence& arglist) + { + return std::max( + std::max(std::max(value(arglist[0]),value(arglist[1])), + std::max(value(arglist[2]),value(arglist[3]))), + value(arglist[4])); + } + }; + + template + struct vararg_mand_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arglist) + { + if (arglist.size() > 5) + { + for (std::size_t i = 0; i < arglist.size(); ++i) + { + if (T(0) == value(arglist[i])) + return T(0); + } + return T(1); + } + else + { + switch (arglist.size()) + { + case 1 : return process_1(arglist); + case 2 : return process_2(arglist); + case 3 : return process_3(arglist); + case 4 : return process_4(arglist); + case 5 : return process_5(arglist); + default : return T(0); + } + } + } + + template + static inline T process_1(const Sequence& arglist) + { + return (T(0) != value(arglist[0])) ? T(1) : T(0); + } + + template + static inline T process_2(const Sequence& arglist) + { + return ( + (T(0) != value(arglist[0])) && (T(0) != value(arglist[1])) + ) ? T(1) : T(0); + } + + template + static inline T process_3(const Sequence& arglist) + { + return ( + (T(0) != value(arglist[0])) && (T(0) != value(arglist[1])) && + (T(0) != value(arglist[2])) + ) ? T(1) : T(0); + } + + template + static inline T process_4(const Sequence& arglist) + { + return ( + (T(0) != value(arglist[0])) && (T(0) != value(arglist[1])) && + (T(0) != value(arglist[2])) && (T(0) != value(arglist[3])) + ) ? T(1) : T(0); + } + + template + static inline T process_5(const Sequence& arglist) + { + return ( + (T(0) != value(arglist[0])) && (T(0) != value(arglist[1])) && + (T(0) != value(arglist[2])) && (T(0) != value(arglist[3])) && + (T(0) != value(arglist[4])) + ) ? T(1) : T(0); + } + }; + + template + struct vararg_mor_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arglist) + { + if (arglist.size() > 5) + { + for (std::size_t i = 0; i < arglist.size(); ++i) + { + if (T(0) != value(arglist[i])) + return T(1); + } + return T(0); + } + else + { + switch (arglist.size()) + { + case 1 : return process_1(arglist); + case 2 : return process_2(arglist); + case 3 : return process_3(arglist); + case 4 : return process_4(arglist); + case 5 : return process_5(arglist); + default : return T(0); + } + } + } + + template + static inline T process_1(const Sequence& arglist) + { + return (T(0) != value(arglist[0])) ? T(1) : T(0); + } + + template + static inline T process_2(const Sequence& arglist) + { + return ( + (T(0) != value(arglist[0])) || (T(0) != value(arglist[1])) + ) ? T(1) : T(0); + } + + template + static inline T process_3(const Sequence& arglist) + { + return ( + (T(0) != value(arglist[0])) || (T(0) != value(arglist[1])) || + (T(0) != value(arglist[2])) + ) ? T(1) : T(0); + } + + template + static inline T process_4(const Sequence& arglist) + { + return ( + (T(0) != value(arglist[0])) || (T(0) != value(arglist[1])) || + (T(0) != value(arglist[2])) || (T(0) != value(arglist[3])) + ) ? T(1) : T(0); + } + + template + static inline T process_5(const Sequence& arglist) + { + return ( + (T(0) != value(arglist[0])) || (T(0) != value(arglist[1])) || + (T(0) != value(arglist[2])) || (T(0) != value(arglist[3])) || + (T(0) != value(arglist[4])) + ) ? T(1) : T(0); + } + }; + template class vov_base_node : public expression_node { @@ -6591,6 +7325,15 @@ namespace exprtk return new node_type(); } + template class Sequence> + inline expression_node* allocate(const Sequence& seq) const + { + return new node_type(seq); + } + template inline expression_node* allocate(T1& t1) const { @@ -6832,11 +7575,6 @@ namespace exprtk register_op( "frac",e_frac , 1) register_op( "trunc",e_trunc , 1) register_op( "atan2",e_atan2 , 2) - register_op( "min",e_min , 2) - register_op( "max",e_max , 2) - register_op( "avg",e_avg , 2) - register_op( "sum",e_sum , 2) - register_op( "mul",e_prod , 2) register_op( "mod",e_mod , 2) register_op( "logn",e_logn , 2) register_op( "pow",e_pow , 2) @@ -6849,26 +7587,6 @@ namespace exprtk register_op( "shl",e_shl , 2) register_op( "clamp",e_clamp , 3) register_op( "inrange",e_inrange , 3) - register_op( "min",e_min , 3) - register_op( "max",e_max , 3) - register_op( "avg",e_avg , 3) - register_op( "sum",e_sum , 3) - register_op( "mul",e_prod , 3) - register_op( "min",e_min , 4) - register_op( "max",e_max , 4) - register_op( "avg",e_avg , 4) - register_op( "sum",e_sum , 4) - register_op( "mul",e_prod , 4) - register_op( "min",e_min , 5) - register_op( "max",e_max , 5) - register_op( "avg",e_avg , 5) - register_op( "sum",e_sum , 5) - register_op( "mul",e_prod , 5) - register_op( "min",e_min , 6) - register_op( "max",e_max , 6) - register_op( "avg",e_avg , 6) - register_op( "sum",e_sum , 6) - register_op( "mul",e_prod , 6) #undef register_op } @@ -7002,7 +7720,20 @@ namespace exprtk { return std::numeric_limits::quiet_NaN(); } + }; + template + class ivararg_function + { + public: + + virtual ~ivararg_function() + {} + + inline virtual T operator()(const std::vector&) + { + return std::numeric_limits::quiet_NaN(); + } }; template @@ -7121,6 +7852,7 @@ namespace exprtk { typedef typename details::variable_node variable_node_t; typedef ifunction ifunction_t; + typedef ivararg_function ivararg_function_t; typedef vector_holder vector_t; #ifndef exprtk_disable_string_capabilities typedef typename details::stringvar_node stringvar_node_t; @@ -7256,6 +7988,11 @@ namespace exprtk { return std::make_pair(is_constant,&t); } + + static inline std::pair make(vararg_function_t& t, const bool is_constant = false) + { + return std::make_pair(is_constant,&t); + } }; if (1 == symbol_name.size()) @@ -7476,7 +8213,9 @@ namespace exprtk typedef stringvar_t* stringvar_ptr; #endif typedef ifunction function_t; + typedef ivararg_function vararg_function_t; typedef function_t* function_ptr; + typedef vararg_function_t* vararg_function_ptr; typedef vector_holder* vector_ptr; static const std::size_t lut_size = 256; @@ -7491,6 +8230,7 @@ namespace exprtk type_store,std::string> stringvar_store; #endif type_store,ifunction > function_store; + type_store,ivararg_function > vararg_function_store; type_store,vector_holder > vector_store; st_data() @@ -7660,6 +8400,16 @@ namespace exprtk return local_data().function_store.get(function_name); } + inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) + { + if (!valid()) + return reinterpret_cast(0); + else if (!valid_symbol(vararg_function_name)) + return reinterpret_cast(0); + else + return local_data().vararg_function_store.get(vararg_function_name); + } + inline vector_ptr get_vector(const std::string& vector_name) { if (!valid()) @@ -7799,6 +8549,18 @@ namespace exprtk return local_data().function_store.add(function_name,function); } + inline bool add_vararg_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) + { + if (!valid()) + return false; + else if (!valid_symbol(vararg_function_name)) + return false; + else if (symbol_exists(vararg_function_name)) + return false; + else + return local_data().vararg_function_store.add(vararg_function_name,vararg_function); + } + inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) { if (!valid()) @@ -7863,6 +8625,14 @@ namespace exprtk return local_data().function_store.remove(function_name); } + inline bool remove_vararg_function(const std::string& vararg_function_name) + { + if (!valid()) + return false; + else + return local_data().vararg_function_store.remove(vararg_function_name); + } + inline bool remove_vector(const std::string& vector_name) { if (!valid()) @@ -7996,6 +8766,14 @@ namespace exprtk return local_data().function_store.symbol_exists(function_name); } + inline bool is_vararg_function(const std::string& vararg_function_name) const + { + if (!valid()) + return false; + else + return local_data().vararg_function_store.symbol_exists(vararg_function_name); + } + inline bool valid() const { //symbol table sanity check. @@ -8323,7 +9101,9 @@ namespace exprtk typedef const T& cref_t; typedef const T const_t; typedef ifunction F; + typedef ivararg_function VAF; typedef ifunction ifunction_t; + typedef ivararg_function ivararg_function_t; typedef details::expression_node expression_node_t; typedef details::literal_node literal_node_t; typedef details::string_literal_node string_literal_node_t; @@ -8340,6 +9120,8 @@ namespace exprtk typedef details::stringvar_node stringvar_node_t; #endif typedef details::assignment_node assignment_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; @@ -8543,7 +9325,10 @@ namespace exprtk default : diagnostic + "Unknown compiler error"; break; } - set_error(make_error(parser_error::e_lexer,lexer_[i],diagnostic + ": " + lexer_[i].value)); + set_error( + make_error(parser_error::e_lexer, + lexer_[i], + diagnostic + ": " + lexer_[i].value)); } } } @@ -8714,6 +9499,27 @@ namespace exprtk return (base_ops_map_.end() != base_ops_map_.find(symbol)); } + inline bool valid_vararg_operation(const std::string& symbol) + { + static const std::string s_sum = "sum" ; + static const std::string s_mul = "mul" ; + static const std::string s_avg = "avg" ; + static const std::string s_min = "min" ; + static const std::string s_max = "max" ; + static const std::string s_mand = "mand"; + static const std::string s_mor = "mor" ; + return + ( + details::imatch(symbol,s_sum ) || + details::imatch(symbol,s_mul ) || + details::imatch(symbol,s_avg ) || + details::imatch(symbol,s_min ) || + details::imatch(symbol,s_max ) || + details::imatch(symbol,s_mand) || + details::imatch(symbol,s_mor ) + ); + } + inline void store_token() { lexer_.store(); @@ -8801,27 +9607,39 @@ namespace exprtk static const std::string s_and1 = "&"; static const std::string s_or1 = "|"; - if ( - details::imatch(current_token_.value,s_and ) || - details::imatch(current_token_.value,s_and1) - ) + if (details::imatch(current_token_.value,s_and)) { current_state.set(e_level01,e_level02,details::e_and); break; } + else if (details::imatch(current_token_.value,s_and1)) + { + #ifndef exprtk_disable_sc_andor + current_state.set(e_level01,e_level02,details::e_scand); + #else + current_state.set(e_level01,e_level02,details::e_and); + #endif + break; + } else if (details::imatch(current_token_.value,s_nand)) { current_state.set(e_level01,e_level02,details::e_nand); break; } - else if ( - details::imatch(current_token_.value,s_or ) || - details::imatch(current_token_.value,s_or1) - ) + else if (details::imatch(current_token_.value,s_or)) { current_state.set(e_level03,e_level04,details::e_or); break; } + else if (details::imatch(current_token_.value,s_or1)) + { + #ifndef exprtk_disable_sc_andor + current_state.set(e_level03,e_level04,details::e_scor); + #else + current_state.set(e_level03,e_level04,details::e_or); + #endif + break; + } else if (details::imatch(current_token_.value,s_nor)) { current_state.set(e_level03,e_level04,details::e_nor); @@ -8920,6 +9738,71 @@ namespace exprtk scoped_delete& operator=(const scoped_delete&); }; + template + struct scoped_deq_delete + { + typedef Type* ptr_t; + + scoped_deq_delete(parser& pr, std::deque& deq) + : delete_ptr(true), + parser_(pr), + deq_(deq) + {} + + ~scoped_deq_delete() + { + if (delete_ptr) + { + for (std::size_t i = 0; i < deq_.size(); ++i) + { + free_node(parser_.node_allocator_,deq_[i]); + } + deq_.clear(); + } + } + + bool delete_ptr; + parser& parser_; + std::deque& deq_; + + private: + + scoped_deq_delete& operator=(const scoped_deq_delete&); + }; + + template + struct scoped_vec_delete + { + typedef Type* ptr_t; + + scoped_vec_delete(parser& pr, std::vector& vec) + : delete_ptr(true), + parser_(pr), + vec_(vec) + {} + + ~scoped_vec_delete() + { + if (delete_ptr) + { + for (std::size_t i = 0; i < vec_.size(); ++i) + { + free_node(parser_.node_allocator_,vec_[i]); + } + vec_.clear(); + } + } + + bool delete_ptr; + parser& parser_; + std::vector& vec_; + + private: + + scoped_vec_delete& operator=(const scoped_vec_delete&); + }; + + template inline expression_node_ptr parse_function_call(const details::operator_type& opt_type, bool& internal_error) { @@ -9174,14 +10057,119 @@ namespace exprtk { set_error( make_error(parser_error::e_syntax, - current_token_, - "ERR19 - Failed to parse branch for while-loop")); + current_token_, + "ERR19 - Failed to parse branch for while-loop")); return error_node(); } else return result; } + inline expression_node_ptr parse_vararg_function() + { + std::deque arg_list; + expression_node_ptr result = error_node(); + + details::operator_type opt_type = details::e_default; + const std::string symbol = current_token_.value; + + if (details::imatch(symbol,"sum" )) opt_type = details::e_sum; + else if (details::imatch(symbol,"mul" )) opt_type = details::e_prod; + else if (details::imatch(symbol,"avg" )) opt_type = details::e_avg; + else if (details::imatch(symbol,"min" )) opt_type = details::e_min; + else if (details::imatch(symbol,"max" )) opt_type = details::e_max; + else if (details::imatch(symbol,"mand")) opt_type = details::e_mand; + else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR20 - Unsupported vararg function: " + symbol)); + return error_node(); + } + + scoped_deq_delete sdd(*this,arg_list); + + next_token(); + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR21 - Expected '(' for call to vararg function: " + symbol)); + return error_node(); + } + + for (;;) + { + expression_node_ptr arg = parse_expression(); + if (0 == arg) + return error_node(); + else + arg_list.push_back(arg); + if (token_is(token_t::e_rbracket)) + break; + else if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR22 - Expected ',' for call to vararg function: " + symbol)); + return error_node(); + } + } + + result = expression_generator_.vararg_function(opt_type,arg_list); + + sdd.delete_ptr = (0 == result); + return result; + } + + inline expression_node_ptr parse_vararg_function_call(ivararg_function* vararg_function, const std::string& vararg_function_name) + { + std::vector arg_list; + expression_node_ptr result = error_node(); + + const std::string symbol = current_token_.value; + + scoped_vec_delete sdd(*this,arg_list); + + next_token(); + if (!token_is(token_t::e_lbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR21 - Expected '(' for call to vararg function: " + vararg_function_name)); + return error_node(); + } + + for (;;) + { + expression_node_ptr arg = parse_expression(); + if (0 == arg) + return error_node(); + else + arg_list.push_back(arg); + if (token_is(token_t::e_rbracket)) + break; + else if (!token_is(token_t::e_comma)) + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR22 - Expected ',' for call to vararg function: " + vararg_function_name)); + return error_node(); + } + } + + result = expression_generator_.vararg_function_call(vararg_function,arg_list); + + sdd.delete_ptr = (0 == result); + return result; + } + template struct parse_special_function_impl { @@ -9216,7 +10204,7 @@ namespace exprtk return p.error_node(); else result = p.expression_generator_.special_function(opt_type,branch); - sd.delete_ptr = false; + sd.delete_ptr = (0 == result); return result; } }; @@ -9232,7 +10220,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token_, - "ERR20 - Invalid special function[1]: " + current_token_.value)); + "ERR23 - Invalid special function[1]: " + current_token_.value)); return error_node(); } @@ -9243,7 +10231,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token_, - "ERR21 - Invalid special function[2]: " + current_token_.value)); + "ERR24 - Invalid special function[2]: " + current_token_.value)); return error_node(); } @@ -9335,7 +10323,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR22 - Invalid number of parameters for function: " + symbol)); + "ERR25 - Invalid number of parameters for function: " + symbol)); return error_node(); } } @@ -9347,7 +10335,27 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR23 - Failed to generate node for function: '" + symbol + "'")); + "ERR26 - Failed to generate node for function: '" + symbol + "'")); + return error_node(); + } + } + + // Are we dealing with a vararg function? + ivararg_function* vararg_function = symbol_table_.get_vararg_function(symbol); + + if (vararg_function) + { + expression_node_ptr vararg_func_node = error_node(); + vararg_func_node = parse_vararg_function_call(vararg_function,symbol); + + if (vararg_func_node) + return vararg_func_node; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR27 - Failed to generate node for vararg function: '" + symbol + "'")); return error_node(); } } @@ -9356,18 +10364,22 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR24 - Undefined variable or function: '" + symbol + "'")); + "ERR28 - Undefined variable or function: '" + symbol + "'")); return error_node(); } } inline expression_node_ptr parse_symbol() { - static const std::string symbol_if = "if"; + static const std::string symbol_if = "if"; static const std::string symbol_while = "while"; - static const std::string symbol_null = "null"; + static const std::string symbol_null = "null"; - if (valid_base_operation(current_token_.value)) + if (valid_vararg_operation(current_token_.value)) + { + return parse_vararg_function(); + } + else if (valid_base_operation(current_token_.value)) { return parse_base_operation(); } @@ -9396,7 +10408,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token_, - "ERR25 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value)); + "ERR29 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value)); return error_node(); } } @@ -9471,7 +10483,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR26 - Premature end of expression.[1]")); + "ERR30 - Premature end of expression.[1]")); return error_node(); } else @@ -9479,7 +10491,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR27 - Premature end of expression.[2]")); + "ERR31 - Premature end of expression.[2]")); return error_node(); } } @@ -9936,6 +10948,18 @@ namespace exprtk return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); } + #ifndef exprtk_disable_sc_andor + inline bool is_shortcircuit_expression(const details::operator_type& operation) + { + return ((details::e_scand == operation) || (details::e_scor == operation)); + } + #else + inline bool is_shortcircuit_expression(const details::operator_type&) + { + return false; + } + #endif + inline bool is_null_present(expression_node_ptr (&branch)[2]) { return details::is_null_node(branch[0]) || @@ -9953,6 +10977,8 @@ namespace exprtk return error_node(); else if (details::e_assign == operation) return synthesize_assignment_expression(operation,branch); + else if (is_shortcircuit_expression(operation)) + return synthesize_shortcircuit_expression(operation,branch); else if (is_string_operation(operation,branch)) return synthesize_string_expression(operation,branch); else if (is_null_present(branch)) @@ -10383,6 +11409,76 @@ namespace exprtk } } + template class Sequence> + inline expression_node_ptr const_optimize_varargfunc(const details::operator_type& operation, Sequence& arglist) + { + expression_node_ptr temp_node = error_node(); + switch (operation) + { + #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate > >(arglist); break; + case_stmt(details::e_sum, details::vararg_add_op ) + case_stmt(details::e_prod, details::vararg_mul_op ) + case_stmt(details::e_avg, details::vararg_avg_op ) + case_stmt(details::e_min, details::vararg_min_op ) + case_stmt(details::e_max, details::vararg_max_op ) + case_stmt(details::e_mand, details::vararg_mand_op) + case_stmt(details::e_mor, details::vararg_mor_op ) + #undef case_stmt + default : return error_node(); + } + T v = temp_node->value(); + details::free_node(*node_allocator_,temp_node); + return node_allocator_->allocate(v); + } + + template class Sequence> + inline expression_node_ptr varnode_optimize_varargfunc(const details::operator_type& operation, Sequence& arglist) + { + switch (operation) + { + #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(arglist); + case_stmt(details::e_sum, details::vararg_add_op ) + case_stmt(details::e_prod, details::vararg_mul_op ) + case_stmt(details::e_avg, details::vararg_avg_op ) + case_stmt(details::e_min, details::vararg_min_op ) + case_stmt(details::e_max, details::vararg_max_op ) + case_stmt(details::e_mand, details::vararg_mand_op) + case_stmt(details::e_mor, details::vararg_mor_op ) + #undef case_stmt + default : return error_node(); + } + } + + template class Sequence> + inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence& arglist) + { + if (!all_nodes_valid(arglist)) + { + details::free_all_nodes(*node_allocator_,arglist); + return error_node(); + } + else if (is_constant_foldable(arglist)) + return const_optimize_varargfunc(operation,arglist); + else if (all_nodes_variables(arglist)) + return varnode_optimize_varargfunc(operation,arglist); + switch (operation) + { + #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(arglist); + case_stmt(details::e_sum, details::vararg_add_op ) + case_stmt(details::e_prod, details::vararg_mul_op ) + case_stmt(details::e_avg, details::vararg_avg_op ) + case_stmt(details::e_min, details::vararg_min_op ) + case_stmt(details::e_max, details::vararg_max_op ) + case_stmt(details::e_mand, details::vararg_mand_op) + case_stmt(details::e_mor, details::vararg_mor_op ) + #undef case_stmt + default : return error_node(); + } + } + template inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) { @@ -10392,23 +11488,32 @@ namespace exprtk return error_node(); else { - // Has the function call been completely optimized? + // Can the function call be completely optimized? if (details::is_constant_node(result)) return result; else if (!all_nodes_valid(b)) return error_node(); else if (N != f->param_count) + { + details::free_all_nodes(*node_allocator_,b); return error_node(); + } function_N_node_t* func_node_ptr = dynamic_cast(result); if (func_node_ptr) { if (func_node_ptr->init_branches(b)) return result; else + { + details::free_all_nodes(*node_allocator_,b); return error_node(); + } } else + { + details::free_all_nodes(*node_allocator_,b); return error_node(); + } } } @@ -10418,6 +11523,26 @@ namespace exprtk return node_allocator_->allocate(f); } + inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, + std::vector& arglist) + { + if (!all_nodes_valid(arglist)) + { + details::free_all_nodes(*node_allocator_,arglist); + return error_node(); + } + + expression_node_ptr result = node_allocator_->allocate > >(vaf,arglist); + + if (is_constant_foldable(arglist)) + { + T v = result->value(); + details::free_node(*node_allocator_,result); + result = node_allocator_->allocate(v); + } + return result; + } + private: template @@ -10433,6 +11558,21 @@ namespace exprtk return true; } + template class Sequence> + inline bool is_constant_foldable(const Sequence& b) const + { + for (std::size_t i = 0; i < b.size(); ++i) + { + if (0 == b[i]) + return false; + else if (!details::is_constant_node(b[i])) + return false; + } + return true; + } + inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) { if (details::is_variable_node(branch[0])) @@ -10441,6 +11581,46 @@ namespace exprtk return error_node(); } + #ifndef exprtk_disable_sc_andor + inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) + { + expression_node_ptr result = error_node(); + if (details::is_constant_node(branch[0])) + { + if ((details::e_scand == operation) && (T(0) == branch[0]->value())) + result = node_allocator_->allocate_c(T(0)); + else if ((details::e_scor == operation) && (T(0) != branch[0]->value())) + result = node_allocator_->allocate_c(T(1)); + } + + if (details::is_constant_node(branch[1]) && (0 == result)) + { + if ((details::e_scand == operation) && (T(0) == branch[1]->value())) + result = node_allocator_->allocate_c(T(0)); + else if ((details::e_scor == operation) && (T(0) != branch[1]->value())) + result = node_allocator_->allocate_c(T(1)); + } + + if (result) + { + free_node(*node_allocator_,branch[0]); + free_node(*node_allocator_,branch[1]); + return result; + } + else if (details::e_scand == operation) + return synthesize_expression(operation,branch); + else if (details::e_scor == operation) + return synthesize_expression(operation,branch); + else + return error_node(); + } + #else + inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) + { + return error_node(); + } + #endif + #define basic_opr_switch_statements \ case_stmt(details:: e_add,details:: add_op) \ case_stmt(details:: e_sub,details:: sub_op) \ @@ -14029,9 +15209,9 @@ namespace exprtk /* Note: The following 'compute' routines are very simple helpers, for quickly setting up the required pieces of code in order to - evaluate an expression. By virtue of how they the operate there - will be an overhead with regards to their setup and teardown and - hence should not be used in time critical sections of code. + evaluate an expression. By virtue of how they operate there will + be an overhead with regards to their setup and teardown and hence + should not be used in time critical sections of code. Furthermore they only assume a small sub set of variables - no string variables or user defined functions. */ @@ -14691,7 +15871,7 @@ namespace exprtk namespace information { static const char* library = "Mathematical Expression Toolkit"; - static const char* version = "2.7182818284590452353602874713"; + static const char* version = "2.718281828459045235360287471352"; static const char* date = "20130330"; static inline std::string data() diff --git a/exprtk_test.cpp b/exprtk_test.cpp index e638cdf..8ebb894 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -27,827 +27,869 @@ #include "exprtk.hpp" + typedef std::pair test_t; static const test_t test_list[] = - { - // Note: The each of following tests should - // all 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("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("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(" 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+2)",-3.0), - test_t("+(1+2)",+3.0), - test_t("+(1-2)",-1.0), - test_t("-(1-2)",+1.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^1",9.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("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("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("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("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("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^2+3.3)",1.0), - test_t("equal($f31(1.1,2.2,3.3),1.1*2.2^3+3.3)",1.0), - test_t("equal($f32(1.1,2.2,3.3),1.1*2.2^4+3.3)",1.0), - test_t("equal($f33(1.1,2.2,3.3),1.1*2.2^5+3.3)",1.0), - test_t("equal($f34(1.1,2.2,3.3),1.1*2.2^6+3.3)",1.0), - test_t("equal($f35(1.1,2.2,3.3),1.1*2.2^7+3.3)",1.0), - test_t("equal($f36(1.1,2.2,3.3),1.1*2.2^8+3.3)",1.0), - test_t("equal($f37(1.1,2.2,3.3),1.1*2.2^9+3.3)",1.0), - test_t("equal($f38(1.1,2.2,3.3),1.1*log(2.2)+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*log10(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*sin(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*cos(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),if(0!=1.1,2.2,3.3))",1.0), - test_t("equal($f47(1.1,2.2,3.3,4.4),1.1+((2.2+3.3)/4.4))",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^2+3.3*4.4^2)",1.0), - test_t("equal($f84(1.1,2.2,3.3,4.4),1.1*2.2^3+3.3*4.4^3)",1.0), - test_t("equal($f85(1.1,2.2,3.3,4.4),1.1*2.2^4+3.3*4.4^4)",1.0), - test_t("equal($f86(1.1,2.2,3.3,4.4),1.1*2.2^5+3.3*4.4^5)",1.0), - test_t("equal($f87(1.1,2.2,3.3,4.4),1.1*2.2^6+3.3*4.4^6)",1.0), - test_t("equal($f88(1.1,2.2,3.3,4.4),1.1*2.2^7+3.3*4.4^7)",1.0), - test_t("equal($f89(1.1,2.2,3.3,4.4),1.1*2.2^8+3.3*4.4^8)",1.0), - test_t("equal($f90(1.1,2.2,3.3,4.4),1.1*2.2^9+3.3*4.4^9)",1.0), - test_t("equal($f91(1.1,2.2,3.3,4.4),if(1.1 and 2.2,3.3,4.4))",1.0), - test_t("equal($f92(1.1,2.2,3.3,4.4),if(1.1 or 2.2,3.3,4.4))",1.0), - test_t("equal($f93(1.1,2.2,3.3,4.4),if(1.1 < 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(equal(1.1,2.2),3.3,4.4))",1.0), - test_t("equal($f98(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) - }; + { + // Note: Each of following tests should all + // 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("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("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(" 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+2)",-3.0), + test_t("+(1+2)",+3.0), + test_t("+(1-2)",-1.0), + test_t("-(1-2)",+1.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^1",9.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("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("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("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^2+3.3)",1.0), + test_t("equal($f31(1.1,2.2,3.3),1.1*2.2^3+3.3)",1.0), + test_t("equal($f32(1.1,2.2,3.3),1.1*2.2^4+3.3)",1.0), + test_t("equal($f33(1.1,2.2,3.3),1.1*2.2^5+3.3)",1.0), + test_t("equal($f34(1.1,2.2,3.3),1.1*2.2^6+3.3)",1.0), + test_t("equal($f35(1.1,2.2,3.3),1.1*2.2^7+3.3)",1.0), + test_t("equal($f36(1.1,2.2,3.3),1.1*2.2^8+3.3)",1.0), + test_t("equal($f37(1.1,2.2,3.3),1.1*2.2^9+3.3)",1.0), + test_t("equal($f38(1.1,2.2,3.3),1.1*log(2.2)+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*log10(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*sin(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*cos(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),if(0!=1.1,2.2,3.3))",1.0), + test_t("equal($f47(1.1,2.2,3.3,4.4),1.1+((2.2+3.3)/4.4))",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^2+3.3*4.4^2)",1.0), + test_t("equal($f84(1.1,2.2,3.3,4.4),1.1*2.2^3+3.3*4.4^3)",1.0), + test_t("equal($f85(1.1,2.2,3.3,4.4),1.1*2.2^4+3.3*4.4^4)",1.0), + test_t("equal($f86(1.1,2.2,3.3,4.4),1.1*2.2^5+3.3*4.4^5)",1.0), + test_t("equal($f87(1.1,2.2,3.3,4.4),1.1*2.2^6+3.3*4.4^6)",1.0), + test_t("equal($f88(1.1,2.2,3.3,4.4),1.1*2.2^7+3.3*4.4^7)",1.0), + test_t("equal($f89(1.1,2.2,3.3,4.4),1.1*2.2^8+3.3*4.4^8)",1.0), + test_t("equal($f90(1.1,2.2,3.3,4.4),1.1*2.2^9+3.3*4.4^9)",1.0), + test_t("equal($f91(1.1,2.2,3.3,4.4),if(1.1 and 2.2,3.3,4.4))",1.0), + test_t("equal($f92(1.1,2.2,3.3,4.4),if(1.1 or 2.2,3.3,4.4))",1.0), + test_t("equal($f93(1.1,2.2,3.3,4.4),if(1.1 < 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(equal(1.1,2.2),3.3,4.4))",1.0), + test_t("equal($f98(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), + }; static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_t); @@ -2486,7 +2528,19 @@ inline bool run_test12() "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(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); @@ -2656,6 +2710,10 @@ inline std::size_t load_expressions(const std::string& file_name, std::size_t line_count = 0; while (std::getline(stream,buffer)) { + if (buffer.empty()) + continue; + else if ('#' == buffer[0]) + continue; ++line_count; sequence.push_back(buffer); } @@ -2774,30 +2832,32 @@ inline bool run_test15() symbol_table.add_variable("y",y); symbol_table.add_variable("z",z); - std::deque expr_str_list; - - expr_str_list.push_back("2 - (x + y) / z//Comment 01 "); - expr_str_list.push_back("2 - (x + y) / z#Comment 02 "); - expr_str_list.push_back("2 - (x + y) / z //Comment 03 "); - expr_str_list.push_back("2 - (x + y) / z #Comment 04 "); - expr_str_list.push_back("2 - (x + y) / z//Comment 05 \n"); - expr_str_list.push_back("2 - (x + y) / z#Comment 06 \n"); - expr_str_list.push_back("2 - (x + y) / z //Comment 07\n"); - expr_str_list.push_back("2 - (x + y) / z #Comment 08 \n"); - expr_str_list.push_back("/* Comment 09*/2 - (x + y) / z"); - expr_str_list.push_back("/* Comment 10*/2 - (x + y) / z\n"); - expr_str_list.push_back("/* Comment 11*/2 - (x + y) / z/* Comment 12*/"); - expr_str_list.push_back("/* Comment 13*/2 - (x + y) / z/* Comment 14*/\n"); - expr_str_list.push_back("2 - /* Comment 15 */(x + y) / z"); - expr_str_list.push_back("2 - /* Comment 15 */(x + y) /* Comment 16 *// z \n"); - expr_str_list.push_back("2 - /* Comment 17 */(x + y) /* Comment 18 */ / z //Comment 19\n"); - expr_str_list.push_back("2 - /* Comment 20 */(x + y) /* Comment 21 */ / z #Comment 22\n"); - expr_str_list.push_back("2 - /* Comment 23 */(x + y) /* Comment 24 */ / z //Comment 25"); - expr_str_list.push_back("2 - /* Comment 26 */(x + y) /* Comment 27 */ / z #Comment 28"); + 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 15 */(x + y) /* Comment 16 *// z \n", + "2 - /* Comment 17 */(x + y) /* Comment 18 */ / z //Comment 19\n", + "2 - /* Comment 20 */(x + y) /* Comment 21 */ / z #Comment 22\n", + "2 - /* Comment 23 */(x + y) /* Comment 24 */ / z //Comment 25", + "2 - /* Comment 26 */(x + y) /* Comment 27 */ / z #Comment 28" + }; + static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); std::deque expression_list; - for (std::size_t i = 0; i < expr_str_list.size(); ++i) + for (std::size_t i = 0; i < expr_str_list_size; ++i) { expression_t expression; expression.register_symbol_table(symbol_table); @@ -2852,6 +2912,367 @@ inline bool run_test15() return !failure; } +template +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); } +}; + +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 +inline bool run_test16() +{ + typedef exprtk::expression expression_t; + + T x = T(1.1); + T y = T(2.2); + T z = T(3.3); + T w = T(4.4); + T u = T(5.5); + + test_func0 test_func00; + test_func1 test_func01; + test_func2 test_func02; + test_func3 test_func03; + test_func4 test_func04; + test_func5 test_func05; + + exprtk::symbol_table 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_function("test_func0",test_func00); + symbol_table.add_function("test_func1",test_func01); + symbol_table.add_function("test_func2",test_func02); + symbol_table.add_function("test_func3",test_func03); + symbol_table.add_function("test_func4",test_func04); + 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))" + }; + static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); + + std::deque expression_list; + + for (std::size_t i = 0; i < expr_str_list_size; ++i) + { + expression_t expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + + if (!parser.compile(expr_str_list[i],expression)) + { + printf("run_test16() - Error: %s Expression: %s\n", + parser.error().c_str(), + expr_str_list[i].c_str()); + return false; + } + else + expression_list.push_back(expression); + } + + bool failure = false; + + for (std::size_t i = 0; i < expression_list.size(); ++i) + { + if (T(1) != expression_list[i].value()) + { + printf("run_test16() - Error in evaluation! (1) Expression: %s\n", + expr_str_list[i].c_str()); + failure = true; + } + } + + return !failure; +} + +template +inline bool run_test17() +{ + typedef exprtk::expression expression_t; + + T x = T(1.1); + T y = T(2.2); + T z = T(3.3); + T w = T(4.4); + T u = T(5.5); + T v = T(6.6); + T t = T(7.7); + + T one = T(1.0); + T zero = T(0.0); + + exprtk::symbol_table 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); + symbol_table.add_variable("t",t); + + symbol_table.add_variable("one",one); + 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))" + }; + static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); + + std::deque expression_list; + + for (std::size_t i = 0; i < expr_str_list_size; ++i) + { + expression_t expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + + if (!parser.compile(expr_str_list[i],expression)) + { + printf("run_test17() - Error: %s Expression: %s\n", + parser.error().c_str(), + expr_str_list[i].c_str()); + return false; + } + else + expression_list.push_back(expression); + } + + bool failure = false; + + for (std::size_t i = 0; i < expression_list.size(); ++i) + { + if (T(1) != expression_list[i].value()) + { + printf("run_test17() - Error in evaluation! (1) Expression: %s\n", + expr_str_list[i].c_str()); + failure = true; + } + } + + return !failure; +} + +template +struct va_func : public exprtk::ivararg_function +{ + inline T operator()(const std::vector& arglist) + { + T result = T(0); + for (std::size_t i = 0; i < arglist.size(); ++i) + { + result += arglist[i]; + } + return result; + } +}; + +template +inline bool run_test18() +{ + typedef exprtk::expression expression_t; + + T x = T(1.1); + T y = T(2.2); + T z = T(3.3); + T w = T(4.4); + T u = T(5.5); + T v = T(6.6); + T t = T(7.7); + + va_func vaf; + + exprtk::symbol_table 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); + symbol_table.add_variable("t",t); + symbol_table.add_vararg_function("va_func",vaf); + + static const std::string expr_str_list[] = + { + "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))" + }; + static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); + + std::deque expression_list; + + for (std::size_t i = 0; i < expr_str_list_size; ++i) + { + expression_t expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + + if (!parser.compile(expr_str_list[i],expression)) + { + printf("run_test18() - Error: %s Expression: %s\n", + parser.error().c_str(), + expr_str_list[i].c_str()); + return false; + } + else + expression_list.push_back(expression); + } + + bool failure = false; + + for (std::size_t i = 0; i < expression_list.size(); ++i) + { + if (T(1) != expression_list[i].value()) + { + printf("run_test18() - Error in evaluation! (1) Expression: %s\n", + expr_str_list[i].c_str()); + failure = true; + } + } + + return !failure; +} + int main() { #define perform_test(Type,Number) \ @@ -2885,6 +3306,9 @@ int main() perform_test(double,13) perform_test(double,14) perform_test(double,15) + perform_test(double,16) + perform_test(double,17) + perform_test(double,18) #undef perform_test diff --git a/readme.txt b/readme.txt index ef2c362..63ed0b6 100644 --- a/readme.txt +++ b/readme.txt @@ -160,6 +160,14 @@ Expression Library can be found at: | and | Logical AND, True only if x and y are both true. | | | (eg: x and y) | +-----------+--------------------------------------------------------+ +| mand | Multi-input logical AND, True only if all inputs are | +| | true. Left to right short-circuiting of expressions. | +| | (eg: mand(x > y,z < w,u or v,w and x)) | ++-----------|--------------------------------------------------------+ +| mor | Multi-input logical OR, True if at least one of the | +| | inputs are true. Left to right short-circuiting of | +| | expressions. (eg: mand(x > y,z < w,u or v,w and x)) | ++-----------+--------------------------------------------------------+ | nand | Logical NAND, True only if either x or y is false. | | | (eg: x nand y) | +-----------+--------------------------------------------------------+ @@ -179,6 +187,12 @@ Expression Library can be found at: +-----------+--------------------------------------------------------+ | if | If x is true then return y else return z. | | | (eg: if(x, y, z) or if((x + 1) > 2y, z + 1, w / v)) | ++-----------|--------------------------------------------------------+ +| & | Similar to AND but with left to right expression short | +| | circuiting optimisation. (eg: (x & y) == (y and x)) | ++-----------|--------------------------------------------------------+ +| | | Similar to OR but with left to right expression short | +| | circuiting optimisation. (eg: (x | y) == (y or x)) | +-----------+--------------------------------------------------------+ (3) General Purpose Functions @@ -188,7 +202,7 @@ Expression Library can be found at: | abs | Absolute value of x. | +-----------+--------------------------------------------------------+ | avg | Average of all the inputs. | -| | (eg: avg(x,y,z,w) == (x+y+z+w)/4) | +| | (eg: avg(x,y,z,w,u,v) == (x+y+z+w+u+v)/6) | +-----------+--------------------------------------------------------+ | ceil | Smallest integer that is greater than or equal to x. | +-----------+--------------------------------------------------------+ @@ -219,9 +233,12 @@ Expression Library can be found at: | logn | Base N logarithm of x (eg: logn(1235,8)) | | | where n > 0 and is an integer. | +-----------+--------------------------------------------------------+ -| max | Largest value of all the inputs. (eg: max(x,y,z,w)) | +| max | Largest value of all the inputs. (eg: max(x,y,z,w,u,v))| +-----------+--------------------------------------------------------+ -| min | Smallest value of all the inputs. (eg: min(x,y,z,w)) | +| min | Smallest value of all the inputs. (eg: min(x,y,z,w,u)) | ++-----------+--------------------------------------------------------+ +| mul | Product of all the inputs. | +| | (eg: mul(x,y,z,w,u,v,t) == (x*y*z*w*u*v*t)) | +-----------+--------------------------------------------------------+ | nequal | Not-equal test between x and y using normalized epsilon| +-----------+--------------------------------------------------------+ @@ -238,7 +255,7 @@ Expression Library can be found at: | sqrt | Square root of x, where x > 0 | +-----------+--------------------------------------------------------+ | sum | Sum of all the inputs. | -| | (eg: sum(x,y,z,w,v) == (x+y+z+w+v)) | +| | (eg: sum(x,y,z,w,u,v,t) == (x+y+z+w+u+v+t)) | +-----------+--------------------------------------------------------+ | trunc | Integer portion of x | +-----------+--------------------------------------------------------+ @@ -405,7 +422,9 @@ correctly optimize such expressions for a given architecture. be enclosed with single-quotes. eg: 'Frankly, my dear, I don't give a damn!' - (10) User defined functions can have up to 20 parameters. + (10) User defined normal functions can have up to 20 parameters. + Where as user defined vararg-functions can have unlimited an + number of parameters. (11) The inbuilt polynomial functions can be at most of degree 12.