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
{
#if exprtk_enable_debugging
#ifdef exprtk_enable_debugging
#define exprtk_debug(params) printf params
#else
#define exprtk_debug(params) (void)0
@ -678,16 +678,16 @@ namespace exprtk
{
namespace constant
{
static const double e = 2.718281828459045235360;
static const double pi = 3.141592653589793238462;
static const double pi_2 = 1.570796326794896619231;
static const double pi_4 = 0.785398163397448309616;
static const double pi_180 = 0.017453292519943295769;
static const double _1_pi = 0.318309886183790671538;
static const double _2_pi = 0.636619772367581343076;
static const double _180_pi = 57.295779513082320876798;
static const double log2 = 0.693147180559945309417;
static const double sqrt2 = 1.414213562373095048801;
static const double e = 2.71828182845904523536028747135266249775724709369996;
static const double pi = 3.14159265358979323846264338327950288419716939937510;
static const double pi_2 = 1.57079632679489661923132169163975144209858469968755;
static const double pi_4 = 0.78539816339744830961566084581987572104929234984378;
static const double pi_180 = 0.01745329251994329576923690768488612713442871888542;
static const double _1_pi = 0.31830988618379067153776752674502872406891929148091;
static const double _2_pi = 0.63661977236758134307553505349005744813783858296183;
static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
static const double log2 = 0.69314718055994530941723212145817656807550013436026;
static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695;
}
namespace details
@ -1760,7 +1760,7 @@ namespace exprtk
if (curr != itr)
{
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
@ -6733,9 +6733,9 @@ namespace exprtk
std::string stringvar_node<T>::null_value = std::string("");
template <typename T>
class string_range_node : public expression_node <T>,
public string_base_node<T>,
public range_interface <T>
class string_range_node : public expression_node <T>,
public string_base_node<T>,
public range_interface <T>
{
public:
@ -11600,7 +11600,7 @@ namespace exprtk
public:
virtual ~boc_base_node()
{}
{}
inline virtual operator_type operation() const
{
@ -13554,6 +13554,43 @@ namespace exprtk
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>
class ipowinv_node : public expression_node<T>
{
@ -13584,6 +13621,43 @@ namespace exprtk
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>
inline bool is_vov_node(const expression_node<T>* node)
{
@ -17139,7 +17213,7 @@ namespace exprtk
{
st = e_usr_variable_type;
default_value = T(0);
error_message = "";
error_message.clear();
return true;
}
@ -17698,7 +17772,7 @@ namespace exprtk
settings_store& disable_inequality_operation(settings_inequality_opr inequality)
{
if (
(e_assign_unknown != inequality) &&
(e_ineq_unknown != inequality) &&
(static_cast<std::size_t>(inequality) < details::inequality_ops_list_size)
)
{
@ -20039,7 +20113,7 @@ namespace exprtk
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))
{
free_node(node_allocator_, condition);
@ -20183,7 +20257,7 @@ namespace exprtk
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))
{
free_node(node_allocator_, condition);
@ -23259,7 +23333,7 @@ namespace exprtk
}
#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) ||
(details::e_acosh == operation) || (details::e_asin == operation) ||
@ -23283,7 +23357,7 @@ namespace exprtk
(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);
@ -23295,7 +23369,7 @@ namespace exprtk
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);
@ -23307,7 +23381,7 @@ namespace exprtk
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);
@ -23319,7 +23393,7 @@ namespace exprtk
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);
@ -23343,9 +23417,9 @@ namespace exprtk
return error_node();
else if (details::is_constant_node(branch[0]))
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);
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);
else
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) ||
(details::e_sub == operation) ||
@ -23481,47 +23555,47 @@ namespace exprtk
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;
else
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;
else
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;
else
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;
else
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;
else
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 (
(details::e_add == operation) ||
@ -23537,7 +23611,7 @@ namespace exprtk
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 (
(details::e_add == operation) ||
@ -23553,33 +23627,33 @@ namespace exprtk
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;
else
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;
else
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;
else
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;
else
return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1]));
@ -23605,6 +23679,22 @@ namespace exprtk
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])
{
return (
@ -23750,7 +23840,11 @@ namespace exprtk
else if (is_string_operation(operation,branch))
return synthesize_string_expression(operation,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();
@ -23770,30 +23864,30 @@ namespace exprtk
*/
result = error_node();
if (cocob_optimizable(operation,branch))
if (cocob_optimisable(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);
if (result)
return result;
}
if (uvouv_optimizable(operation,branch))
if (uvouv_optimisable(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);
else if (bov_optimizable(operation,branch))
else if (bov_optimisable(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);
else if (boc_optimizable(operation,branch))
else if (boc_optimisable(operation,branch))
return synthesize_boc_expression::process(*this,operation,branch);
#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);
#endif
else if (binext_optimizable(operation,branch))
else if (binext_optimisable(operation,branch))
return synthesize_binary_ext_expression::process(*this,operation,branch);
else
return synthesize_expression<binary_node_t,2>(operation,branch);
@ -23853,7 +23947,7 @@ namespace exprtk
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))
{
// True branch
@ -23899,7 +23993,7 @@ namespace exprtk
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))
{
// True branch
@ -23930,9 +24024,9 @@ namespace exprtk
return error_node();
}
#else
inline expression_node_ptr conditional_string(expression_node_ptr ,
expression_node_ptr ,
expression_node_ptr ) const
inline expression_node_ptr conditional_string(expression_node_ptr,
expression_node_ptr,
expression_node_ptr) const
{
return error_node();
}
@ -24055,7 +24149,7 @@ namespace exprtk
template <typename Allocator,
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();
@ -24091,7 +24185,7 @@ namespace exprtk
template <typename Allocator,
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();
@ -24224,7 +24318,7 @@ namespace exprtk
return error_node();
}
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)
{
@ -24258,7 +24352,7 @@ namespace exprtk
return error_node();
}
else if (is_constant_foldable(arg_list))
return const_optimize_mswitch(arg_list);
return const_optimise_mswitch(arg_list);
else
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 temp_node = error_node();
@ -24401,7 +24495,7 @@ namespace exprtk
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;
@ -24450,9 +24544,9 @@ namespace exprtk
if (!all_nodes_valid(branch))
return error_node();
else if (is_constant_foldable(branch))
return const_optimize_sf3(operation,branch);
return const_optimise_sf3(operation,branch);
else if (all_nodes_variables(branch))
return varnode_optimize_sf3(operation,branch);
return varnode_optimise_sf3(operation,branch);
else
{
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();
@ -24538,7 +24632,7 @@ namespace exprtk
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;
@ -24589,9 +24683,9 @@ namespace exprtk
if (!all_nodes_valid(branch))
return error_node();
else if (is_constant_foldable(branch))
return const_optimize_sf4(operation,branch);
return const_optimise_sf4(operation,branch);
else if (all_nodes_variables(branch))
return varnode_optimize_sf4(operation,branch);
return varnode_optimise_sf4(operation,branch);
switch (operation)
{
#define case_stmt(op0,op1) \
@ -24631,7 +24725,7 @@ namespace exprtk
template <typename Allocator,
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();
@ -24674,7 +24768,7 @@ namespace exprtk
template <typename Allocator,
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)
{
@ -24731,13 +24825,13 @@ namespace exprtk
return error_node();
}
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]))
return vectorize_func(operation,arg_list);
else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
return arg_list[0];
else if (all_nodes_variables(arg_list))
return varnode_optimize_varargfunc(operation,arg_list);
return varnode_optimise_varargfunc(operation,arg_list);
switch (operation)
{
@ -24768,7 +24862,7 @@ namespace exprtk
return error_node();
else
{
// Can the function call be completely optimized?
// Can the function call be completely optimised?
if (details::is_constant_node(result))
return result;
else if (!all_nodes_valid(b))
@ -25519,8 +25613,8 @@ namespace exprtk
case_stmt(details::e_xnor,details::xnor_op) \
#ifndef exprtk_disable_cardinal_pow_optimisation
template <template <typename,typename> class IPowNode>
inline expression_node_ptr cardinal_pow_optimization_impl(const T& v, const unsigned int& p)
template <typename TType, template <typename,typename> class IPowNode>
inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& 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 int p = details::numeric::to_int32(details::numeric::abs(c));
@ -25563,26 +25657,50 @@ namespace exprtk
else
{
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
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);
}
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
inline expression_node_ptr cardinal_pow_optimization(T&, const T&)
inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
{
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;
}
inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
{
return error_node();
}
#endif
struct synthesize_binary_ext_expression
@ -26092,6 +26210,18 @@ namespace exprtk
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
@ -26471,7 +26601,7 @@ namespace exprtk
{
result = error_node();
if (!operation_optimizable(operation))
if (!operation_optimisable(operation))
return false;
const std::string node_id = branch_to_id(branch);
@ -26557,12 +26687,12 @@ namespace exprtk
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))
return branch[0];
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))
return expr_gen(T(0));
@ -26631,7 +26761,7 @@ namespace exprtk
{
details::operator_type sf3opr;
if (!expr_gen.sf3_optimizable(id,sf3opr))
if (!expr_gen.sf3_optimisable(id,sf3opr))
return false;
else
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;
if (!expr_gen.sf4_optimizable(id,sf4opr))
if (!expr_gen.sf4_optimisable(id,sf4opr))
return false;
else
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_->
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))
@ -31508,7 +31646,7 @@ namespace exprtk
}
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);
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;
// Attempt simple constant folding optimization.
// Attempt simple constant folding optimisation.
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);

