C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html

This commit is contained in:
Arash Partow 2015-12-02 19:30:27 +11:00
parent b8e8b9502b
commit 187456164e
3 changed files with 283 additions and 137 deletions

View File

@ -57,7 +57,7 @@
namespace exprtk namespace exprtk
{ {
#if exprtk_enable_debugging #ifdef exprtk_enable_debugging
#define exprtk_debug(params) printf params #define exprtk_debug(params) printf params
#else #else
#define exprtk_debug(params) (void)0 #define exprtk_debug(params) (void)0
@ -678,16 +678,16 @@ namespace exprtk
{ {
namespace constant namespace constant
{ {
static const double e = 2.718281828459045235360; static const double e = 2.71828182845904523536028747135266249775724709369996;
static const double pi = 3.141592653589793238462; static const double pi = 3.14159265358979323846264338327950288419716939937510;
static const double pi_2 = 1.570796326794896619231; static const double pi_2 = 1.57079632679489661923132169163975144209858469968755;
static const double pi_4 = 0.785398163397448309616; static const double pi_4 = 0.78539816339744830961566084581987572104929234984378;
static const double pi_180 = 0.017453292519943295769; static const double pi_180 = 0.01745329251994329576923690768488612713442871888542;
static const double _1_pi = 0.318309886183790671538; static const double _1_pi = 0.31830988618379067153776752674502872406891929148091;
static const double _2_pi = 0.636619772367581343076; static const double _2_pi = 0.63661977236758134307553505349005744813783858296183;
static const double _180_pi = 57.295779513082320876798; static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
static const double log2 = 0.693147180559945309417; static const double log2 = 0.69314718055994530941723212145817656807550013436026;
static const double sqrt2 = 1.414213562373095048801; static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695;
} }
namespace details namespace details
@ -1760,7 +1760,7 @@ namespace exprtk
if (curr != itr) if (curr != itr)
{ {
instate = true; instate = true;
d += compute_pow10(tmp_d,-std::distance(curr,itr)); d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
} }
#undef parse_digit_1 #undef parse_digit_1
@ -6733,9 +6733,9 @@ namespace exprtk
std::string stringvar_node<T>::null_value = std::string(""); std::string stringvar_node<T>::null_value = std::string("");
template <typename T> template <typename T>
class string_range_node : public expression_node <T>, class string_range_node : public expression_node <T>,
public string_base_node<T>, public string_base_node<T>,
public range_interface <T> public range_interface <T>
{ {
public: public:
@ -11600,7 +11600,7 @@ namespace exprtk
public: public:
virtual ~boc_base_node() virtual ~boc_base_node()
{} {}
inline virtual operator_type operation() const inline virtual operator_type operation() const
{ {
@ -13554,6 +13554,43 @@ namespace exprtk
const T& v_; const T& v_;
}; };
template <typename T, typename PowOp>
class bipow_node : public expression_node<T>
{
public:
typedef expression_node<T>* expression_ptr;
typedef std::pair<expression_ptr, bool> branch_t;
typedef PowOp operation_t;
explicit bipow_node(expression_ptr brnch)
{
init_branches<1>(branch_, brnch);
}
~bipow_node()
{
cleanup_branches::execute<T,1>(branch_);
}
inline T value() const
{
return PowOp::result(branch_[0].first->value());
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_ipow;
}
private:
bipow_node(const bipow_node<T,PowOp>&);
bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
branch_t branch_[1];
};
template <typename T, typename PowOp> template <typename T, typename PowOp>
class ipowinv_node : public expression_node<T> class ipowinv_node : public expression_node<T>
{ {
@ -13584,6 +13621,43 @@ namespace exprtk
const T& v_; const T& v_;
}; };
template <typename T, typename PowOp>
class bipowninv_node : public expression_node<T>
{
public:
typedef expression_node<T>* expression_ptr;
typedef std::pair<expression_ptr, bool> branch_t;
typedef PowOp operation_t;
explicit bipowninv_node(expression_ptr brnch)
{
init_branches<1>(branch_, brnch);
}
~bipowninv_node()
{
cleanup_branches::execute<T,1>(branch_);
}
inline T value() const
{
return (T(1) / PowOp::result(branch_[0].first->value()));
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_ipowinv;
}
private:
bipowninv_node(const bipowninv_node<T,PowOp>&);
bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
branch_t branch_[1];
};
template <typename T> template <typename T>
inline bool is_vov_node(const expression_node<T>* node) inline bool is_vov_node(const expression_node<T>* node)
{ {
@ -17139,7 +17213,7 @@ namespace exprtk
{ {
st = e_usr_variable_type; st = e_usr_variable_type;
default_value = T(0); default_value = T(0);
error_message = ""; error_message.clear();
return true; return true;
} }
@ -17698,7 +17772,7 @@ namespace exprtk
settings_store& disable_inequality_operation(settings_inequality_opr inequality) settings_store& disable_inequality_operation(settings_inequality_opr inequality)
{ {
if ( if (
(e_assign_unknown != inequality) && (e_ineq_unknown != inequality) &&
(static_cast<std::size_t>(inequality) < details::inequality_ops_list_size) (static_cast<std::size_t>(inequality) < details::inequality_ops_list_size)
) )
{ {
@ -20039,7 +20113,7 @@ namespace exprtk
return error_node(); return error_node();
} }
// Can we optimize away the case statement? // Can we optimise away the case statement?
if (is_constant_node(condition) && is_false(condition)) if (is_constant_node(condition) && is_false(condition))
{ {
free_node(node_allocator_, condition); free_node(node_allocator_, condition);
@ -20183,7 +20257,7 @@ namespace exprtk
return error_node(); return error_node();
} }
// Can we optimize away the case statement? // Can we optimise away the case statement?
if (is_constant_node(condition) && is_false(condition)) if (is_constant_node(condition) && is_false(condition))
{ {
free_node(node_allocator_, condition); free_node(node_allocator_, condition);
@ -23259,7 +23333,7 @@ namespace exprtk
} }
#endif #endif
inline bool unary_optimizable(const details::operator_type& operation) const inline bool unary_optimisable(const details::operator_type& operation) const
{ {
return (details::e_abs == operation) || (details::e_acos == operation) || return (details::e_abs == operation) || (details::e_acos == operation) ||
(details::e_acosh == operation) || (details::e_asin == operation) || (details::e_acosh == operation) || (details::e_asin == operation) ||
@ -23283,7 +23357,7 @@ namespace exprtk
(details::e_frac == operation) || (details::e_trunc == operation); (details::e_frac == operation) || (details::e_trunc == operation);
} }
inline bool sf3_optimizable(const std::string& sf3id, trinary_functor_t& tfunc) inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc)
{ {
typename sf3_map_t::iterator itr = sf3_map_->find(sf3id); typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
@ -23295,7 +23369,7 @@ namespace exprtk
return true; return true;
} }
inline bool sf4_optimizable(const std::string& sf4id, quaternary_functor_t& qfunc) inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc)
{ {
typename sf4_map_t::iterator itr = sf4_map_->find(sf4id); typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
@ -23307,7 +23381,7 @@ namespace exprtk
return true; return true;
} }
inline bool sf3_optimizable(const std::string& sf3id, details::operator_type& operation) inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation)
{ {
typename sf3_map_t::iterator itr = sf3_map_->find(sf3id); typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
@ -23319,7 +23393,7 @@ namespace exprtk
return true; return true;
} }
inline bool sf4_optimizable(const std::string& sf4id, details::operator_type& operation) inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation)
{ {
typename sf4_map_t::iterator itr = sf4_map_->find(sf4id); typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
@ -23343,9 +23417,9 @@ namespace exprtk
return error_node(); return error_node();
else if (details::is_constant_node(branch[0])) else if (details::is_constant_node(branch[0]))
return synthesize_expression<unary_node_t,1>(operation,branch); return synthesize_expression<unary_node_t,1>(operation,branch);
else if (unary_optimizable(operation) && details::is_variable_node(branch[0])) else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
return synthesize_uv_expression(operation,branch); return synthesize_uv_expression(operation,branch);
else if (unary_optimizable(operation) && details::is_ivector_node(branch[0])) else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
return synthesize_uvec_expression(operation,branch); return synthesize_uvec_expression(operation,branch);
else else
return synthesize_unary_expression(operation,branch); return synthesize_unary_expression(operation,branch);
@ -23413,7 +23487,7 @@ namespace exprtk
} }
} }
inline bool operation_optimizable(const details::operator_type& operation) const inline bool operation_optimisable(const details::operator_type& operation) const
{ {
return (details::e_add == operation) || return (details::e_add == operation) ||
(details::e_sub == operation) || (details::e_sub == operation) ||
@ -23481,47 +23555,47 @@ namespace exprtk
return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
} }
inline bool cov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1])); return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1]));
} }
inline bool voc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1])); return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1]));
} }
inline bool vov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1])); return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
} }
inline bool cob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1])); return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1]));
} }
inline bool boc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1])); return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
} }
inline bool cocob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if ( if (
(details::e_add == operation) || (details::e_add == operation) ||
@ -23537,7 +23611,7 @@ namespace exprtk
return false; return false;
} }
inline bool coboc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if ( if (
(details::e_add == operation) || (details::e_add == operation) ||
@ -23553,33 +23627,33 @@ namespace exprtk
return false; return false;
} }
inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1])); return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1]));
} }
inline bool vob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1])); return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1]));
} }
inline bool bov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1])); return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
} }
inline bool binext_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
{ {
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
else else
return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1])); return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1]));
@ -23605,6 +23679,22 @@ namespace exprtk
return false; return false;
} }
inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2])
{
if (
!is_constant_node(branch[1]) ||
is_constant_node(branch[0]) ||
is_variable_node(branch[0]) ||
is_vector_node (branch[0]) ||
is_generally_string_node(branch[0])
)
return false;
const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
return cardinal_pow_optimisable(operation, c);
}
inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
{ {
return ( return (
@ -23750,7 +23840,11 @@ namespace exprtk
else if (is_string_operation(operation,branch)) else if (is_string_operation(operation,branch))
return synthesize_string_expression(operation,branch); return synthesize_string_expression(operation,branch);
else if (is_null_present(branch)) else if (is_null_present(branch))
return synthesize_null_expression(operation,branch); return synthesize_null_expression(operation, branch);
#ifndef exprtk_disable_cardinal_pow_optimisation
else if (is_constpow_operation(operation, branch))
return cardinal_pow_optimisation(branch);
#endif
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
@ -23770,30 +23864,30 @@ namespace exprtk
*/ */
result = error_node(); result = error_node();
if (cocob_optimizable(operation,branch)) if (cocob_optimisable(operation,branch))
result = synthesize_cocob_expression::process(*this,operation,branch); result = synthesize_cocob_expression::process(*this,operation,branch);
else if (coboc_optimizable(operation,branch) && (0 == result)) else if (coboc_optimisable(operation,branch) && (0 == result))
result = synthesize_coboc_expression::process(*this,operation,branch); result = synthesize_coboc_expression::process(*this,operation,branch);
if (result) if (result)
return result; return result;
} }
if (uvouv_optimizable(operation,branch)) if (uvouv_optimisable(operation,branch))
return synthesize_uvouv_expression(operation,branch); return synthesize_uvouv_expression(operation,branch);
else if (vob_optimizable(operation,branch)) else if (vob_optimisable(operation,branch))
return synthesize_vob_expression::process(*this,operation,branch); return synthesize_vob_expression::process(*this,operation,branch);
else if (bov_optimizable(operation,branch)) else if (bov_optimisable(operation,branch))
return synthesize_bov_expression::process(*this,operation,branch); return synthesize_bov_expression::process(*this,operation,branch);
else if (cob_optimizable(operation,branch)) else if (cob_optimisable(operation,branch))
return synthesize_cob_expression::process(*this,operation,branch); return synthesize_cob_expression::process(*this,operation,branch);
else if (boc_optimizable(operation,branch)) else if (boc_optimisable(operation,branch))
return synthesize_boc_expression::process(*this,operation,branch); return synthesize_boc_expression::process(*this,operation,branch);
#ifndef exprtk_disable_enhanced_features #ifndef exprtk_disable_enhanced_features
else if (cov_optimizable(operation,branch)) else if (cov_optimisable(operation,branch))
return synthesize_cov_expression::process(*this,operation,branch); return synthesize_cov_expression::process(*this,operation,branch);
#endif #endif
else if (binext_optimizable(operation,branch)) else if (binext_optimisable(operation,branch))
return synthesize_binary_ext_expression::process(*this,operation,branch); return synthesize_binary_ext_expression::process(*this,operation,branch);
else else
return synthesize_expression<binary_node_t,2>(operation,branch); return synthesize_expression<binary_node_t,2>(operation,branch);
@ -23853,7 +23947,7 @@ namespace exprtk
return error_node(); return error_node();
} }
// Can the condition be immediately evaluated? if so optimize. // Can the condition be immediately evaluated? if so optimise.
else if (details::is_constant_node(condition)) else if (details::is_constant_node(condition))
{ {
// True branch // True branch
@ -23899,7 +23993,7 @@ namespace exprtk
return error_node(); return error_node();
} }
// Can the condition be immediately evaluated? if so optimize. // Can the condition be immediately evaluated? if so optimise.
else if (details::is_constant_node(condition)) else if (details::is_constant_node(condition))
{ {
// True branch // True branch
@ -23930,9 +24024,9 @@ namespace exprtk
return error_node(); return error_node();
} }
#else #else
inline expression_node_ptr conditional_string(expression_node_ptr , inline expression_node_ptr conditional_string(expression_node_ptr,
expression_node_ptr , expression_node_ptr,
expression_node_ptr ) const expression_node_ptr) const
{ {
return error_node(); return error_node();
} }
@ -24055,7 +24149,7 @@ namespace exprtk
template <typename Allocator, template <typename Allocator,
template <typename,typename> class Sequence> template <typename,typename> class Sequence>
inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arg_list) inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
{ {
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
@ -24091,7 +24185,7 @@ namespace exprtk
template <typename Allocator, template <typename Allocator,
template <typename,typename> class Sequence> template <typename,typename> class Sequence>
inline expression_node_ptr const_optimize_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
{ {
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
@ -24224,7 +24318,7 @@ namespace exprtk
return error_node(); return error_node();
} }
else if (is_constant_foldable(arg_list)) else if (is_constant_foldable(arg_list))
return const_optimize_switch(arg_list); return const_optimise_switch(arg_list);
switch ((arg_list.size() - 1) / 2) switch ((arg_list.size() - 1) / 2)
{ {
@ -24258,7 +24352,7 @@ namespace exprtk
return error_node(); return error_node();
} }
else if (is_constant_foldable(arg_list)) else if (is_constant_foldable(arg_list))
return const_optimize_mswitch(arg_list); return const_optimise_mswitch(arg_list);
else else
return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
} }
@ -24353,7 +24447,7 @@ namespace exprtk
} }
} }
inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation, inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
expression_node_ptr (&branch)[3]) expression_node_ptr (&branch)[3])
{ {
expression_node_ptr temp_node = error_node(); expression_node_ptr temp_node = error_node();
@ -24401,7 +24495,7 @@ namespace exprtk
return node_allocator_->allocate<literal_node_t>(v); return node_allocator_->allocate<literal_node_t>(v);
} }
inline expression_node_ptr varnode_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
{ {
typedef details::variable_node<Type>* variable_ptr; typedef details::variable_node<Type>* variable_ptr;
@ -24450,9 +24544,9 @@ namespace exprtk
if (!all_nodes_valid(branch)) if (!all_nodes_valid(branch))
return error_node(); return error_node();
else if (is_constant_foldable(branch)) else if (is_constant_foldable(branch))
return const_optimize_sf3(operation,branch); return const_optimise_sf3(operation,branch);
else if (all_nodes_variables(branch)) else if (all_nodes_variables(branch))
return varnode_optimize_sf3(operation,branch); return varnode_optimise_sf3(operation,branch);
else else
{ {
switch (operation) switch (operation)
@ -24491,7 +24585,7 @@ namespace exprtk
} }
} }
inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
{ {
expression_node_ptr temp_node = error_node(); expression_node_ptr temp_node = error_node();
@ -24538,7 +24632,7 @@ namespace exprtk
return node_allocator_->allocate<literal_node_t>(v); return node_allocator_->allocate<literal_node_t>(v);
} }
inline expression_node_ptr varnode_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
{ {
typedef details::variable_node<Type>* variable_ptr; typedef details::variable_node<Type>* variable_ptr;
@ -24589,9 +24683,9 @@ namespace exprtk
if (!all_nodes_valid(branch)) if (!all_nodes_valid(branch))
return error_node(); return error_node();
else if (is_constant_foldable(branch)) else if (is_constant_foldable(branch))
return const_optimize_sf4(operation,branch); return const_optimise_sf4(operation,branch);
else if (all_nodes_variables(branch)) else if (all_nodes_variables(branch))
return varnode_optimize_sf4(operation,branch); return varnode_optimise_sf4(operation,branch);
switch (operation) switch (operation)
{ {
#define case_stmt(op0,op1) \ #define case_stmt(op0,op1) \
@ -24631,7 +24725,7 @@ namespace exprtk
template <typename Allocator, template <typename Allocator,
template <typename,typename> class Sequence> template <typename,typename> class Sequence>
inline expression_node_ptr const_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
{ {
expression_node_ptr temp_node = error_node(); expression_node_ptr temp_node = error_node();
@ -24674,7 +24768,7 @@ namespace exprtk
template <typename Allocator, template <typename Allocator,
template <typename,typename> class Sequence> template <typename,typename> class Sequence>
inline expression_node_ptr varnode_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
{ {
switch (operation) switch (operation)
{ {
@ -24731,13 +24825,13 @@ namespace exprtk
return error_node(); return error_node();
} }
else if (is_constant_foldable(arg_list)) else if (is_constant_foldable(arg_list))
return const_optimize_varargfunc(operation,arg_list); return const_optimise_varargfunc(operation,arg_list);
else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0])) else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
return vectorize_func(operation,arg_list); return vectorize_func(operation,arg_list);
else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation)) else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
return arg_list[0]; return arg_list[0];
else if (all_nodes_variables(arg_list)) else if (all_nodes_variables(arg_list))
return varnode_optimize_varargfunc(operation,arg_list); return varnode_optimise_varargfunc(operation,arg_list);
switch (operation) switch (operation)
{ {
@ -24768,7 +24862,7 @@ namespace exprtk
return error_node(); return error_node();
else else
{ {
// Can the function call be completely optimized? // Can the function call be completely optimised?
if (details::is_constant_node(result)) if (details::is_constant_node(result))
return result; return result;
else if (!all_nodes_valid(b)) else if (!all_nodes_valid(b))
@ -25519,8 +25613,8 @@ namespace exprtk
case_stmt(details::e_xnor,details::xnor_op) \ case_stmt(details::e_xnor,details::xnor_op) \
#ifndef exprtk_disable_cardinal_pow_optimisation #ifndef exprtk_disable_cardinal_pow_optimisation
template <template <typename,typename> class IPowNode> template <typename TType, template <typename,typename> class IPowNode>
inline expression_node_ptr cardinal_pow_optimization_impl(const T& v, const unsigned int& p) inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
{ {
switch (p) switch (p)
{ {
@ -25548,7 +25642,7 @@ namespace exprtk
} }
} }
inline expression_node_ptr cardinal_pow_optimization(const T& v, const T& c) inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
{ {
const bool not_recipricol = (c >= T(0)); const bool not_recipricol = (c >= T(0));
const int p = details::numeric::to_int32(details::numeric::abs(c)); const int p = details::numeric::to_int32(details::numeric::abs(c));
@ -25563,26 +25657,50 @@ namespace exprtk
else else
{ {
if (not_recipricol) if (not_recipricol)
return cardinal_pow_optimization_impl<details::ipow_node>(v,p); return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
else else
return cardinal_pow_optimization_impl<details::ipowinv_node>(v,p); return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
} }
} }
inline bool cardinal_pow_optimizable(const details::operator_type& operation, const T& c) inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c)
{ {
return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
} }
inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
{
const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
const bool not_recipricol = (c >= T(0));
const int p = details::numeric::to_int32(details::numeric::abs(c));
node_allocator_->free(branch[1]);
if (0 == p)
{
details::free_all_nodes(*node_allocator_, branch);
return node_allocator_->allocate_c<literal_node_t>(T(1));
}
else if (not_recipricol)
return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
else
return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
}
#else #else
inline expression_node_ptr cardinal_pow_optimization(T&, const T&) inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
{ {
return error_node(); return error_node();
} }
inline bool cardinal_pow_optimizable(const details::operator_type&, const T&) inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
{ {
return false; return false;
} }
inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
{
return error_node();
}
#endif #endif
struct synthesize_binary_ext_expression struct synthesize_binary_ext_expression
@ -26092,6 +26210,18 @@ namespace exprtk
return bocnode; return bocnode;
} }
} }
else if (operation == details::e_pow)
{
// (v ^ c0) ^ c1 --> v ^(c0 * c1)
details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
details::operator_type boc_opr = bocnode->operation();
if (details::e_pow == boc_opr)
{
bocnode->set_c(bocnode->c() * c);
return bocnode;
}
}
} }
#ifndef exprtk_disable_enhanced_features #ifndef exprtk_disable_enhanced_features
@ -26471,7 +26601,7 @@ namespace exprtk
{ {
result = error_node(); result = error_node();
if (!operation_optimizable(operation)) if (!operation_optimisable(operation))
return false; return false;
const std::string node_id = branch_to_id(branch); const std::string node_id = branch_to_id(branch);
@ -26557,12 +26687,12 @@ namespace exprtk
details::free_node(*(expr_gen.node_allocator_),branch[1]); details::free_node(*(expr_gen.node_allocator_),branch[1]);
if (expr_gen.cardinal_pow_optimizable(operation,c)) if (expr_gen.cardinal_pow_optimisable(operation,c))
{ {
if (std::equal_to<T>()(T(1),c)) if (std::equal_to<T>()(T(1),c))
return branch[0]; return branch[0];
else else
return expr_gen.cardinal_pow_optimization(v,c); return expr_gen.cardinal_pow_optimisation(v,c);
} }
else if ((T(0) == c) && (details::e_mul == operation)) else if ((T(0) == c) && (details::e_mul == operation))
return expr_gen(T(0)); return expr_gen(T(0));
@ -26631,7 +26761,7 @@ namespace exprtk
{ {
details::operator_type sf3opr; details::operator_type sf3opr;
if (!expr_gen.sf3_optimizable(id,sf3opr)) if (!expr_gen.sf3_optimisable(id,sf3opr))
return false; return false;
else else
result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2); result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2);
@ -26715,7 +26845,7 @@ namespace exprtk
{ {
details::operator_type sf4opr; details::operator_type sf4opr;
if (!expr_gen.sf4_optimizable(id,sf4opr)) if (!expr_gen.sf4_optimisable(id,sf4opr))
return false; return false;
else else
result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3); result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3);
@ -27731,6 +27861,14 @@ namespace exprtk
return expr_gen.node_allocator_-> return expr_gen.node_allocator_->
template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1); template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1);
} }
// (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
else if ((details::e_pow == o0) && (details::e_pow == o1))
{
exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
return expr_gen.node_allocator_->
template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v,c0 * c1);
}
} }
if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result)) if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result))
@ -31508,7 +31646,7 @@ namespace exprtk
} }
else if ((details::e_default != operation)) else if ((details::e_default != operation))
{ {
// Attempt simple constant folding optimization. // Attempt simple constant folding optimisation.
expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
if (is_constant_foldable<N>(branch)) if (is_constant_foldable<N>(branch))
@ -31537,7 +31675,7 @@ namespace exprtk
typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
// Attempt simple constant folding optimization. // Attempt simple constant folding optimisation.
expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);

View File

@ -2348,8 +2348,8 @@ inline bool run_test02()
if (!parser.compile(test.expr, expression)) if (!parser.compile(test.expr, expression))
{ {
printf("run_test02() - Error: %s Expression: %s\n", printf("run_test02() - Error: %s Expression: %s\n",
parser.error().c_str(), parser.error().c_str(),
test.expr.c_str()); test.expr.c_str());
result = false; result = false;
continue; continue;
@ -2365,13 +2365,13 @@ inline bool run_test02()
if (not_equal(expr_result, test.result)) if (not_equal(expr_result, test.result))
{ {
printf("run_test02() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\t" printf("run_test02() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\t"
"a='%s'\tb='%s'\tc='%s'\n", "a='%s'\tb='%s'\tc='%s'\n",
test.expr.c_str(), test.expr.c_str(),
(double)test.result, (double)test.result,
(double)expr_result, (double)expr_result,
str_a.c_str(), str_a.c_str(),
str_b.c_str(), str_b.c_str(),
str_c.c_str()); str_c.c_str());
result = false; result = false;
continue; continue;
@ -6325,11 +6325,13 @@ inline bool run_test19()
104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729,
1000621, 1000639, 1000651, 1000667, 1000669, 1001023, 1001027, 1001041 1000621, 1000639, 1000651, 1000667, 1000669, 1001023, 1001027, 1001041
}; };
const std::size_t prime_list_size = sizeof(prime_list) / sizeof(std::size_t); const std::size_t prime_list_size = sizeof(prime_list) / sizeof(std::size_t);
for (std::size_t i = 0; (i < prime_list_size) && (!failure); ++i) for (std::size_t i = 0; (i < prime_list_size) && (!failure); ++i)
{ {
x = prime_list[i]; x = static_cast<T>(prime_list[i]);
std::vector<T> result(expression_count,T(0)); std::vector<T> result(expression_count,T(0));
for (std::size_t j = 0; j < expression_list.size(); ++j) for (std::size_t j = 0; j < expression_list.size(); ++j)
@ -6467,6 +6469,7 @@ inline bool run_test19()
"x")); "x"));
symbol_table_t& symbol_table = compositor.symbol_table(); symbol_table_t& symbol_table = compositor.symbol_table();
symbol_table.add_constants(); symbol_table.add_constants();
symbol_table.add_variable("x",x); symbol_table.add_variable("x",x);
@ -6515,11 +6518,13 @@ inline bool run_test19()
46368, 75025, 121393, 196418, 46368, 75025, 121393, 196418,
317811, 514229, 832040, 1346269 317811, 514229, 832040, 1346269
}; };
const std::size_t fibonacci_list_size = sizeof(fibonacci_list) / sizeof(std::size_t); const std::size_t fibonacci_list_size = sizeof(fibonacci_list) / sizeof(std::size_t);
for (std::size_t i = 0; (i < fibonacci_list_size) && (!failure); ++i) for (std::size_t i = 0; (i < fibonacci_list_size) && (!failure); ++i)
{ {
x = i; x = static_cast<T>(i);
std::vector<T> result(expression_count,T(0)); std::vector<T> result(expression_count,T(0));
for (std::size_t j = 0; j < expression_list.size(); ++j) for (std::size_t j = 0; j < expression_list.size(); ++j)
@ -6629,7 +6634,8 @@ inline bool run_test19()
for (std::size_t i = 0; i < 100; ++i) for (std::size_t i = 0; i < 100; ++i)
{ {
x = i; x = static_cast<T>(i);
T result = expression.value(); T result = expression.value();
if (not_equal(result,std::sqrt(x),T(0.0000001))) if (not_equal(result,std::sqrt(x),T(0.0000001)))
@ -6757,7 +6763,9 @@ inline bool run_test19()
for (std::size_t i = 0; i < 100; ++i) for (std::size_t i = 0; i < 100; ++i)
{ {
x = T(i); x = T(i);
sum += x; sum += x;
T result = expression.value(); T result = expression.value();
if (result != sum) if (result != sum)
@ -6847,7 +6855,7 @@ struct my_usr : public exprtk::parser<T>::unknown_symbol_resolver
{ {
st = usr_t::e_usr_variable_type; st = usr_t::e_usr_variable_type;
default_value = next_value(); default_value = next_value();
error_message = ""; error_message.clear();
return true; return true;
} }
@ -6855,7 +6863,7 @@ struct my_usr : public exprtk::parser<T>::unknown_symbol_resolver
{ {
st = usr_t::e_usr_constant_type; st = usr_t::e_usr_constant_type;
default_value = next_value(); default_value = next_value();
error_message = ""; error_message.clear();
return true; return true;
} }

View File

@ -7,7 +7,7 @@ mathematical expression parsing and evaluation engine. The parsing
engine supports numerous forms of functional and logic processing engine supports numerous forms of functional and logic processing
semantics and is easily extendible. semantics and is easily extendible.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[01 - CAPABILITIES] [01 - CAPABILITIES]
The ExprTk expression evaluator supports the following fundamental The ExprTk expression evaluator supports the following fundamental
@ -49,7 +49,7 @@ arithmetic operations, functions and processes:
(11) Calculus: numerical integration and differentiation (11) Calculus: numerical integration and differentiation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02 - EXAMPLE EXPRESSIONS] [02 - EXAMPLE EXPRESSIONS]
The following is a short listing of the types of mathematical The following is a short listing of the types of mathematical
@ -76,7 +76,7 @@ expressions that can be parsed and evaluated using the ExprTk library.
(19) ((x + 'abc') like '*123*') or ('a123b' ilike y) (19) ((x + 'abc') like '*123*') or ('a123b' ilike y)
(20) sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x } (20) sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[03 - COPYRIGHT NOTICE] [03 - COPYRIGHT NOTICE]
Free use of the C++ Mathematical Expression Toolkit Library is Free use of the C++ Mathematical Expression Toolkit Library is
@ -85,7 +85,7 @@ version of the Common Public License.
http://www.opensource.org/licenses/cpl1.0.php http://www.opensource.org/licenses/cpl1.0.php
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[04 - DOWNLOADS & UPDATES] [04 - DOWNLOADS & UPDATES]
The most recent version of the C++ Mathematical Expression Toolkit The most recent version of the C++ Mathematical Expression Toolkit
@ -95,13 +95,13 @@ locations:
(a) Download: http://www.partow.net/programming/exprtk/index.html (a) Download: http://www.partow.net/programming/exprtk/index.html
(b) Repository: https://github.com/ArashPartow/exprtk (b) Repository: https://github.com/ArashPartow/exprtk
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[05 - INSTALLATION] [05 - INSTALLATION]
The header file exprtk.hpp should be placed in a project or system The header file exprtk.hpp should be placed in a project or system
include path (e.g: /usr/include/). include path (e.g: /usr/include/).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[06 - COMPILATION] [06 - COMPILATION]
(a) For a complete build: make clean all (a) For a complete build: make clean all
@ -109,7 +109,7 @@ include path (e.g: /usr/include/).
(c) To strip executables: make strip_bin (c) To strip executables: make strip_bin
(d) Execute valgrind check: make valgrind_check (d) Execute valgrind check: make valgrind_check
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[07 - COMPILER COMPATIBILITY] [07 - COMPILER COMPATIBILITY]
ExprTk has been built error and warning free using the following set ExprTk has been built error and warning free using the following set
@ -120,11 +120,10 @@ of C++ compilers:
(*) Clang/LLVM (1.1+) (*) Clang/LLVM (1.1+)
(*) PGI C++ (10.x+) (*) PGI C++ (10.x+)
(*) Microsoft Visual Studio C++ Compiler (8.1+) (*) Microsoft Visual Studio C++ Compiler (8.1+)
(*) Comeau C++ Compiler (4.3+)
(*) IBM XL C/C++ (9.x+) (*) IBM XL C/C++ (9.x+)
(*) C++ Builder (XE4+) (*) C++ Builder (XE4+)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[08 - BUILT-IN OPERATIONS & FUNCTIONS] [08 - BUILT-IN OPERATIONS & FUNCTIONS]
@ -604,7 +603,7 @@ appropriate may represent any of one the following:
5. A string 5. A string
6. An expression comprised of [1], [2] or [3] (eg: 2 + x / vec[3]) 6. An expression comprised of [1], [2] or [3] (eg: 2 + x / vec[3])
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[09 - Fundamental Types] [09 - Fundamental Types]
ExprTk supports three fundamental types which can be used freely in ExprTk supports three fundamental types which can be used freely in
@ -635,7 +634,7 @@ can be assigned and concatenated to one another, they can also be
manipulated via sub-ranges using the range definition syntax. Strings manipulated via sub-ranges using the range definition syntax. Strings
however can not interact with scalar or vector types. however can not interact with scalar or vector types.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[10 - COMPONENTS] [10 - COMPONENTS]
There are three primary components, that are specialized upon a given There are three primary components, that are specialized upon a given
@ -794,7 +793,7 @@ The above denoted AST will be evaluated in the following order:
(3) Parser (3) Parser
A structure which takes as input a string representation of an A component which takes as input a string representation of an
expression and attempts to compile said input with the result being an expression and attempts to compile said input with the result being an
instance of Expression. If an error is encountered during the instance of Expression. If an error is encountered during the
compilation process, the parser will stop compiling and return an compilation process, the parser will stop compiling and return an
@ -802,7 +801,7 @@ error status code, with a more detailed description of the error(s)
and its location within the input provided by the 'get_error' and its location within the input provided by the 'get_error'
interface. interface.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[11 - COMPILATION OPTIONS] [11 - COMPILATION OPTIONS]
The exprtk::parser when being instantiated takes as input a set of The exprtk::parser when being instantiated takes as input a set of
@ -937,7 +936,7 @@ desired over the strength reduced form. In these situations it is best
to turn off strength reduction optimisations or to use a type with a to turn off strength reduction optimisations or to use a type with a
larger numerical bound. larger numerical bound.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[12 - SPECIAL FUNCTIONS] [12 - SPECIAL FUNCTIONS]
The purpose of special functions in ExprTk is to provide compiler The purpose of special functions in ExprTk is to provide compiler
@ -1008,7 +1007,7 @@ correctly optimize such expressions for a given architecture.
$f98(x,y,z,w) | (x == y) ? z : w $f98(x,y,z,w) | (x == y) ? z : w
$f99(x,y,z,w) | x*sin(y)+z*cos(w) $f99(x,y,z,w) | x*sin(y)+z*cos(w)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[13 - VARIABLE , VECTOR & STRING DEFINITION] [13 - VARIABLE , VECTOR & STRING DEFINITION]
ExprTk supports the definition of expression local variables, vectors ExprTk supports the definition of expression local variables, vectors
@ -1127,7 +1126,7 @@ based on the following priorities:
(e) Symbol table functions (e) Symbol table functions
(f) Unknown symbol resolver based variables (f) Unknown symbol resolver based variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[14 - VECTOR PROCESSING] [14 - VECTOR PROCESSING]
ExprTk provides support for various forms of vector oriented ExprTk provides support for various forms of vector oriented
@ -1203,7 +1202,7 @@ not a vector but rather a single value.
min(1 / x) == (1 / 3) min(1 / x) == (1 / 3)
max(x / 2) == (3 / 2) max(x / 2) == (3 / 2)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[15 - USER DEFINED FUNCTIONS] [15 - USER DEFINED FUNCTIONS]
ExprTk provides a means whereby custom functions can be defined and ExprTk provides a means whereby custom functions can be defined and
@ -1310,6 +1309,7 @@ example defines a generic function called 'too':
{ {
... ...
} }
return T(0); return T(0);
} }
}; };
@ -1735,7 +1735,7 @@ carried out:
{ ... } { ... }
}; };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[16 - EXPRESSION DEPENDENTS] [16 - EXPRESSION DEPENDENTS]
Any expression that is not a literal (aka constant) will have Any expression that is not a literal (aka constant) will have
@ -1881,7 +1881,7 @@ of the DEC in determining the 'assignments' of the given expression:
Note: The assignments will only consist of variable types and as such Note: The assignments will only consist of variable types and as such
will not contain symbols denoting functions. will not contain symbols denoting functions.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[17 - ENABLING AND DISABLING FEATURES] [17 - ENABLING AND DISABLING FEATURES]
The parser can be configured via its settings instance to either allow The parser can be configured via its settings instance to either allow
@ -2239,7 +2239,7 @@ provided symbol names when calling the standard 'add_function' method.
Normally if a user specified symbol name conflicts with any of the Normally if a user specified symbol name conflicts with any of the
ExprTk reserved words, the add_function call will fail. ExprTk reserved words, the add_function call will fail.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[18 - EXPRESSION RETURN VALUES] [18 - EXPRESSION RETURN VALUES]
ExprTk expressions can return immediately from any point by utilizing ExprTk expressions can return immediately from any point by utilizing
@ -2291,7 +2291,7 @@ expression will return normally.
typedef typename type_t::vector_view vector_t; typedef typename type_t::vector_view vector_t;
typedef typename type_t::string_view string_t; typedef typename type_t::string_view string_t;
const results_context_t& result = expression.results(); const results_context_t& results = expression.results();
for (std::size_t i = 0; i < results.count(); ++i) for (std::size_t i = 0; i < results.count(); ++i)
{ {
@ -2313,10 +2313,10 @@ expression will return normally.
} }
Note: Processing of the return results is very similar to that of the Note: Processing of the return results is similar to that of the
generic function call parameters. generic function call parameters.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[19 - COMPILATION ERRORS] [19 - COMPILATION ERRORS]
When attempting to compile a malformed or otherwise erroneous ExprTk When attempting to compile a malformed or otherwise erroneous ExprTk
@ -2426,7 +2426,7 @@ find, within the symbol_table, symbols representing variables or
functions, to being unable to create new variables in the symbol_table functions, to being unable to create new variables in the symbol_table
via the 'unknown symbol resolver' mechanism. via the 'unknown symbol resolver' mechanism.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[20 - EXPRTK NOTES] [20 - EXPRTK NOTES]
The following is a list of facts and suggestions one may want to take The following is a list of facts and suggestions one may want to take
@ -2604,7 +2604,7 @@ into account when using ExprTk:
(x + y) / (x - y); (x + y) / (x - y);
} }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[21 - SIMPLE EXPRTK EXAMPLE] [21 - SIMPLE EXPRTK EXAMPLE]
--- snip --- --- snip ---
@ -2692,7 +2692,7 @@ int main()
} }
--- snip --- --- snip ---
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[22 - BUILD OPTIONS] [22 - BUILD OPTIONS]
When building ExprTk there are a number of defines that will enable or When building ExprTk there are a number of defines that will enable or
@ -2738,7 +2738,7 @@ This define will disable all string processing capabilities. Any
expression that contains a string or string related syntax will result expression that contains a string or string related syntax will result
in a compilation failure. in a compilation failure.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[23 - FILES] [23 - FILES]
The source distribution of ExprTk is comprised of the following set of The source distribution of ExprTk is comprised of the following set of
@ -2766,7 +2766,7 @@ files:
(19) exprtk_simple_example_15.cpp (19) exprtk_simple_example_15.cpp
(20) exprtk_simple_example_16.cpp (20) exprtk_simple_example_16.cpp
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[24 - LANGUAGE STRUCTURE] [24 - LANGUAGE STRUCTURE]
+-------------------------------------------------------------+ +-------------------------------------------------------------+