From 9d798d71e5b03c6d44520c8ec921b3b1cfe9fc39 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Mon, 25 Mar 2013 04:54:44 +1100 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 151 ++++++++++++++++++++++++++++++++++++----------------- readme.txt | 116 +++++++++++++++++++++------------------- 2 files changed, 166 insertions(+), 101 deletions(-) diff --git a/exprtk.hpp b/exprtk.hpp index e3012c9..142b5bd 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -72,7 +72,8 @@ namespace exprtk ('[' == c) || (']' == c) || ('{' == c) || ('}' == c) || ('%' == c) || (':' == c) || - ('?' == c); + ('?' == c) || ('&' == c) || + ('|' == c); } inline bool is_letter(const char c) @@ -225,7 +226,7 @@ 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" + "null", "or", "shl", "shr", "true", "while", "xnor", "xor", "&", "|" }; static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); @@ -238,7 +239,7 @@ namespace exprtk "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" + "sum", "tan", "tanh", "true", "trunc", "while", "xnor", "xor", "&", "|" }; static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); @@ -720,7 +721,7 @@ namespace exprtk template inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } template inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); } template inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); } - template inline T notl_impl(const T v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); } + template inline T notl_impl(const T v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); } template inline T frac_impl(const T v, real_type_tag) { return (v - static_cast(v)); } template inline T trunc_impl(const T v, real_type_tag) { return T(static_cast(v)); } @@ -1545,7 +1546,7 @@ namespace exprtk return eof_token_; } - inline token_t& operator[](const std::size_t index) + inline token_t& operator[](const std::size_t& index) { if (index < token_list_.size()) return token_list_[index]; @@ -1553,7 +1554,7 @@ namespace exprtk return eof_token_; } - inline token_t operator[](const std::size_t index) const + inline token_t operator[](const std::size_t& index) const { if (index < token_list_.size()) return token_list_[index]; @@ -1571,9 +1572,25 @@ namespace exprtk } } + inline void skip_comments() + { + #ifndef exprtk_disable_comments + if ((s_end_ == s_itr_) || (s_end_ == (s_itr_ + 1))) + return; + else if (('/' != *s_itr_) || ('/' != *(s_itr_ + 1))) + return; + while ((s_end_ != s_itr_) && ('\n' != *s_itr_)) + { + ++s_itr_; + } + skip_whitespace(); + #endif + } + inline void scan_token() { skip_whitespace(); + skip_comments(); if (s_end_ == s_itr_) { return; @@ -1608,7 +1625,7 @@ namespace exprtk else { token_t t; - t.set_error(token::e_error,s_itr_,s_itr_ + 2); + t.set_error(token::e_error,s_itr_,s_itr_ + 2,base_itr_); token_list_.push_back(t); ++s_itr_; } @@ -1644,6 +1661,10 @@ namespace exprtk t.set_operator(token_t::e_lt,s_itr_,s_itr_ + 1,base_itr_); else if ('>' == *s_itr_) t.set_operator(token_t::e_gt,s_itr_,s_itr_ + 1,base_itr_); + else if ('&' == *s_itr_) + t.set_symbol(s_itr_,s_itr_ + 1,base_itr_); + else if ('|' == *s_itr_) + t.set_symbol(s_itr_,s_itr_ + 1,base_itr_); else t.set_operator(token_t::token_type(*s_itr_),s_itr_,s_itr_ + 1,base_itr_); token_list_.push_back(t); @@ -4418,10 +4439,10 @@ namespace exprtk inline T value() const { - if (0 == function_) - return std::numeric_limits::quiet_NaN(); - else + if (function_) return (*function_)(); + else + return std::numeric_limits::quiet_NaN(); } inline typename expression_node::node_type type() const @@ -7320,11 +7341,20 @@ namespace exprtk inline void clear() { + struct deleter + { + static inline void process(std::pair& n) { delete n.second; } + static inline void process(std::pair&) { } + #ifndef exprtk_disable_string_capabilities + static inline void process(std::pair& n) { delete n.second; } + #endif + }; + for (std::size_t i = 0; i < lut_size; ++i) { if (short_type_lut[i].second) { - delete (short_type_lut[i]).second; + deleter::process(short_type_lut[i]); short_type_lut[i].first = false; short_type_lut[i].second = reinterpret_cast(0); } @@ -7336,14 +7366,6 @@ namespace exprtk tm_itr_t end = map.end(); while (end != itr) { - struct deleter - { - static inline void process(std::pair& n) { delete n.second; } - static inline void process(std::pair&) { } - #ifndef exprtk_disable_string_capabilities - static inline void process(std::pair& n) { delete n.second; } - #endif - }; deleter::process((*itr).second); ++itr; @@ -8739,8 +8761,13 @@ namespace exprtk static const std::string s_in = "in"; static const std::string s_like = "like"; static const std::string s_ilike = "ilike"; + static const std::string s_and1 = "&"; + static const std::string s_or1 = "|"; - if (details::imatch(current_token_.value,s_and)) + if ( + details::imatch(current_token_.value,s_and ) || + details::imatch(current_token_.value,s_and1) + ) { current_state.set(e_level01,e_level02,details::e_and); break; @@ -8750,7 +8777,10 @@ namespace exprtk current_state.set(e_level01,e_level02,details::e_nand); break; } - else if (details::imatch(current_token_.value,s_or)) + else if ( + details::imatch(current_token_.value,s_or ) || + details::imatch(current_token_.value,s_or1) + ) { current_state.set(e_level03,e_level04,details::e_or); break; @@ -8952,6 +8982,22 @@ namespace exprtk return result; } + inline expression_node_ptr parse_function_call_0(ifunction* function, const std::string& function_name) + { + expression_node_ptr result = expression_generator_.function(function); + next_token(); + if (token_is(token_t::e_lbracket) && (!token_is(token_t::e_rbracket))) + { + set_error( + make_error(parser_error::e_syntax, + current_token_, + "ERR10 - Expecting '()' to proceed: '" + function_name + "'")); + return error_node(); + } + else + return result; + } + inline expression_node_ptr parse_base_operation() { typedef std::pair map_range_t; @@ -8962,7 +9008,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR10 - No entries found for base operation: " + operation_name)); + "ERR11 - No entries found for base operation: " + operation_name)); return error_node(); } @@ -8985,7 +9031,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR11 - Impossible argument count for base function: " + operation_name)); + "ERR12 - Impossible argument count for base function: " + operation_name)); return error_node(); } @@ -9006,7 +9052,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR12 - Invalid parameter count for function: " + operation_name)); + "ERR13 - Invalid parameter count for function: " + operation_name)); return error_node(); } @@ -9026,7 +9072,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR13 - Failed to parse condition for if-statement")); + "ERR14 - Failed to parse condition for if-statement")); return error_node(); } else if (!token_is(token_t::e_comma)) @@ -9036,7 +9082,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR14 - Failed to parse consequent for if-statement")); + "ERR15 - Failed to parse consequent for if-statement")); return error_node(); } else if (!token_is(token_t::e_comma)) @@ -9046,7 +9092,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR15 - Failed to parse alternative for if-statement")); + "ERR16 - Failed to parse alternative for if-statement")); return error_node(); } else if (!token_is(token_t::e_rbracket)) @@ -9068,7 +9114,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR16 - Failed to parse condition for while-loop")); + "ERR17 - Failed to parse condition for while-loop")); return error_node(); } else if (!token_is(token_t::e_rbracket)) @@ -9080,7 +9126,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR17 - Failed to parse branch for while-loop")); + "ERR18 - Failed to parse branch for while-loop")); return error_node(); } else if (!token_is(token_t::e_rcrlbracket)) @@ -9092,7 +9138,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR18 - Failed to parse branch for while-loop")); + "ERR19 - Failed to parse branch for while-loop")); return error_node(); } else @@ -9149,7 +9195,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token_, - "ERR19 - Invalid special function[1]: " + current_token_.value)); + "ERR20 - Invalid special function[1]: " + current_token_.value)); return error_node(); } @@ -9160,7 +9206,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token_, - "ERR20 - Invalid special function[2]: " + current_token_.value)); + "ERR21 - Invalid special function[2]: " + current_token_.value)); return error_node(); } @@ -9227,7 +9273,7 @@ namespace exprtk expression_node_ptr func_node = reinterpret_cast(0); switch (function->param_count) { - case 0 : func_node = expression_generator_.function(function); break; + case 0 : func_node = parse_function_call_0 (function,symbol); break; case 1 : func_node = parse_function_call< 1>(function,symbol); break; case 2 : func_node = parse_function_call< 2>(function,symbol); break; case 3 : func_node = parse_function_call< 3>(function,symbol); break; @@ -9252,7 +9298,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR21 - Invalid number of parameters for function: " + symbol)); + "ERR22 - Invalid number of parameters for function: " + symbol)); return error_node(); } } @@ -9264,7 +9310,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR22 - Failed to generate node for function: '" + symbol + "'")); + "ERR23 - Failed to generate node for function: '" + symbol + "'")); return error_node(); } } @@ -9273,7 +9319,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR23 - Undefined variable or function: '" + symbol + "'")); + "ERR24 - Undefined variable or function: '" + symbol + "'")); return error_node(); } } @@ -9313,7 +9359,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token_, - "ERR24 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value)); + "ERR25 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value)); return error_node(); } } @@ -9388,7 +9434,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR25 - Premature end of expression.[1]")); + "ERR26 - Premature end of expression.[1]")); return error_node(); } else @@ -9396,7 +9442,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token_, - "ERR26 - Premature end of expression.[2]")); + "ERR27 - Premature end of expression.[2]")); return error_node(); } } @@ -9703,22 +9749,31 @@ namespace exprtk inline std::string branch_to_id(expression_node_ptr branch) { + static const std::string null_str ("(null)"); + static const std::string const_str("(c)" ); + static const std::string var_str ("(v)" ); + static const std::string vov_str ("(vov)" ); + static const std::string cov_str ("(cov)" ); + static const std::string voc_str ("(voc)" ); + static const std::string str_str ("(s)" ); + static const std::string cs_str ("(cs)" ); + if (details::is_null_node(branch)) - return "(null)"; + return null_str; else if (details::is_constant_node(branch)) - return "(c)"; + return const_str; else if (details::is_variable_node(branch)) - return "(v)"; + return var_str; else if (details::is_vov_node(branch)) - return "(vov)"; + return vov_str; else if (details::is_cov_node(branch)) - return "(cov)"; + return cov_str; else if (details::is_voc_node(branch)) - return "(voc)"; + return voc_str; else if (details::is_string_node(branch)) - return "(s)"; + return str_str; else if (details::is_const_string_node(branch)) - return "(cs)"; + return cs_str; else if (details::is_t0ot1ot2_node(branch)) return "(" + dynamic_cast*>(branch)->type_id() + ")"; else if (details::is_t0ot1ot2ot3_node(branch)) @@ -14486,7 +14541,7 @@ namespace exprtk { static const char* library = "Mathematical Expression Toolkit"; static const char* version = "2.7182818284590452353602874713"; - static const char* date = "20130126"; + static const char* date = "20130330"; static inline std::string data() { diff --git a/readme.txt b/readme.txt index a88473c..992edda 100644 --- a/readme.txt +++ b/readme.txt @@ -318,58 +318,58 @@ correctly optimize such expressions for a given architecture. +-------------+-------------+ +--------------+------------------+ | Prototype | Operation | | Prototype | Operation | +-------------+-------------+ +--------------+------------------+ - $f00(x,y,z) | (x + y) / z $f46(x,y,z,w) | x + ((y + z) / w) - $f01(x,y,z) | (x + y) * z $f47(x,y,z,w) | x + ((y + z) * w) - $f02(x,y,z) | (x + y) - z $f48(x,y,z,w) | x + ((y - z) / w) - $f03(x,y,z) | (x + y) + z $f49(x,y,z,w) | x + ((y - z) * w) - $f04(x,y,z) | (x - y) / z $f50(x,y,z,w) | x + ((y * z) / w) - $f05(x,y,z) | (x - y) * z $f51(x,y,z,w) | x + ((y * z) * w) - $f06(x,y,z) | (x * y) + z $f52(x,y,z,w) | x + ((y / z) + w) - $f07(x,y,z) | (x * y) - z $f53(x,y,z,w) | x + ((y / z) / w) - $f08(x,y,z) | (x * y) / z $f54(x,y,z,w) | x + ((y / z) * w) - $f09(x,y,z) | (x * y) * z $f55(x,y,z,w) | x - ((y + z) / w) - $f10(x,y,z) | (x / y) + z $f56(x,y,z,w) | x - ((y + z) * w) - $f11(x,y,z) | (x / y) - z $f57(x,y,z,w) | x - ((y - z) / w) - $f12(x,y,z) | (x / y) / z $f58(x,y,z,w) | x - ((y - z) * w) - $f13(x,y,z) | (x / y) * z $f59(x,y,z,w) | x - ((y * z) / w) - $f14(x,y,z) | x / (y + z) $f60(x,y,z,w) | x - ((y * z) * w) - $f15(x,y,z) | x / (y - z) $f61(x,y,z,w) | x - ((y / z) / w) - $f16(x,y,z) | x / (y * z) $f62(x,y,z,w) | x - ((y / z) * w) - $f17(x,y,z) | x / (y / z) $f63(x,y,z,w) | ((x + y) * z) - w - $f18(x,y,z) | x * (y + z) $f64(x,y,z,w) | ((x - y) * z) - w - $f19(x,y,z) | x * (y - z) $f65(x,y,z,w) | ((x * y) * z) - w - $f20(x,y,z) | x * (y * z) $f66(x,y,z,w) | ((x / y) * z) - w - $f21(x,y,z) | x * (y / z) $f67(x,y,z,w) | ((x + y) / z) - w - $f22(x,y,z) | x - (y / z) $f68(x,y,z,w) | ((x - y) / z) - w - $f23(x,y,z) | x - (y / z) $f69(x,y,z,w) | ((x * y) / z) - w - $f24(x,y,z) | x - (y * z) $f70(x,y,z,w) | ((x / y) / z) - w - $f25(x,y,z) | x + (y * z) $f71(x,y,z,w) | (x * y) + (z * w) - $f26(x,y,z) | x + (y / z) $f72(x,y,z,w) | (x * y) - (z * w) - $f27(x,y,z) | x + (y + z) $f73(x,y,z,w) | (x * y) + (z / w) - $f28(x,y,z) | x + (y - z) $f74(x,y,z,w) | (x * y) - (z / w) - $f29(x,y,z) | x * y^2 + z $f75(x,y,z,w) | (x / y) + (z / w) - $f30(x,y,z) | x * y^3 + z $f76(x,y,z,w) | (x / y) - (z / w) - $f31(x,y,z) | x * y^4 + z $f77(x,y,z,w) | (x / y) - (z * w) - $f32(x,y,z) | x * y^5 + z $f78(x,y,z,w) | x / (y + (z * w)) - $f33(x,y,z) | x * y^6 + z $f79(x,y,z,w) | x / (y - (z * w)) - $f34(x,y,z) | x * y^7 + z $f80(x,y,z,w) | x * (y + (z * w)) - $f35(x,y,z) | x * y^8 + z $f81(x,y,z,w) | x * (y - (z * w)) - $f36(x,y,z) | x * y^9 + z $f82(x,y,z,w) | x * y^2 + z * w^2 - $f37(x,y,z) | x * log(y)+z $f83(x,y,z,w) | x * y^3 + z * w^3 - $f38(x,y,z) | x * log(y)-z $f84(x,y,z,w) | x * y^4 + z * w^4 - $f39(x,y,z) | x * log10(y)+z $f85(x,y,z,w) | x * y^5 + z * w^5 - $f40(x,y,z) | x * log10(y)-z $f86(x,y,z,w) | x * y^6 + z * w^6 - $f41(x,y,z) | x * sin(y)+z $f87(x,y,z,w) | x * y^7 + z * w^7 - $f42(x,y,z) | x * sin(y)-z $f88(x,y,z,w) | x * y^8 + z * w^8 - $f43(x,y,z) | x * cos(y)+z $f89(x,y,z,w) | x * y^9 + z * w^9 - $f44(x,y,z) | x * cos(y)-z $f90(x,y,z,w) | (x and y) ? z : w - $f45(x,y,z) | x ? y : z $f91(x,y,z,w) | (x or y) ? z : w - $f92(x,y,z,w) | (x < y) ? z : w - $f93(x,y,z,w) | (x <= y) ? z : w - $f94(x,y,z,w) | (x > y) ? z : w - $f95(x,y,z,w) | (x >= y) ? z : w - $f96(x,y,z,w) | (x == y) ? z : w - $f97(x,y,z,w) | x*sin(y) + z*cos(w) + $f00(x,y,z) | (x + y) / z $f47(x,y,z,w) | x + ((y + z) / w) + $f01(x,y,z) | (x + y) * z $f48(x,y,z,w) | x + ((y + z) * w) + $f02(x,y,z) | (x + y) - z $f49(x,y,z,w) | x + ((y - z) / w) + $f03(x,y,z) | (x + y) + z $f50(x,y,z,w) | x + ((y - z) * w) + $f04(x,y,z) | (x - y) / z $f51(x,y,z,w) | x + ((y * z) / w) + $f05(x,y,z) | (x - y) * z $f52(x,y,z,w) | x + ((y * z) * w) + $f06(x,y,z) | (x * y) + z $f53(x,y,z,w) | x + ((y / z) + w) + $f07(x,y,z) | (x * y) - z $f54(x,y,z,w) | x + ((y / z) / w) + $f08(x,y,z) | (x * y) / z $f55(x,y,z,w) | x + ((y / z) * w) + $f09(x,y,z) | (x * y) * z $f56(x,y,z,w) | x - ((y + z) / w) + $f10(x,y,z) | (x / y) + z $f57(x,y,z,w) | x - ((y + z) * w) + $f11(x,y,z) | (x / y) - z $f58(x,y,z,w) | x - ((y - z) / w) + $f12(x,y,z) | (x / y) / z $f59(x,y,z,w) | x - ((y - z) * w) + $f13(x,y,z) | (x / y) * z $f60(x,y,z,w) | x - ((y * z) / w) + $f14(x,y,z) | x / (y + z) $f61(x,y,z,w) | x - ((y * z) * w) + $f15(x,y,z) | x / (y - z) $f62(x,y,z,w) | x - ((y / z) / w) + $f16(x,y,z) | x / (y * z) $f63(x,y,z,w) | x - ((y / z) * w) + $f17(x,y,z) | x / (y / z) $f64(x,y,z,w) | ((x + y) * z) - w + $f18(x,y,z) | x * (y + z) $f65(x,y,z,w) | ((x - y) * z) - w + $f19(x,y,z) | x * (y - z) $f66(x,y,z,w) | ((x * y) * z) - w + $f20(x,y,z) | x * (y * z) $f67(x,y,z,w) | ((x / y) * z) - w + $f21(x,y,z) | x * (y / z) $f68(x,y,z,w) | ((x + y) / z) - w + $f22(x,y,z) | x - (y + z) $f69(x,y,z,w) | ((x - y) / z) - w + $f23(x,y,z) | x - (y - z) $f70(x,y,z,w) | ((x * y) / z) - w + $f24(x,y,z) | x - (y / z) $f71(x,y,z,w) | ((x / y) / z) - w + $f25(x,y,z) | x - (y * z) $f72(x,y,z,w) | (x * y) + (z * w) + $f26(x,y,z) | x + (y * z) $f73(x,y,z,w) | (x * y) - (z * w) + $f27(x,y,z) | x + (y / z) $f74(x,y,z,w) | (x * y) + (z / w) + $f28(x,y,z) | x + (y + z) $f75(x,y,z,w) | (x * y) - (z / w) + $f29(x,y,z) | x + (y - z) $f76(x,y,z,w) | (x / y) + (z / w) + $f30(x,y,z) | x * y^2 + z $f77(x,y,z,w) | (x / y) - (z / w) + $f31(x,y,z) | x * y^3 + z $f78(x,y,z,w) | (x / y) - (z * w) + $f32(x,y,z) | x * y^4 + z $f79(x,y,z,w) | x / (y + (z * w)) + $f33(x,y,z) | x * y^5 + z $f80(x,y,z,w) | x / (y - (z * w)) + $f34(x,y,z) | x * y^6 + z $f81(x,y,z,w) | x * (y + (z * w)) + $f35(x,y,z) | x * y^7 + z $f82(x,y,z,w) | x * (y - (z * w)) + $f36(x,y,z) | x * y^8 + z $f83(x,y,z,w) | x*y^2 + z*w^2 + $f37(x,y,z) | x * y^9 + z $f84(x,y,z,w) | x*y^3 + z*w^3 + $f38(x,y,z) | x * log(y)+z $f85(x,y,z,w) | x*y^4 + z*w^4 + $f39(x,y,z) | x * log(y)-z $f86(x,y,z,w) | x*y^5 + z*w^5 + $f40(x,y,z) | x * log10(y)+z $f87(x,y,z,w) | x*y^6 + z*w^6 + $f41(x,y,z) | x * log10(y)-z $f88(x,y,z,w) | x*y^7 + z*w^7 + $f42(x,y,z) | x * sin(y)+z $f89(x,y,z,w) | x*y^8 + z*w^8 + $f43(x,y,z) | x * sin(y)-z $f90(x,y,z,w) | x*y^9 + z*w^9 + $f44(x,y,z) | x * cos(y)+z $f91(x,y,z,w) | (x and y) ? z + $f45(x,y,z) | x * cos(y)-z $f92(x,y,z,w) | (x or y) ? z : w + $f46(x,y,z) | x ? y : z $f93(x,y,z,w) | (x < y) ? z : w + $f94(x,y,z,w) | (x <= y) ? z : w + $f95(x,y,z,w) | (x > y) ? z : w + $f96(x,y,z,w) | (x >= y) ? z : w + $f97(x,y,z,w) | (x == y) ? z : w + $f98(x,y,z,w) | x * sin(y) + z * cos(w) @@ -406,11 +406,21 @@ correctly optimize such expressions for a given architecture. (10) User defined functions can have up to 20 parameters. - (11) Polynomial functions can be at most of degree 10. + (11) The inbuilt polynomial functions can be at most of degree 10. (12) Where appropriate constant folding optimisations will be applied. (eg: The expression '2+(3-(x/y))' becomes '5-(x/y)') + (13) String processing capabilities are available by default. + To turn them off, the following needs to be defined at + compile time: exprtk_disable_string_capabilities + + (14) Expressions may contain trailing comments that must be prefixed + with '//' and are terminated by the next occurrence of new-line + or line-break. To disallow comments, the following needs to be + defined at compile time: exprtk_disable_comments + (eg: '2+(3-(x/y)) // This is an expression') + [SIMPLE EXPRTK EXAMPLE]