View File

@ -2348,8 +2348,8 @@ inline bool run_test02()
if (!parser.compile(test.expr, expression))
{
printf("run_test02() - Error: %s Expression: %s\n",
parser.error().c_str(),
test.expr.c_str());
parser.error().c_str(),
test.expr.c_str());
result = false;
continue;
@ -2365,13 +2365,13 @@ inline bool run_test02()
if (not_equal(expr_result, test.result))
{
printf("run_test02() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\t"
"a='%s'\tb='%s'\tc='%s'\n",
test.expr.c_str(),
(double)test.result,
(double)expr_result,
str_a.c_str(),
str_b.c_str(),
str_c.c_str());
"a='%s'\tb='%s'\tc='%s'\n",
test.expr.c_str(),
(double)test.result,
(double)expr_result,
str_a.c_str(),
str_b.c_str(),
str_c.c_str());
result = false;
continue;
@ -6325,11 +6325,13 @@ inline bool run_test19()
104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729,
1000621, 1000639, 1000651, 1000667, 1000669, 1001023, 1001027, 1001041
};
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)
{
x = prime_list[i];
x = static_cast<T>(prime_list[i]);
std::vector<T> result(expression_count,T(0));
for (std::size_t j = 0; j < expression_list.size(); ++j)
@ -6467,6 +6469,7 @@ inline bool run_test19()
"x"));
symbol_table_t& symbol_table = compositor.symbol_table();
symbol_table.add_constants();
symbol_table.add_variable("x",x);
@ -6515,11 +6518,13 @@ inline bool run_test19()
46368, 75025, 121393, 196418,
317811, 514229, 832040, 1346269
};
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)
{
x = i;
x = static_cast<T>(i);
std::vector<T> result(expression_count,T(0));
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)
{
x = i;
x = static_cast<T>(i);
T result = expression.value();
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)
{
x = T(i);
sum += x;
T result = expression.value();
if (result != sum)
@ -6847,7 +6855,7 @@ struct my_usr : public exprtk::parser<T>::unknown_symbol_resolver
{
st = usr_t::e_usr_variable_type;
default_value = next_value();
error_message = "";
error_message.clear();
return true;
}
@ -6855,7 +6863,7 @@ struct my_usr : public exprtk::parser<T>::unknown_symbol_resolver
{
st = usr_t::e_usr_constant_type;
default_value = next_value();
error_message = "";
error_message.clear();
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
semantics and is easily extendible.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[01 - CAPABILITIES]
The ExprTk expression evaluator supports the following fundamental
@ -49,7 +49,7 @@ arithmetic operations, functions and processes:
(11) Calculus: numerical integration and differentiation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[02 - EXAMPLE EXPRESSIONS]
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)
(20) sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[03 - COPYRIGHT NOTICE]
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[04 - DOWNLOADS & UPDATES]
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
(b) Repository: https://github.com/ArashPartow/exprtk
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[05 - INSTALLATION]
The header file exprtk.hpp should be placed in a project or system
include path (e.g: /usr/include/).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[06 - COMPILATION]
(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
(d) Execute valgrind check: make valgrind_check
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[07 - COMPILER COMPATIBILITY]
ExprTk has been built error and warning free using the following set
@ -120,11 +120,10 @@ of C++ compilers:
(*) Clang/LLVM (1.1+)
(*) PGI C++ (10.x+)
(*) Microsoft Visual Studio C++ Compiler (8.1+)
(*) Comeau C++ Compiler (4.3+)
(*) IBM XL C/C++ (9.x+)
(*) C++ Builder (XE4+)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[08 - BUILT-IN OPERATIONS & FUNCTIONS]
@ -604,7 +603,7 @@ appropriate may represent any of one the following:
5. A string
6. An expression comprised of [1], [2] or [3] (eg: 2 + x / vec[3])
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[09 - Fundamental Types]
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
however can not interact with scalar or vector types.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[10 - COMPONENTS]
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
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
instance of Expression. If an error is encountered during the
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'
interface.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[11 - COMPILATION OPTIONS]
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
larger numerical bound.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[12 - SPECIAL FUNCTIONS]
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
$f99(x,y,z,w) | x*sin(y)+z*cos(w)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[13 - VARIABLE , VECTOR & STRING DEFINITION]
ExprTk supports the definition of expression local variables, vectors
@ -1127,7 +1126,7 @@ based on the following priorities:
(e) Symbol table functions
(f) Unknown symbol resolver based variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[14 - VECTOR PROCESSING]
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)
max(x / 2) == (3 / 2)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[15 - USER DEFINED FUNCTIONS]
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);
}
};
@ -1735,7 +1735,7 @@ carried out:
{ ... }
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[16 - EXPRESSION DEPENDENTS]
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
will not contain symbols denoting functions.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[17 - ENABLING AND DISABLING FEATURES]
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
ExprTk reserved words, the add_function call will fail.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[18 - EXPRESSION RETURN VALUES]
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::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)
{
@ -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.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[19 - COMPILATION ERRORS]
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
via the 'unknown symbol resolver' mechanism.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[20 - EXPRTK NOTES]
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);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[21 - SIMPLE EXPRTK EXAMPLE]
--- snip ---
@ -2692,7 +2692,7 @@ int main()
}
--- snip ---
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[22 - BUILD OPTIONS]
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
in a compilation failure.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[23 - FILES]
The source distribution of ExprTk is comprised of the following set of
@ -2766,7 +2766,7 @@ files:
(19) exprtk_simple_example_15.cpp
(20) exprtk_simple_example_16.cpp
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[24 - LANGUAGE STRUCTURE]
+-------------------------------------------------------------+