C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
b1a89fc96a
commit
816385aa4c
415
exprtk.hpp
415
exprtk.hpp
|
@ -42,6 +42,7 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,7 +154,8 @@ namespace exprtk
|
||||||
|
|
||||||
static const std::string reserved_words[] =
|
static const std::string reserved_words[] =
|
||||||
{
|
{
|
||||||
"and", "for", "if", "ilike", "in", "like", "nand", "nor", "not", "or", "while", "xor"
|
"and", "false", "for", "if", "ilike", "in", "like", "nand", "nor", "not",
|
||||||
|
"or", "true", "while", "xor"
|
||||||
};
|
};
|
||||||
static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
|
static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
|
||||||
|
|
||||||
|
@ -161,11 +163,11 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
"abs", "acos", "and", "asin", "atan", "atan2", "avg", "ceil", "clamp",
|
"abs", "acos", "and", "asin", "atan", "atan2", "avg", "ceil", "clamp",
|
||||||
"cos", "cosh", "cot", "csc", "deg2grad", "deg2rad", "equal", "erf", "erfc",
|
"cos", "cosh", "cot", "csc", "deg2grad", "deg2rad", "equal", "erf", "erfc",
|
||||||
"exp", "floor", "for", "grad2deg", "hyp", "if", "ilike", "in", "inrange",
|
"exp", "false", "floor", "for", "grad2deg", "hyp", "if", "ilike", "in",
|
||||||
"like", "log", "log10", "logn", "max", "min", "mod", "mul", "nand",
|
"inrange", "like", "log", "log10", "logn", "max", "min", "mod", "mul",
|
||||||
"nor", "not", "not_equal", "or", "rad2deg", "root", "round", "roundn",
|
"nand", "nor", "not", "not_equal", "or", "rad2deg", "root", "round",
|
||||||
"sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum", "tan", "tanh",
|
"roundn", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum",
|
||||||
"while", "xor"
|
"tan", "tanh", "true", "while", "xor"
|
||||||
};
|
};
|
||||||
static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
|
static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
|
||||||
|
|
||||||
|
@ -544,6 +546,58 @@ namespace exprtk
|
||||||
return erfc_impl(static_cast<double>(v),real_type_tag());
|
return erfc_impl(static_cast<double>(v),real_type_tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> inline T abs_impl (const T v, real_type_tag) { return std::abs (v); }
|
||||||
|
template <typename T> inline T acos_impl (const T v, real_type_tag) { return std::acos (v); }
|
||||||
|
template <typename T> inline T asin_impl (const T v, real_type_tag) { return std::asin (v); }
|
||||||
|
template <typename T> inline T atan_impl (const T v, real_type_tag) { return std::atan (v); }
|
||||||
|
template <typename T> inline T ceil_impl (const T v, real_type_tag) { return std::ceil (v); }
|
||||||
|
template <typename T> inline T cos_impl (const T v, real_type_tag) { return std::cos (v); }
|
||||||
|
template <typename T> inline T cosh_impl (const T v, real_type_tag) { return std::cosh (v); }
|
||||||
|
template <typename T> inline T exp_impl (const T v, real_type_tag) { return std::exp (v); }
|
||||||
|
template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
|
||||||
|
template <typename T> inline T log_impl (const T v, real_type_tag) { return std::log (v); }
|
||||||
|
template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
|
||||||
|
template <typename T> inline T neg_impl (const T v, real_type_tag) { return -v; }
|
||||||
|
template <typename T> inline T pos_impl (const T v, real_type_tag) { return +v; }
|
||||||
|
template <typename T> inline T round_impl(const T v, real_type_tag) { return std::floor(v + T(0.5)); }
|
||||||
|
template <typename T> inline T sin_impl (const T v, real_type_tag) { return std::sin (v); }
|
||||||
|
template <typename T> inline T sinh_impl (const T v, real_type_tag) { return std::sinh (v); }
|
||||||
|
template <typename T> inline T sqrt_impl (const T v, real_type_tag) { return std::sqrt (v); }
|
||||||
|
template <typename T> inline T tan_impl (const T v, real_type_tag) { return std::tan (v); }
|
||||||
|
template <typename T> inline T tanh_impl (const T v, real_type_tag) { return std::tanh (v); }
|
||||||
|
template <typename T> inline T cot_impl (const T v, real_type_tag) { return T(1) / std::tan(v); }
|
||||||
|
template <typename T> inline T sec_impl (const T v, real_type_tag) { return T(1) / std::cos(v); }
|
||||||
|
template <typename T> inline T csc_impl (const T v, real_type_tag) { return T(1) / std::sin(v); }
|
||||||
|
template <typename T> inline T r2d_impl (const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
|
||||||
|
template <typename T> inline T d2r_impl (const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
|
||||||
|
template <typename T> inline T d2g_impl (const T v, real_type_tag) { return (v * T(20.0/9.0)); }
|
||||||
|
template <typename T> inline T g2d_impl (const T v, real_type_tag) { return (v * T(9.0/20.0)); }
|
||||||
|
template <typename T> inline T notl_impl (const T v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); }
|
||||||
|
|
||||||
|
template <typename T> inline T abs_impl (const T v, int_type_tag) { return std::abs (v); }
|
||||||
|
template <typename T> inline T exp_impl (const T v, int_type_tag) { return std::exp (v); }
|
||||||
|
template <typename T> inline T log_impl (const T v, int_type_tag) { return std::log (v); }
|
||||||
|
template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
|
||||||
|
template <typename T> inline T neg_impl (const T v, int_type_tag) { return -v; }
|
||||||
|
template <typename T> inline T pos_impl (const T v, int_type_tag) { return +v; }
|
||||||
|
template <typename T> inline T ceil_impl (const T v, int_type_tag) { return v; }
|
||||||
|
template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
|
||||||
|
template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
|
||||||
|
template <typename T> inline T notl_impl (const T v, int_type_tag) { return !v; }
|
||||||
|
template <typename T> inline T sqrt_impl (const T v, int_type_tag) { return std::sqrt (v); }
|
||||||
|
template <typename T> inline T acos_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T asin_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T atan_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T cos_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T cosh_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T sin_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T sinh_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T tan_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T tanh_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T cot_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T sec_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
template <typename T> inline T csc_impl (const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool is_integer_impl(const T& v, real_type_tag)
|
inline bool is_integer_impl(const T& v, real_type_tag)
|
||||||
{
|
{
|
||||||
|
@ -643,13 +697,6 @@ namespace exprtk
|
||||||
return details::shl_impl(v0,v1,num_type);
|
return details::shl_impl(v0,v1,num_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T sgn(const T& v)
|
|
||||||
{
|
|
||||||
typename details::number_type<T>::type num_type;
|
|
||||||
return details::sgn_impl(v,num_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T xor_opr(const T& v0, const T& v1)
|
inline T xor_opr(const T& v0, const T& v1)
|
||||||
{
|
{
|
||||||
|
@ -657,20 +704,6 @@ namespace exprtk
|
||||||
return details::xor_impl(v0,v1,num_type);
|
return details::xor_impl(v0,v1,num_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T erf(const T& v)
|
|
||||||
{
|
|
||||||
typename details::number_type<T>::type num_type;
|
|
||||||
return details::erf_impl(v,num_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T erfc(const T& v)
|
|
||||||
{
|
|
||||||
typename details::number_type<T>::type num_type;
|
|
||||||
return details::erfc_impl(v,num_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool is_integer(const T& v)
|
inline bool is_integer(const T& v)
|
||||||
{
|
{
|
||||||
|
@ -711,6 +744,45 @@ namespace exprtk
|
||||||
template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
|
template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
|
||||||
template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
|
template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
|
||||||
|
|
||||||
|
#define exprtk_define_unary_function(FunctionName) \
|
||||||
|
template <typename T> \
|
||||||
|
inline T FunctionName (const T& v) \
|
||||||
|
{ \
|
||||||
|
typename details::number_type<T>::type num_type; \
|
||||||
|
return details:: FunctionName##_impl(v,num_type); \
|
||||||
|
}
|
||||||
|
|
||||||
|
exprtk_define_unary_function(abs )
|
||||||
|
exprtk_define_unary_function(acos )
|
||||||
|
exprtk_define_unary_function(asin )
|
||||||
|
exprtk_define_unary_function(atan )
|
||||||
|
exprtk_define_unary_function(ceil )
|
||||||
|
exprtk_define_unary_function(cos )
|
||||||
|
exprtk_define_unary_function(cosh )
|
||||||
|
exprtk_define_unary_function(exp )
|
||||||
|
exprtk_define_unary_function(floor)
|
||||||
|
exprtk_define_unary_function(log )
|
||||||
|
exprtk_define_unary_function(log10)
|
||||||
|
exprtk_define_unary_function(neg )
|
||||||
|
exprtk_define_unary_function(pos )
|
||||||
|
exprtk_define_unary_function(round)
|
||||||
|
exprtk_define_unary_function(sin )
|
||||||
|
exprtk_define_unary_function(sinh )
|
||||||
|
exprtk_define_unary_function(sqrt )
|
||||||
|
exprtk_define_unary_function(tan )
|
||||||
|
exprtk_define_unary_function(tanh )
|
||||||
|
exprtk_define_unary_function(cot )
|
||||||
|
exprtk_define_unary_function(sec )
|
||||||
|
exprtk_define_unary_function(csc )
|
||||||
|
exprtk_define_unary_function(r2d )
|
||||||
|
exprtk_define_unary_function(d2r )
|
||||||
|
exprtk_define_unary_function(d2g )
|
||||||
|
exprtk_define_unary_function(g2d )
|
||||||
|
exprtk_define_unary_function(notl )
|
||||||
|
exprtk_define_unary_function(sgn )
|
||||||
|
exprtk_define_unary_function(erf )
|
||||||
|
exprtk_define_unary_function(erfc )
|
||||||
|
#undef exprtk_define_unary_function
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -758,12 +830,14 @@ namespace exprtk
|
||||||
token(token_type ttype,
|
token(token_type ttype,
|
||||||
const char* begin, const char* end)
|
const char* begin, const char* end)
|
||||||
: type(ttype),
|
: type(ttype),
|
||||||
value(std::string(begin,end))
|
value(std::string(begin,end)),
|
||||||
|
numeric_value(T(0))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
token(token_type ttype, const std::string& v)
|
token(token_type ttype, const std::string& v)
|
||||||
: type(ttype),
|
: type(ttype),
|
||||||
value(v)
|
value(v),
|
||||||
|
numeric_value(T(0))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
token(token_type ttype, const T& num_val)
|
token(token_type ttype, const T& num_val)
|
||||||
|
@ -919,6 +993,13 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
++s_itr;
|
++s_itr;
|
||||||
}
|
}
|
||||||
|
static const std::string true_string = "true";
|
||||||
|
static const std::string false_string = "false";
|
||||||
|
if (details::imatch(std::string(begin,s_itr),true_string))
|
||||||
|
token_list_.push_back(token_t(token_t::number,T(1)));
|
||||||
|
else if (details::imatch(std::string(begin,s_itr),false_string))
|
||||||
|
token_list_.push_back(token_t(token_t::number,T(0)));
|
||||||
|
else
|
||||||
token_list_.push_back(token_t(token_t::symbol,begin,s_itr));
|
token_list_.push_back(token_t(token_t::symbol,begin,s_itr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1511,7 +1592,7 @@ namespace exprtk
|
||||||
e_d2g ,
|
e_d2g ,
|
||||||
e_g2d ,
|
e_g2d ,
|
||||||
e_hyp ,
|
e_hyp ,
|
||||||
e_not ,
|
e_notl ,
|
||||||
e_erf ,
|
e_erf ,
|
||||||
e_erfc ,
|
e_erfc ,
|
||||||
e_assign ,
|
e_assign ,
|
||||||
|
@ -1591,33 +1672,33 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
case e_abs : return std::abs (arg);
|
case e_abs : return numeric::abs (arg);
|
||||||
case e_acos : return std::acos (arg);
|
case e_acos : return numeric::acos (arg);
|
||||||
case e_asin : return std::asin (arg);
|
case e_asin : return numeric::asin (arg);
|
||||||
case e_atan : return std::atan (arg);
|
case e_atan : return numeric::atan (arg);
|
||||||
case e_ceil : return std::ceil (arg);
|
case e_ceil : return numeric::ceil (arg);
|
||||||
case e_cos : return std::cos (arg);
|
case e_cos : return numeric::cos (arg);
|
||||||
case e_cosh : return std::cosh (arg);
|
case e_cosh : return numeric::cosh (arg);
|
||||||
case e_exp : return std::exp (arg);
|
case e_exp : return numeric::exp (arg);
|
||||||
case e_floor : return std::floor(arg);
|
case e_floor : return numeric::floor(arg);
|
||||||
case e_log : return std::log (arg);
|
case e_log : return numeric::log (arg);
|
||||||
case e_log10 : return std::log10(arg);
|
case e_log10 : return numeric::log10(arg);
|
||||||
case e_neg : return -arg;
|
case e_neg : return numeric::neg (arg);
|
||||||
case e_pos : return +arg;
|
case e_pos : return numeric::pos (arg);
|
||||||
case e_round : return std::floor(arg + T(0.5));
|
case e_round : return numeric::round(arg);
|
||||||
case e_sin : return std::sin (arg);
|
case e_sin : return numeric::sin (arg);
|
||||||
case e_sinh : return std::sinh (arg);
|
case e_sinh : return numeric::sinh (arg);
|
||||||
case e_sqrt : return std::sqrt (arg);
|
case e_sqrt : return numeric::sqrt (arg);
|
||||||
case e_tan : return std::tan (arg);
|
case e_tan : return numeric::tan (arg);
|
||||||
case e_tanh : return std::tanh (arg);
|
case e_tanh : return numeric::tanh (arg);
|
||||||
case e_cot : return T(1) / std::tan(arg);
|
case e_cot : return numeric::cot (arg);
|
||||||
case e_sec : return T(1) / std::cos(arg);
|
case e_sec : return numeric::sec (arg);
|
||||||
case e_csc : return T(1) / std::sin(arg);
|
case e_csc : return numeric::csc (arg);
|
||||||
case e_r2d : return (arg * T(numeric::constant::_180_pi));
|
case e_r2d : return numeric::r2d (arg);
|
||||||
case e_d2r : return (arg * T(numeric::constant::pi_180));
|
case e_d2r : return numeric::d2r (arg);
|
||||||
case e_d2g : return (arg * T(20/9));
|
case e_d2g : return numeric::d2g (arg);
|
||||||
case e_g2d : return (arg * T(9/20));
|
case e_g2d : return numeric::g2d (arg);
|
||||||
case e_not : return (arg != T(0) ? T(0) : T(1));
|
case e_notl : return numeric::notl (arg);
|
||||||
case e_sgn : return numeric::sgn (arg);
|
case e_sgn : return numeric::sgn (arg);
|
||||||
case e_erf : return numeric::erf (arg);
|
case e_erf : return numeric::erf (arg);
|
||||||
case e_erfc : return numeric::erfc (arg);
|
case e_erfc : return numeric::erfc (arg);
|
||||||
|
@ -1630,14 +1711,14 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
case e_abs : return std::abs (arg);
|
case e_abs : return numeric::abs (arg);
|
||||||
case e_exp : return std::exp (arg);
|
case e_exp : return numeric::exp (arg);
|
||||||
case e_log : return std::log (arg);
|
case e_log : return numeric::log (arg);
|
||||||
case e_log10 : return std::log10(arg);
|
case e_log10 : return numeric::log10(arg);
|
||||||
case e_neg : return -arg;
|
case e_neg : return numeric::neg (arg);
|
||||||
case e_pos : return +arg;
|
case e_pos : return numeric::pos (arg);
|
||||||
case e_sqrt : return std::sqrt (arg);
|
case e_sqrt : return numeric::sqrt (arg);
|
||||||
case e_not : return !arg;
|
case e_notl : return numeric::notl (arg);
|
||||||
case e_sgn : return numeric::sgn (arg);
|
case e_sgn : return numeric::sgn (arg);
|
||||||
default : return std::numeric_limits<T>::quiet_NaN();
|
default : return std::numeric_limits<T>::quiet_NaN();
|
||||||
}
|
}
|
||||||
|
@ -2815,6 +2896,47 @@ namespace exprtk
|
||||||
std::size_t parameter_count_;
|
std::size_t parameter_count_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define exprtk_def_unary_op(OpName) \
|
||||||
|
template <typename T> \
|
||||||
|
struct OpName##_op \
|
||||||
|
{ \
|
||||||
|
static inline T process(const T& v) { return numeric:: OpName (v); } \
|
||||||
|
static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_##OpName; } \
|
||||||
|
static inline details::operator_type operation() { return details::e_##OpName; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
exprtk_def_unary_op(abs )
|
||||||
|
exprtk_def_unary_op(acos )
|
||||||
|
exprtk_def_unary_op(asin )
|
||||||
|
exprtk_def_unary_op(atan )
|
||||||
|
exprtk_def_unary_op(ceil )
|
||||||
|
exprtk_def_unary_op(cos )
|
||||||
|
exprtk_def_unary_op(cosh )
|
||||||
|
exprtk_def_unary_op(exp )
|
||||||
|
exprtk_def_unary_op(floor)
|
||||||
|
exprtk_def_unary_op(log )
|
||||||
|
exprtk_def_unary_op(log10)
|
||||||
|
exprtk_def_unary_op(neg )
|
||||||
|
exprtk_def_unary_op(pos )
|
||||||
|
exprtk_def_unary_op(round)
|
||||||
|
exprtk_def_unary_op(sin )
|
||||||
|
exprtk_def_unary_op(sinh )
|
||||||
|
exprtk_def_unary_op(sqrt )
|
||||||
|
exprtk_def_unary_op(tan )
|
||||||
|
exprtk_def_unary_op(tanh )
|
||||||
|
exprtk_def_unary_op(cot )
|
||||||
|
exprtk_def_unary_op(sec )
|
||||||
|
exprtk_def_unary_op(csc )
|
||||||
|
exprtk_def_unary_op(r2d )
|
||||||
|
exprtk_def_unary_op(d2r )
|
||||||
|
exprtk_def_unary_op(d2g )
|
||||||
|
exprtk_def_unary_op(g2d )
|
||||||
|
exprtk_def_unary_op(notl )
|
||||||
|
exprtk_def_unary_op(sgn )
|
||||||
|
exprtk_def_unary_op(erf )
|
||||||
|
exprtk_def_unary_op(erfc )
|
||||||
|
#undef exprtk_def_unary_op
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct add_op
|
struct add_op
|
||||||
{
|
{
|
||||||
|
@ -3867,7 +3989,7 @@ namespace exprtk
|
||||||
operation_t( "deg2grad" , e_d2g , 1),
|
operation_t( "deg2grad" , e_d2g , 1),
|
||||||
operation_t( "grad2deg" , e_g2d , 1),
|
operation_t( "grad2deg" , e_g2d , 1),
|
||||||
operation_t( "sgn" , e_sgn , 1),
|
operation_t( "sgn" , e_sgn , 1),
|
||||||
operation_t( "not" , e_not , 1),
|
operation_t( "not" , e_notl , 1),
|
||||||
operation_t( "erf" , e_erf , 1),
|
operation_t( "erf" , e_erf , 1),
|
||||||
operation_t( "erfc" , e_erfc , 1),
|
operation_t( "erfc" , e_erfc , 1),
|
||||||
operation_t( "atan2", e_atan2 , 2),
|
operation_t( "atan2", e_atan2 , 2),
|
||||||
|
@ -4042,7 +4164,16 @@ namespace exprtk
|
||||||
|
|
||||||
inline bool is_constant(const std::string& symbol_name) const
|
inline bool is_constant(const std::string& symbol_name) const
|
||||||
{
|
{
|
||||||
return short_type_lut[static_cast<std::size_t>(symbol_name[0])].first;
|
if (1 == symbol_name.size() && short_type_lut[static_cast<std::size_t>(symbol_name[0])].first)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tm_const_itr_t itr = map.find(symbol_name);
|
||||||
|
if (map.end() == itr)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return (*itr).second.first;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool add(const std::string& symbol_name, RawType& t, const bool is_constant = false)
|
inline bool add(const std::string& symbol_name, RawType& t, const bool is_constant = false)
|
||||||
|
@ -4293,8 +4424,26 @@ namespace exprtk
|
||||||
#endif
|
#endif
|
||||||
type_store<ifunction<T>,ifunction<T> > function_store;
|
type_store<ifunction<T>,ifunction<T> > function_store;
|
||||||
|
|
||||||
|
st_data()
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < details::reserved_words_size; ++i)
|
||||||
|
{
|
||||||
|
reserved_symbol_table_.insert(details::reserved_words[i]);
|
||||||
|
}
|
||||||
|
for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
|
||||||
|
{
|
||||||
|
reserved_symbol_table_.insert(details::reserved_symbols[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_reserved_symbol(const std::string& symbol) const
|
||||||
|
{
|
||||||
|
return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
|
||||||
|
}
|
||||||
|
|
||||||
std::list<T> local_symbol_list_;
|
std::list<T> local_symbol_list_;
|
||||||
std::list<std::string> local_stringvar_list_;
|
std::list<std::string> local_stringvar_list_;
|
||||||
|
std::set<std::string> reserved_symbol_table_;
|
||||||
};
|
};
|
||||||
|
|
||||||
st_holder()
|
st_holder()
|
||||||
|
@ -4641,7 +4790,7 @@ namespace exprtk
|
||||||
inline bool symbol_exists(const std::string& symbol_name) const
|
inline bool symbol_exists(const std::string& symbol_name) const
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Will return true if symbol_name exists as either a
|
Will return true if symbol_name exists as either a reserved symbol,
|
||||||
variable, stringvar or function name in any of the type stores.
|
variable, stringvar or function name in any of the type stores.
|
||||||
*/
|
*/
|
||||||
if (!valid())
|
if (!valid())
|
||||||
|
@ -4654,6 +4803,8 @@ namespace exprtk
|
||||||
#endif
|
#endif
|
||||||
else if (local_data().function_store.symbol_exists(symbol_name))
|
else if (local_data().function_store.symbol_exists(symbol_name))
|
||||||
return true;
|
return true;
|
||||||
|
else if (local_data().is_reserved_symbol(symbol_name))
|
||||||
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4710,7 +4861,7 @@ namespace exprtk
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return (!local_data().is_reserved_symbol(symbol));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline typename st_holder::st_data& local_data()
|
inline typename st_holder::st_data& local_data()
|
||||||
|
@ -4728,6 +4879,7 @@ namespace exprtk
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> class parser;
|
template <typename T> class parser;
|
||||||
|
template <typename T> class expression_helper;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class expression
|
class expression
|
||||||
|
@ -4880,6 +5032,38 @@ namespace exprtk
|
||||||
symbol_table<T> symbol_table_;
|
symbol_table<T> symbol_table_;
|
||||||
|
|
||||||
friend class parser<T>;
|
friend class parser<T>;
|
||||||
|
friend class expression_helper<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class expression_helper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static inline bool is_head_constant(const expression<T>& expr)
|
||||||
|
{
|
||||||
|
return details::is_constant_node(expr.expression_holder_->expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_head_variable(const expression<T>& expr)
|
||||||
|
{
|
||||||
|
return details::is_variable_node(expr.expression_holder_->expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_head_unary(const expression<T>& expr)
|
||||||
|
{
|
||||||
|
return details::is_unary_node(expr.expression_holder_->expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_head_binary(const expression<T>& expr)
|
||||||
|
{
|
||||||
|
return details::is_binary_node(expr.expression_holder_->expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool is_head_function(const expression<T>& expr)
|
||||||
|
{
|
||||||
|
return details::is_function(expr.expression_holder_->expr);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -5406,7 +5590,7 @@ namespace exprtk
|
||||||
}
|
}
|
||||||
else if (symbol_table_.valid())
|
else if (symbol_table_.valid())
|
||||||
{
|
{
|
||||||
const std::string symbol = current_token_.value;
|
const std::string& symbol = current_token_.value;
|
||||||
//Are we dealing with a variable or a special constant?
|
//Are we dealing with a variable or a special constant?
|
||||||
expression_node_ptr variable = symbol_table_.get_variable(symbol);
|
expression_node_ptr variable = symbol_table_.get_variable(symbol);
|
||||||
if (variable)
|
if (variable)
|
||||||
|
@ -5908,10 +6092,52 @@ namespace exprtk
|
||||||
return node_allocator_->allocate<while_loop_node_t>(condition,branch);
|
return node_allocator_->allocate<while_loop_node_t>(condition,branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
|
||||||
|
{
|
||||||
|
expression_node_ptr temp_node = error_node();
|
||||||
|
switch (operation)
|
||||||
|
{
|
||||||
|
#define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate<details::sf3_node<Type,op1<Type> > >(operation,branch); break;
|
||||||
|
case_stmt(details::e_sf00,details::sf00_op)
|
||||||
|
case_stmt(details::e_sf01,details::sf01_op)
|
||||||
|
case_stmt(details::e_sf02,details::sf02_op)
|
||||||
|
case_stmt(details::e_sf03,details::sf03_op)
|
||||||
|
case_stmt(details::e_sf04,details::sf04_op)
|
||||||
|
case_stmt(details::e_sf05,details::sf05_op)
|
||||||
|
case_stmt(details::e_sf06,details::sf06_op)
|
||||||
|
case_stmt(details::e_sf07,details::sf07_op)
|
||||||
|
case_stmt(details::e_sf08,details::sf08_op)
|
||||||
|
case_stmt(details::e_sf09,details::sf09_op)
|
||||||
|
case_stmt(details::e_sf10,details::sf10_op)
|
||||||
|
case_stmt(details::e_sf11,details::sf11_op)
|
||||||
|
case_stmt(details::e_sf12,details::sf12_op)
|
||||||
|
case_stmt(details::e_sf13,details::sf13_op)
|
||||||
|
case_stmt(details::e_sf14,details::sf14_op)
|
||||||
|
case_stmt(details::e_sf15,details::sf15_op)
|
||||||
|
case_stmt(details::e_sf16,details::sf16_op)
|
||||||
|
case_stmt(details::e_sf17,details::sf17_op)
|
||||||
|
case_stmt(details::e_sf18,details::sf18_op)
|
||||||
|
case_stmt(details::e_sf19,details::sf19_op)
|
||||||
|
case_stmt(details::e_sf20,details::sf20_op)
|
||||||
|
case_stmt(details::e_sf21,details::sf21_op)
|
||||||
|
case_stmt(details::e_sf22,details::sf22_op)
|
||||||
|
case_stmt(details::e_sf23,details::sf23_op)
|
||||||
|
case_stmt(details::e_sf24,details::sf24_op)
|
||||||
|
case_stmt(details::e_sf25,details::sf25_op)
|
||||||
|
default : return error_node();
|
||||||
|
#undef case_stmt
|
||||||
|
}
|
||||||
|
T v = temp_node->value();
|
||||||
|
node_allocator_->free(temp_node);
|
||||||
|
return node_allocator_->allocate<literal_node_t>(v);
|
||||||
|
}
|
||||||
|
|
||||||
inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
|
inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
|
||||||
{
|
{
|
||||||
if (!all_nodes_valid(branch))
|
if (!all_nodes_valid(branch))
|
||||||
return error_node();
|
return error_node();
|
||||||
|
else if (is_constant_foldable(branch))
|
||||||
|
return const_optimize_sf3(operation,branch);
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
#define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<details::sf3_node<Type,op1<Type> > >(operation,branch);
|
#define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<details::sf3_node<Type,op1<Type> > >(operation,branch);
|
||||||
|
@ -5946,10 +6172,59 @@ namespace exprtk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
|
||||||
|
{
|
||||||
|
expression_node_ptr temp_node = error_node();
|
||||||
|
switch (operation)
|
||||||
|
{
|
||||||
|
#define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); break;
|
||||||
|
case_stmt(details::e_sf26,details::sf26_op)
|
||||||
|
case_stmt(details::e_sf27,details::sf27_op)
|
||||||
|
case_stmt(details::e_sf28,details::sf28_op)
|
||||||
|
case_stmt(details::e_sf29,details::sf29_op)
|
||||||
|
case_stmt(details::e_sf30,details::sf30_op)
|
||||||
|
case_stmt(details::e_sf31,details::sf31_op)
|
||||||
|
case_stmt(details::e_sf32,details::sf32_op)
|
||||||
|
case_stmt(details::e_sf33,details::sf33_op)
|
||||||
|
case_stmt(details::e_sf34,details::sf34_op)
|
||||||
|
case_stmt(details::e_sf35,details::sf35_op)
|
||||||
|
case_stmt(details::e_sf36,details::sf36_op)
|
||||||
|
case_stmt(details::e_sf37,details::sf37_op)
|
||||||
|
case_stmt(details::e_sf38,details::sf38_op)
|
||||||
|
case_stmt(details::e_sf39,details::sf39_op)
|
||||||
|
case_stmt(details::e_sf40,details::sf40_op)
|
||||||
|
case_stmt(details::e_sf41,details::sf41_op)
|
||||||
|
case_stmt(details::e_sf42,details::sf42_op)
|
||||||
|
case_stmt(details::e_sf43,details::sf43_op)
|
||||||
|
case_stmt(details::e_sf44,details::sf44_op)
|
||||||
|
case_stmt(details::e_sf45,details::sf45_op)
|
||||||
|
case_stmt(details::e_sf46,details::sf46_op)
|
||||||
|
case_stmt(details::e_sf47,details::sf47_op)
|
||||||
|
case_stmt(details::e_sf48,details::sf48_op)
|
||||||
|
case_stmt(details::e_sf49,details::sf49_op)
|
||||||
|
case_stmt(details::e_sf50,details::sf50_op)
|
||||||
|
case_stmt(details::e_sf51,details::sf51_op)
|
||||||
|
case_stmt(details::e_sf52,details::sf52_op)
|
||||||
|
case_stmt(details::e_sf53,details::sf53_op)
|
||||||
|
case_stmt(details::e_sf54,details::sf54_op)
|
||||||
|
case_stmt(details::e_sf55,details::sf55_op)
|
||||||
|
case_stmt(details::e_sf56,details::sf56_op)
|
||||||
|
case_stmt(details::e_sf57,details::sf57_op)
|
||||||
|
case_stmt(details::e_sf58,details::sf58_op)
|
||||||
|
default : return error_node();
|
||||||
|
#undef case_stmt
|
||||||
|
}
|
||||||
|
T v = temp_node->value();
|
||||||
|
node_allocator_->free(temp_node);
|
||||||
|
return node_allocator_->allocate<literal_node_t>(v);
|
||||||
|
}
|
||||||
|
|
||||||
inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
|
inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
|
||||||
{
|
{
|
||||||
if (!all_nodes_valid(branch))
|
if (!all_nodes_valid(branch))
|
||||||
return error_node();
|
return error_node();
|
||||||
|
else if (is_constant_foldable(branch))
|
||||||
|
return const_optimize_sf4(operation,branch);
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
#define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<details::sf4_node<Type,op1<Type> > >(operation,branch);
|
#define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<details::sf4_node<Type,op1<Type> > >(operation,branch);
|
||||||
|
|
|
@ -35,13 +35,13 @@ const std::string expression_list[] = {
|
||||||
"1 - sin(2 * x) + cos(pi / y)",
|
"1 - sin(2 * x) + cos(pi / y)",
|
||||||
"sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
|
"sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
|
||||||
"(x^2 / sin(2 * pi / y)) -x / 2",
|
"(x^2 / sin(2 * pi / y)) -x / 2",
|
||||||
|
"x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
|
||||||
"clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
|
"clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
|
||||||
"max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
|
"max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
|
||||||
"if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x"
|
"if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x"
|
||||||
};
|
};
|
||||||
const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
|
const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
|
||||||
|
|
||||||
|
|
||||||
template <typename T,
|
template <typename T,
|
||||||
typename Allocator,
|
typename Allocator,
|
||||||
template <typename,typename> class Sequence>
|
template <typename,typename> class Sequence>
|
||||||
|
@ -85,10 +85,13 @@ void run_benchmark(T& x, T& y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timer.stop();
|
timer.stop();
|
||||||
|
if (T(0.0) != total)
|
||||||
printf("[exprtk] Total Time:%12.8f Rate:%14.3fevals/sec Expression: %s\n",
|
printf("[exprtk] Total Time:%12.8f Rate:%14.3fevals/sec Expression: %s\n",
|
||||||
timer.time(),
|
timer.time(),
|
||||||
count / timer.time(),
|
count / timer.time(),
|
||||||
expr_string.c_str());
|
expr_string.c_str());
|
||||||
|
else
|
||||||
|
std::cerr << "Error - expression: " << expr_string << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
const double pi = 3.14159265358979323846;
|
const double pi = 3.14159265358979323846;
|
||||||
|
@ -108,20 +111,21 @@ inline T clamp(const T& l, const T& v, const T& u)
|
||||||
return (v > u) ? u : v;
|
return (v > u) ? u : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> inline T func00(const T& x, const T& y) { return (y + x); }
|
template <typename T> inline T func00(const T x, const T y) { return (y + x); }
|
||||||
template <typename T> inline T func01(const T& x, const T& y) { return T(2.0) * (y + x); }
|
template <typename T> inline T func01(const T x, const T y) { return T(2.0) * (y + x); }
|
||||||
template <typename T> inline T func02(const T& x, const T& y) { return (T(2.0) * y + T(2.0) * x); }
|
template <typename T> inline T func02(const T x, const T y) { return (T(2.0) * y + T(2.0) * x); }
|
||||||
template <typename T> inline T func03(const T& x, const T& y) { return (y + x / y) * (x - y / x); }
|
template <typename T> inline T func03(const T x, const T y) { return (y + x / y) * (x - y / x); }
|
||||||
template <typename T> inline T func04(const T& x, const T& y) { return x / ((x + y) * (x - y)) / y; }
|
template <typename T> inline T func04(const T x, const T y) { return x / ((x + y) * (x - y)) / y; }
|
||||||
template <typename T> inline T func05(const T& x, const T& y) { return T(1.0) - ((x * y) + (y / x)) - T(3.0); }
|
template <typename T> inline T func05(const T x, const T y) { return T(1.0) - ((x * y) + (y / x)) - T(3.0); }
|
||||||
template <typename T> inline T func06(const T& x, const T& y) { return (1.1*pow(x,T(1.0))+2.2*pow(y,T(2.0))-3.3*pow(x,T(3.0))+4.4*pow(y,T(15.0))-5.5*pow(x,T(23.0))+6.6*pow(y,T(55.0))); }
|
template <typename T> inline T func06(const T x, const T y) { return (1.1*pow(x,T(1.0))+2.2*pow(y,T(2.0))-3.3*pow(x,T(3.0))+4.4*pow(y,T(15.0))-5.5*pow(x,T(23.0))+6.6*pow(y,T(55.0))); }
|
||||||
template <typename T> inline T func07(const T& x, const T& y) { return std::sin(T(2.0) * x) + std::cos(pi / y); }
|
template <typename T> inline T func07(const T x, const T y) { return std::sin(T(2.0) * x) + std::cos(pi / y); }
|
||||||
template <typename T> inline T func08(const T& x, const T& y) { return T(1.0) - std::sin(2.0 * x) + std::cos(pi / y); }
|
template <typename T> inline T func08(const T x, const T y) { return T(1.0) - std::sin(2.0 * x) + std::cos(pi / y); }
|
||||||
template <typename T> inline T func09(const T& x, const T& y) { return std::sqrt(T(1.0) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(3.0)); }
|
template <typename T> inline T func09(const T x, const T y) { return std::sqrt(T(1.0) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(3.0)); }
|
||||||
template <typename T> inline T func10(const T& x, const T& y) { return (std::pow(x,T(2.0)) / std::sin(T(2.0) * pi / y)) -x / T(2.0); }
|
template <typename T> inline T func10(const T x, const T y) { return (std::pow(x,T(2.0)) / std::sin(T(2.0) * pi / y)) -x / T(2.0); }
|
||||||
template <typename T> inline T func11(const T& x, const T& y) { return clamp(T(-1.0), std::sin(T(2.0) * pi * x) + std::cos(y / T(2.0) * pi), + T(1.0)); }
|
template <typename T> inline T func11(const T x, const T y) { return (x + (std::cos(y - std::sin(2 / x * pi)) - std::sin(x - std::cos(2 * y / pi))) - y); }
|
||||||
template <typename T> inline T func12(const T& x, const T& y) { return std::max(T(3.33), std::min(sqrt(T(1.0) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(3.0)), T(1.11))); }
|
template <typename T> inline T func12(const T x, const T y) { return clamp(T(-1.0), std::sin(T(2.0) * pi * x) + std::cos(y / T(2.0) * pi), + T(1.0)); }
|
||||||
template <typename T> inline T func13(const T& x, const T& y) { return ((avg(x,y) <= x + y) ? x - y : x * y) + T(2.0) * pi / x; }
|
template <typename T> inline T func13(const T x, const T y) { return std::max(T(3.33), std::min(sqrt(T(1.0) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(3.0)), T(1.11))); }
|
||||||
|
template <typename T> inline T func14(const T x, const T y) { return ((avg(x,y) <= x + y) ? x - y : x * y) + T(2.0) * pi / x; }
|
||||||
|
|
||||||
template <typename T, typename NativeFunction>
|
template <typename T, typename NativeFunction>
|
||||||
void run_native_benchmark(T& x, T& y, NativeFunction f, const std::string& expr_string)
|
void run_native_benchmark(T& x, T& y, NativeFunction f, const std::string& expr_string)
|
||||||
|
@ -142,10 +146,13 @@ void run_native_benchmark(T& x, T& y, NativeFunction f, const std::string& expr_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timer.stop();
|
timer.stop();
|
||||||
|
if (T(0.0) != total)
|
||||||
printf("[native] Total Time:%12.8f Rate:%14.3fevals/sec Expression: %s\n",
|
printf("[native] Total Time:%12.8f Rate:%14.3fevals/sec Expression: %s\n",
|
||||||
timer.time(),
|
timer.time(),
|
||||||
count / timer.time(),
|
count / timer.time(),
|
||||||
expr_string.c_str());
|
expr_string.c_str());
|
||||||
|
else
|
||||||
|
std::cerr << "Error - expression: " << expr_string << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -229,6 +236,7 @@ int main()
|
||||||
run_native_benchmark(x,y,func11<double>,expression_list[11]);
|
run_native_benchmark(x,y,func11<double>,expression_list[11]);
|
||||||
run_native_benchmark(x,y,func12<double>,expression_list[12]);
|
run_native_benchmark(x,y,func12<double>,expression_list[12]);
|
||||||
run_native_benchmark(x,y,func13<double>,expression_list[13]);
|
run_native_benchmark(x,y,func13<double>,expression_list[13]);
|
||||||
|
run_native_benchmark(x,y,func14<double>,expression_list[14]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -608,6 +608,26 @@ static const test_t test_list[] =
|
||||||
test_t("if((1.0+1.1) >= (2.0+1.2), 3.3, 4.4)",4.4),
|
test_t("if((1.0+1.1) >= (2.0+1.2), 3.3, 4.4)",4.4),
|
||||||
test_t("if(((1.0 + 2.0) == 3.0) and ((4.0 + 5.0) < 9.0),1,2)",2.0),
|
test_t("if(((1.0 + 2.0) == 3.0) and ((4.0 + 5.0) < 9.0),1,2)",2.0),
|
||||||
test_t("(3.0 - 1.0 - 2.0) == ((3.0 - 1.0) - 2.0)",1.0),
|
test_t("(3.0 - 1.0 - 2.0) == ((3.0 - 1.0) - 2.0)",1.0),
|
||||||
|
test_t("true == true",1.0),
|
||||||
|
test_t("false == false",1.0),
|
||||||
|
test_t("true != false",1.0),
|
||||||
|
test_t("false != true",1.0),
|
||||||
|
test_t("(1 < 2) == true",1.0),
|
||||||
|
test_t("(1 > 2) == false",1.0),
|
||||||
|
test_t("true == (1 < 2)",1.0),
|
||||||
|
test_t("false == (1 > 2)",1.0),
|
||||||
|
test_t("(1 > 2) != true",1.0),
|
||||||
|
test_t("(1 < 2) != false",1.0),
|
||||||
|
test_t("true != (1 > 2)",1.0),
|
||||||
|
test_t("false != (1 < 2)",1.0),
|
||||||
|
test_t("(true and true) == true",1.0),
|
||||||
|
test_t("(false and false) == false",1.0),
|
||||||
|
test_t("(true or true) == true",1.0),
|
||||||
|
test_t("(false or false) == false",1.0),
|
||||||
|
test_t("(true and false) == false",1.0),
|
||||||
|
test_t("(false and true) == false",1.0),
|
||||||
|
test_t("(true or false) == true",1.0),
|
||||||
|
test_t("(false or true) == true",1.0),
|
||||||
test_t("clamp(-1,1,+1)",1.0),
|
test_t("clamp(-1,1,+1)",1.0),
|
||||||
test_t("clamp(-1,-1.5,+1.0)",-1.0),
|
test_t("clamp(-1,-1.5,+1.0)",-1.0),
|
||||||
test_t("clamp(-1,+1.5,+1.0)",+1.0),
|
test_t("clamp(-1,+1.5,+1.0)",+1.0),
|
||||||
|
@ -737,6 +757,12 @@ inline bool test_expression(const std::string& expression_string, const T& expec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!exprtk::expression_helper<T>::is_head_constant(expression))
|
||||||
|
{
|
||||||
|
std::cout << "test_expression() - Error: Expression did not compile to a constant!\tExpression: " << expression_string << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
T result = expression.value();
|
T result = expression.value();
|
||||||
if (not_equal<T>(result,expected_result))
|
if (not_equal<T>(result,expected_result))
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,8 @@ operations, functions and processes:
|
||||||
(4) Equalities &
|
(4) Equalities &
|
||||||
Inequalities: =, ==, <>, !=, <, <=, >, >=,
|
Inequalities: =, ==, <>, !=, <, <=, >, >=,
|
||||||
|
|
||||||
(5) Boolean logic: and, or, xor, not, nand, nor, shr, shl
|
(5) Boolean logic: and, or, xor, not, nand, nor, shr, shl, true,
|
||||||
|
false
|
||||||
|
|
||||||
(6) Conditional &
|
(6) Conditional &
|
||||||
Loop statement: if-then-else, while
|
Loop statement: if-then-else, while
|
||||||
|
|
Loading…
Reference in New Issue