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

This commit is contained in:
Arash Partow 2012-05-12 08:18:14 +10:00
parent 4351c7b0a1
commit b1a89fc96a
3 changed files with 631 additions and 181 deletions

View File

@ -1562,7 +1562,24 @@ namespace exprtk
e_sf39 = 1039,
e_sf40 = 1040,
e_sf41 = 1041,
e_sf42 = 1042
e_sf42 = 1042,
e_sf43 = 1043,
e_sf44 = 1044,
e_sf45 = 1045,
e_sf46 = 1046,
e_sf47 = 1047,
e_sf48 = 1048,
e_sf49 = 1049,
e_sf50 = 1050,
e_sf51 = 1051,
e_sf52 = 1052,
e_sf53 = 1053,
e_sf54 = 1054,
e_sf55 = 1055,
e_sf56 = 1056,
e_sf57 = 1057,
e_sf58 = 1058
};
namespace numeric
@ -1983,18 +2000,21 @@ namespace exprtk
#endif
}
template <std::size_t N, typename T>
inline void cleanup_branches(std::pair<expression_node<T>*,bool> (&branch)[N])
template <typename T, std::size_t N>
struct cleanup_branches
{
for (std::size_t i = 0; i < N; ++i)
static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
{
if (branch[i].first && branch[i].second)
for (std::size_t i = 0; i < N; ++i)
{
delete branch[i].first;
branch[i].first = 0;
if (branch[i].first && branch[i].second)
{
delete branch[i].first;
branch[i].first = 0;
}
}
}
}
};
template <typename T>
class binary_node : public expression_node<T>
@ -2014,7 +2034,7 @@ namespace exprtk
~binary_node()
{
cleanup_branches<2>(branch_);
cleanup_branches<T,2>::execute(branch_);
}
inline T value() const
@ -2069,7 +2089,7 @@ namespace exprtk
~trinary_node()
{
cleanup_branches<3>(branch_);
cleanup_branches<T,3>::execute(branch_);
}
inline T value() const
@ -2121,7 +2141,7 @@ namespace exprtk
~quaternary_node()
{
cleanup_branches<4>(branch_);
cleanup_branches<T,4>::execute(branch_);
}
inline T value() const
@ -2173,7 +2193,7 @@ namespace exprtk
~quinary_node()
{
cleanup_branches<5>(branch_);
cleanup_branches<T,5>::execute(branch_);
}
inline T value() const
@ -2227,7 +2247,7 @@ namespace exprtk
~senary_node()
{
cleanup_branches<6>(branch_);
cleanup_branches<T,6>::execute(branch_);
}
inline T value() const
@ -2456,6 +2476,9 @@ namespace exprtk
std::string stringvar_node<T>::null_value = std::string("");
#endif
template <typename T, std::size_t N> inline T axn(T a, T x) { return a * exprtk::details::numeric::fast_exp<T,N>::result(x); } // a*x^n
template <typename T, std::size_t N> inline T axnb(T a, T x, T b) { return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; } // a*x^n+b
template <typename T> struct sf00_op { static inline T process(const T& x, const T& y, const T& z) { return (x + y) / z; } };
template <typename T> struct sf01_op { static inline T process(const T& x, const T& y, const T& z) { return (x + y) * z; } };
template <typename T> struct sf02_op { static inline T process(const T& x, const T& y, const T& z) { return (x - y) / z; } };
@ -2474,31 +2497,47 @@ namespace exprtk
template <typename T> struct sf15_op { static inline T process(const T& x, const T& y, const T& z) { return z / (x / y); } };
template <typename T> struct sf16_op { static inline T process(const T& x, const T& y, const T& z) { return z - (x / y); } };
template <typename T> struct sf17_op { static inline T process(const T& x, const T& y, const T& z) { return z - (x / y); } };
template <typename T> struct sf18_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) / z); } };
template <typename T> struct sf19_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) * z); } };
template <typename T> struct sf20_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) / z); } };
template <typename T> struct sf21_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) * z); } };
template <typename T> struct sf22_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) / z); } };
template <typename T> struct sf23_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) * z); } };
template <typename T> struct sf24_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) + z); } };
template <typename T> struct sf25_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) / z); } };
template <typename T> struct sf26_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) * z); } };
template <typename T> struct sf27_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) / z); } };
template <typename T> struct sf28_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) * z); } };
template <typename T> struct sf29_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) / z); } };
template <typename T> struct sf30_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) * z); } };
template <typename T> struct sf31_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) / z); } };
template <typename T> struct sf32_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) * z); } };
template <typename T> struct sf33_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) / z); } };
template <typename T> struct sf34_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) * z); } };
template <typename T> struct sf35_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) * z) - w; } };
template <typename T> struct sf36_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) * z) - w; } };
template <typename T> struct sf37_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) * z) - w; } };
template <typename T> struct sf38_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) * z) - w; } };
template <typename T> struct sf39_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) / z) - w; } };
template <typename T> struct sf40_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) / z) - w; } };
template <typename T> struct sf41_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) / z) - w; } };
template <typename T> struct sf42_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) / z) - w; } };
template <typename T> struct sf18_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,2>(x,y,z); } }; //x * y^2 + z
template <typename T> struct sf19_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,3>(x,y,z); } }; //x * y^3 + z
template <typename T> struct sf20_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,4>(x,y,z); } }; //x * y^4 + z
template <typename T> struct sf21_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,5>(x,y,z); } }; //x * y^5 + z
template <typename T> struct sf22_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,6>(x,y,z); } }; //x * y^6 + z
template <typename T> struct sf23_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,7>(x,y,z); } }; //x * y^7 + z
template <typename T> struct sf24_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,8>(x,y,z); } }; //x * y^8 + z
template <typename T> struct sf25_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,9>(x,y,z); } }; //x * y^9 + z
template <typename T> struct sf26_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) / z); } };
template <typename T> struct sf27_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) * z); } };
template <typename T> struct sf28_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) / z); } };
template <typename T> struct sf29_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) * z); } };
template <typename T> struct sf30_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) / z); } };
template <typename T> struct sf31_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) * z); } };
template <typename T> struct sf32_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) + z); } };
template <typename T> struct sf33_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) / z); } };
template <typename T> struct sf34_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) * z); } };
template <typename T> struct sf35_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) / z); } };
template <typename T> struct sf36_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) * z); } };
template <typename T> struct sf37_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) / z); } };
template <typename T> struct sf38_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) * z); } };
template <typename T> struct sf39_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) / z); } };
template <typename T> struct sf40_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) * z); } };
template <typename T> struct sf41_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) / z); } };
template <typename T> struct sf42_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) * z); } };
template <typename T> struct sf43_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) * z) - w; } };
template <typename T> struct sf44_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) * z) - w; } };
template <typename T> struct sf45_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) * z) - w; } };
template <typename T> struct sf46_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) * z) - w; } };
template <typename T> struct sf47_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) / z) - w; } };
template <typename T> struct sf48_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) / z) - w; } };
template <typename T> struct sf49_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) / z) - w; } };
template <typename T> struct sf50_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) / z) - w; } };
template <typename T> struct sf51_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,2>(x,y) + axn<T,2>(z,w); } }; //x*y^2+z*w^2
template <typename T> struct sf52_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,3>(x,y) + axn<T,3>(z,w); } }; //x*y^3+z*w^3
template <typename T> struct sf53_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,4>(x,y) + axn<T,4>(z,w); } }; //x*y^4+z*w^4
template <typename T> struct sf54_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,5>(x,y) + axn<T,5>(z,w); } }; //x*y^5+z*w^5
template <typename T> struct sf55_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,6>(x,y) + axn<T,6>(z,w); } }; //x*y^6+z*w^6
template <typename T> struct sf56_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,7>(x,y) + axn<T,7>(z,w); } }; //x*y^7+z*w^7
template <typename T> struct sf57_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,8>(x,y) + axn<T,8>(z,w); } }; //x*y^8+z*w^8
template <typename T> struct sf58_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,9>(x,y) + axn<T,9>(z,w); } }; //x*y^9+z*w^9
template <typename T, typename SpecialFunction>
class sf3_node : public trinary_node<T>
@ -2577,70 +2616,192 @@ namespace exprtk
}
};
template <typename T, typename IFunction>
class function_node : public expression_node<T>
template <typename T, typename IFunction, std::size_t N>
class function_N_node : public expression_node<T>
{
public:
//function of N paramters.
typedef expression_node<T>* expression_ptr;
typedef std::pair<expression_ptr,bool> branch_t;
typedef IFunction ifunction;
static const std::size_t N = 10;
function_node(ifunction* func)
: function(func)
function_N_node(ifunction* func)
: function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
parameter_count_(func->param_count)
{}
~function_node()
~function_N_node()
{
cleanup_branches<N>(branch_);
cleanup_branches<T,N>::execute(branch_);
}
template <std::size_t NumBranches>
bool init_branches(expression_ptr (&b)[NumBranches])
{
for (std::size_t i = 0; i < NumBranches; ++i)
//Needed for incompetent and broken msvc compiler versions
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127)
#endif
if (N != NumBranches)
return false;
else
{
if (b[i])
branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
else
return false;
for (std::size_t i = 0; i < NumBranches; ++i)
{
if (b[i])
branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
else
return false;
}
return true;
}
return true;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
inline bool operator <(const function_node<T,IFunction>& fn) const
inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
{
return this < (&fn);
}
inline T value() const
{
T v[N];
if (function->param_count)
//Needed for incompetent and broken msvc compiler versions
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127)
#endif
if ((0 == function_) || (0 == N))
return std::numeric_limits<T>::quiet_NaN();
else
{
for (std::size_t i = 0; i < function->param_count; ++i)
T v[N];
evaluate_branches<T,N>::execute(v,branch_);
return invoke<T,N>::execute(*function_,v);
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
template <typename T_, std::size_t BranchCount>
struct evaluate_branches
{
static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
{
for (std::size_t i = 0; i < BranchCount; ++i)
{
v[i] = branch_[i].first->value();
}
switch (function->param_count)
{
case 1 : return (*function)(v[0]);
case 2 : return (*function)(v[0],v[1]);
case 3 : return (*function)(v[0],v[1],v[2]);
case 4 : return (*function)(v[0],v[1],v[2],v[3]);
case 5 : return (*function)(v[0],v[1],v[2],v[3],v[4]);
case 6 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5]);
case 7 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5],v[6]);
case 8 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]);
case 9 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]);
case 10 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]);
default : return std::numeric_limits<T>::quiet_NaN();
v[i] = b[i].first->value();
}
}
};
template <typename T_>
struct evaluate_branches <T_,5>
{
static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
{
v[0] = b[0].first->value();
v[1] = b[1].first->value();
v[2] = b[2].first->value();
v[3] = b[3].first->value();
v[4] = b[4].first->value();
}
};
template <typename T_>
struct evaluate_branches <T_,4>
{
static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
{
v[0] = b[0].first->value();
v[1] = b[1].first->value();
v[2] = b[2].first->value();
v[3] = b[3].first->value();
}
};
template <typename T_>
struct evaluate_branches <T_,3>
{
static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
{
v[0] = b[0].first->value();
v[1] = b[1].first->value();
v[2] = b[2].first->value();
}
};
template <typename T_>
struct evaluate_branches <T_,2>
{
static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
{
v[0] = b[0].first->value();
v[1] = b[1].first->value();
}
};
template <typename T_>
struct evaluate_branches <T_,1>
{
static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
{
v[0] = b[0].first->value();
}
};
template <typename T_, std::size_t ParamCount>
struct invoke { static inline T execute(ifunction*, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
template <typename T_> struct invoke<T_,10> { static inline T_ execute(ifunction& f, T_ (&v)[10]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); } };
template <typename T_> struct invoke<T_, 9> { static inline T_ execute(ifunction& f, T_ (&v)[ 9]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); } };
template <typename T_> struct invoke<T_, 8> { static inline T_ execute(ifunction& f, T_ (&v)[ 8]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); } };
template <typename T_> struct invoke<T_, 7> { static inline T_ execute(ifunction& f, T_ (&v)[ 7]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); } };
template <typename T_> struct invoke<T_, 6> { static inline T_ execute(ifunction& f, T_ (&v)[ 6]) { return f(v[0],v[1],v[2],v[3],v[4],v[5]); } };
template <typename T_> struct invoke<T_, 5> { static inline T_ execute(ifunction& f, T_ (&v)[ 5]) { return f(v[0],v[1],v[2],v[3],v[4]); } };
template <typename T_> struct invoke<T_, 4> { static inline T_ execute(ifunction& f, T_ (&v)[ 4]) { return f(v[0],v[1],v[2],v[3]); } };
template <typename T_> struct invoke<T_, 3> { static inline T_ execute(ifunction& f, T_ (&v)[ 3]) { return f(v[0],v[1],v[2]); } };
template <typename T_> struct invoke<T_, 2> { static inline T_ execute(ifunction& f, T_ (&v)[ 2]) { return f(v[0],v[1]); } };
template <typename T_> struct invoke<T_, 1> { static inline T_ execute(ifunction& f, T_ (&v)[ 1]) { return f(v[0]); } };
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_function;
}
private:
ifunction* function_;
std::size_t parameter_count_;
branch_t branch_[N];
};
template <typename T, typename IFunction>
class function_N_node<T,IFunction,0> : public expression_node<T>
{
public:
typedef expression_node<T>* expression_ptr;
typedef IFunction ifunction;
function_N_node(ifunction* func)
: function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
{}
inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
{
return this < (&fn);
}
inline T value() const
{
if (0 == function_)
return std::numeric_limits<T>::quiet_NaN();
else
return (*function)();
return (*function_)();
}
inline typename expression_node<T>::node_type type() const
@ -2650,8 +2811,8 @@ namespace exprtk
private:
ifunction* function;
branch_t branch_[N];
ifunction* function_;
std::size_t parameter_count_;
};
template <typename T>
@ -3843,7 +4004,7 @@ namespace exprtk
}
};
template<typename Type, typename RawType>
template <typename Type, typename RawType>
struct type_store
{
typedef typename details::variable_node<T> variable_node_t;
@ -4745,6 +4906,7 @@ namespace exprtk
};
typedef ifunction <T> F;
typedef ifunction <T> ifunction_t;
typedef details::expression_node <T> expression_node_t;
typedef details::literal_node <T> literal_node_t;
typedef details::string_literal_node<T> string_literal_node_t;
@ -4761,7 +4923,6 @@ namespace exprtk
typedef details::stringvar_node <T> stringvar_node_t;
#endif
typedef details::assignment_node <T> assignment_node_t;
typedef details::function_node <T,F> function_node_t;
typedef details::token <T> token_t;
typedef expression_node_t* expression_node_ptr;
@ -5139,10 +5300,10 @@ namespace exprtk
{
//Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
const details::operator_type opt_type = details::operator_type(id + 1000);
const std::size_t NumberOfParameters = (id < (details::e_sf18 - 1000)) ? 3 : 4;
const std::size_t NumberOfParameters = (id < (details::e_sf26 - 1000)) ? 3 : 4;
expression_node_ptr branch3[3];
expression_node_ptr branch4[4];
expression_node_ptr* branch = (id < (details::e_sf18 - 1000)) ? &branch3[0] : &branch4[0];
expression_node_ptr* branch = (id < (details::e_sf26 - 1000)) ? &branch3[0] : &branch4[0];
expression_node_ptr result = 0;
std::fill_n(branch3,3,reinterpret_cast<expression_node_ptr>(0));
std::fill_n(branch4,4,reinterpret_cast<expression_node_ptr>(0));
@ -5772,6 +5933,14 @@ namespace exprtk
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
}
@ -5784,14 +5953,6 @@ namespace exprtk
switch (operation)
{
#define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<details::sf4_node<Type,op1<Type> > >(operation,branch);
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)
case_stmt(details::e_sf26,details::sf26_op)
case_stmt(details::e_sf27,details::sf27_op)
case_stmt(details::e_sf28,details::sf28_op)
@ -5809,15 +5970,33 @@ namespace exprtk
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
}
}
template <std::size_t N>
inline expression_node_ptr function(typename function_node_t::ifunction* f, expression_node_ptr (&b)[N])
inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
{
expression_node_ptr result = synthesize_expression<function_node_t,N>(f,b);
typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
if (0 == result)
return error_node();
else
@ -5829,7 +6008,7 @@ namespace exprtk
return error_node();
else if (N != f->param_count)
return error_node();
function_node_t* func_node_ptr = dynamic_cast<function_node_t*>(result);
function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(result);
if (func_node_ptr)
{
if (func_node_ptr->init_branches(b))
@ -5842,9 +6021,10 @@ namespace exprtk
}
}
inline expression_node_ptr function(typename function_node_t::ifunction* f)
inline expression_node_ptr function(ifunction_t* f)
{
return node_allocator_->allocate<function_node_t>(f);
typedef typename details::function_N_node<T,ifunction_t,0> function_N_node_t;
return node_allocator_->allocate<function_N_node_t>(f);
}
private:
@ -6616,9 +6796,10 @@ namespace exprtk
{
if (all_nodes_valid<N>(branch))
{
typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
//Attempt simple constant folding optimization.
expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
dynamic_cast<function_node_t*>(expression_point)->init_branches(branch);
dynamic_cast<function_N_node_t*>(expression_point)->init_branches(branch);
if (is_constant_foldable<N>(branch))
{
Type v = expression_point->value();
@ -6743,11 +6924,19 @@ namespace exprtk
//Check for certain illegal sequences of characters.
std::stack<char> bracket_stack;
bool in_string = false;
for (std::size_t i = 0; i < (expression_string.size() - 1); ++i)
{
char c0 = expression_string[i];
char c1 = expression_string[i + 1];
if (details::is_invalid(c0))
if ('\'' == c0)
{
in_string = !in_string;
continue;
}
else if (in_string)
continue;
else if (details::is_invalid(c0))
{
set_error(std::string("parser::validate_expression() - invalid character: ") + c0);
return false;
@ -7022,6 +7211,175 @@ namespace exprtk
return false;
}
template <typename T, std::size_t N>
class polynomial : public ifunction<T>
{
private:
template <typename Type, std::size_t NumberOfCoefficients>
struct poly_impl { };
template <typename Type>
struct poly_impl <Type,9>
{
static inline T evaluate(const Type x,
const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
{
//p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
}
};
template <typename Type>
struct poly_impl <Type,8>
{
static inline T evaluate(const Type x,
const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
const Type c3, const Type c2, const Type c1, const Type c0)
{
//p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
}
};
template <typename Type>
struct poly_impl <Type,7>
{
static inline T evaluate(const Type x,
const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
const Type c2, const Type c1, const Type c0)
{
//p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
}
};
template <typename Type>
struct poly_impl <Type,6>
{
static inline T evaluate(const Type x,
const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
const Type c1, const Type c0)
{
//p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
}
};
template <typename Type>
struct poly_impl <Type,5>
{
static inline T evaluate(const Type x,
const Type c5, const Type c4, const Type c3, const Type c2,
const Type c1, const Type c0)
{
//p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
}
};
template <typename Type>
struct poly_impl <Type,4>
{
static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
{
//p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
}
};
template <typename Type>
struct poly_impl <Type,3>
{
static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
{
//p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0
return (((c3 * x + c2) * x + c1) * x + c0);
}
};
template <typename Type>
struct poly_impl <Type,2>
{
static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
{
//p(x) = c_2x^2 + c_1x^1 + c_0
return ((c2 * x + c1) * x + c0);
}
};
template <typename Type>
struct poly_impl <Type,1>
{
static inline T evaluate(const Type x, const Type c1, const Type c0)
{
//p(x) = c_1x^1 + c_0
return (c1 * x + c0);
}
};
public:
polynomial() : exprtk::ifunction<T>(N) {}
inline virtual T operator()(const T& x, const T& c1, const T& c0)
{
return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN());
}
inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0)
{
return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
}
inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
{
return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
}
inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
{
return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
}
inline virtual T operator()(const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
{
return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
}
inline virtual T operator()(const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
{
return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
}
inline virtual T operator()(const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
{
return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
}
inline virtual T operator()(const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
{
return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
}
inline virtual T operator()()
{
return std::numeric_limits<T>::quiet_NaN();
}
inline virtual T operator()(const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
inline virtual T operator()(const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
};
template <typename T>
inline bool pgo_primer()
{
@ -7326,7 +7684,7 @@ namespace exprtk
{
static const char* library = "Mathematical Expression Toolkit";
static const char* version = "2.71828182845904523536028";
static const char* date = "20120408";
static const char* date = "20120505";
static inline std::string data()
{

View File

@ -635,31 +635,47 @@ static const test_t test_list[] =
test_t("equal($f15(1.1,2.2,3.3),(3.3/(1.1/2.2)))",1.0),
test_t("equal($f16(1.1,2.2,3.3),(3.3-(1.1/2.2)))",1.0),
test_t("equal($f17(1.1,2.2,3.3),(3.3-(1.1/2.2)))",1.0),
test_t("equal($f18(1.1,2.2,3.3,4.4),(4.4+((1.1+2.2)/3.3)))",1.0),
test_t("equal($f19(1.1,2.2,3.3,4.4),(4.4+((1.1+2.2)*3.3)))",1.0),
test_t("equal($f20(1.1,2.2,3.3,4.4),(4.4+((1.1-2.2)/3.3)))",1.0),
test_t("equal($f21(1.1,2.2,3.3,4.4),(4.4+((1.1-2.2)*3.3)))",1.0),
test_t("equal($f22(1.1,2.2,3.3,4.4),(4.4+((1.1*2.2)/3.3)))",1.0),
test_t("equal($f23(1.1,2.2,3.3,4.4),(4.4+((1.1*2.2)*3.3)))",1.0),
test_t("equal($f24(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)+3.3)))",1.0),
test_t("equal($f25(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)/3.3)))",1.0),
test_t("equal($f26(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)*3.3)))",1.0),
test_t("equal($f27(1.1,2.2,3.3,4.4),(4.4-((1.1+2.2)/3.3)))",1.0),
test_t("equal($f28(1.1,2.2,3.3,4.4),(4.4-((1.1+2.2)*3.3)))",1.0),
test_t("equal($f29(1.1,2.2,3.3,4.4),(4.4-((1.1-2.2)/3.3)))",1.0),
test_t("equal($f30(1.1,2.2,3.3,4.4),(4.4-((1.1-2.2)*3.3)))",1.0),
test_t("equal($f31(1.1,2.2,3.3,4.4),(4.4-((1.1*2.2)/3.3)))",1.0),
test_t("equal($f32(1.1,2.2,3.3,4.4),(4.4-((1.1*2.2)*3.3)))",1.0),
test_t("equal($f33(1.1,2.2,3.3,4.4),(4.4-((1.1/2.2)/3.3)))",1.0),
test_t("equal($f34(1.1,2.2,3.3,4.4),(4.4-((1.1/2.2)*3.3)))",1.0),
test_t("equal($f35(1.1,2.2,3.3,4.4),(((1.1+2.2)*3.3)-4.4))",1.0),
test_t("equal($f36(1.1,2.2,3.3,4.4),(((1.1-2.2)*3.3)-4.4))",1.0),
test_t("equal($f37(1.1,2.2,3.3,4.4),(((1.1*2.2)*3.3)-4.4))",1.0),
test_t("equal($f38(1.1,2.2,3.3,4.4),(((1.1/2.2)*3.3)-4.4))",1.0),
test_t("equal($f39(1.1,2.2,3.3,4.4),(((1.1+2.2)/3.3)-4.4))",1.0),
test_t("equal($f40(1.1,2.2,3.3,4.4),(((1.1-2.2)/3.3)-4.4))",1.0),
test_t("equal($f41(1.1,2.2,3.3,4.4),(((1.1*2.2)/3.3)-4.4))",1.0),
test_t("equal($f42(1.1,2.2,3.3,4.4),(((1.1/2.2)/3.3)-4.4))",1.0),
test_t("equal($f18(1.1,2.2,3.3),(1.1*2.2^2+3.3))",1.0),
test_t("equal($f19(1.1,2.2,3.3),(1.1*2.2^3+3.3))",1.0),
test_t("equal($f20(1.1,2.2,3.3),(1.1*2.2^4+3.3))",1.0),
test_t("equal($f21(1.1,2.2,3.3),(1.1*2.2^5+3.3))",1.0),
test_t("equal($f22(1.1,2.2,3.3),(1.1*2.2^6+3.3))",1.0),
test_t("equal($f23(1.1,2.2,3.3),(1.1*2.2^7+3.3))",1.0),
test_t("equal($f24(1.1,2.2,3.3),(1.1*2.2^8+3.3))",1.0),
test_t("equal($f25(1.1,2.2,3.3),(1.1*2.2^9+3.3))",1.0),
test_t("equal($f26(1.1,2.2,3.3,4.4),(4.4+((1.1+2.2)/3.3)))",1.0),
test_t("equal($f27(1.1,2.2,3.3,4.4),(4.4+((1.1+2.2)*3.3)))",1.0),
test_t("equal($f28(1.1,2.2,3.3,4.4),(4.4+((1.1-2.2)/3.3)))",1.0),
test_t("equal($f29(1.1,2.2,3.3,4.4),(4.4+((1.1-2.2)*3.3)))",1.0),
test_t("equal($f30(1.1,2.2,3.3,4.4),(4.4+((1.1*2.2)/3.3)))",1.0),
test_t("equal($f31(1.1,2.2,3.3,4.4),(4.4+((1.1*2.2)*3.3)))",1.0),
test_t("equal($f32(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)+3.3)))",1.0),
test_t("equal($f33(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)/3.3)))",1.0),
test_t("equal($f34(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)*3.3)))",1.0),
test_t("equal($f35(1.1,2.2,3.3,4.4),(4.4-((1.1+2.2)/3.3)))",1.0),
test_t("equal($f36(1.1,2.2,3.3,4.4),(4.4-((1.1+2.2)*3.3)))",1.0),
test_t("equal($f37(1.1,2.2,3.3,4.4),(4.4-((1.1-2.2)/3.3)))",1.0),
test_t("equal($f38(1.1,2.2,3.3,4.4),(4.4-((1.1-2.2)*3.3)))",1.0),
test_t("equal($f39(1.1,2.2,3.3,4.4),(4.4-((1.1*2.2)/3.3)))",1.0),
test_t("equal($f40(1.1,2.2,3.3,4.4),(4.4-((1.1*2.2)*3.3)))",1.0),
test_t("equal($f41(1.1,2.2,3.3,4.4),(4.4-((1.1/2.2)/3.3)))",1.0),
test_t("equal($f42(1.1,2.2,3.3,4.4),(4.4-((1.1/2.2)*3.3)))",1.0),
test_t("equal($f43(1.1,2.2,3.3,4.4),(((1.1+2.2)*3.3)-4.4))",1.0),
test_t("equal($f44(1.1,2.2,3.3,4.4),(((1.1-2.2)*3.3)-4.4))",1.0),
test_t("equal($f45(1.1,2.2,3.3,4.4),(((1.1*2.2)*3.3)-4.4))",1.0),
test_t("equal($f46(1.1,2.2,3.3,4.4),(((1.1/2.2)*3.3)-4.4))",1.0),
test_t("equal($f47(1.1,2.2,3.3,4.4),(((1.1+2.2)/3.3)-4.4))",1.0),
test_t("equal($f48(1.1,2.2,3.3,4.4),(((1.1-2.2)/3.3)-4.4))",1.0),
test_t("equal($f49(1.1,2.2,3.3,4.4),(((1.1*2.2)/3.3)-4.4))",1.0),
test_t("equal($f50(1.1,2.2,3.3,4.4),(((1.1/2.2)/3.3)-4.4))",1.0),
test_t("equal($f51(1.1,2.2,3.3,4.4),(1.1*2.2^2+3.3*4.4^2))",1.0),
test_t("equal($f52(1.1,2.2,3.3,4.4),(1.1*2.2^3+3.3*4.4^3))",1.0),
test_t("equal($f53(1.1,2.2,3.3,4.4),(1.1*2.2^4+3.3*4.4^4))",1.0),
test_t("equal($f54(1.1,2.2,3.3,4.4),(1.1*2.2^5+3.3*4.4^5))",1.0),
test_t("equal($f55(1.1,2.2,3.3,4.4),(1.1*2.2^6+3.3*4.4^6))",1.0),
test_t("equal($f56(1.1,2.2,3.3,4.4),(1.1*2.2^7+3.3*4.4^7))",1.0),
test_t("equal($f57(1.1,2.2,3.3,4.4),(1.1*2.2^8+3.3*4.4^8))",1.0),
test_t("equal($f58(1.1,2.2,3.3,4.4),(1.1*2.2^9+3.3*4.4^9))",1.0),
test_t("1+2+3+4+5+6+7+8+9+0",45.0),
test_t("1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0",45.0),
test_t("1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0 + 8.0 + 9.0 + 0.0",45.0),
@ -697,7 +713,9 @@ inline bool not_equal(const T& t1,
{
if (t1 != t1) return true;
if (t2 != t2) return true;
return std::abs(t1 - t2) > (std::max(T(1.0),std::max(std::abs(t1),std::abs(t2))) * epsilon);
T diff = std::abs(t1 - t2);
T eps_norm = (std::max(T(1.0),std::max(std::abs(t1),std::abs(t2))) * epsilon);
return diff > eps_norm;
}
template <typename T>
@ -746,7 +764,7 @@ inline bool run_test00()
return true;
}
template<typename T>
template <typename T>
struct test_xy
{
test_xy(std::string e, const T& v0, const T& v1, const T& r)
@ -924,7 +942,7 @@ inline bool run_test01()
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_xy<T>);
const std::size_t rounds = 1000;
const std::size_t rounds = 100;
for (std::size_t r = 0; r < rounds; ++r)
{
for (std::size_t i = 0; i < test_list_size; ++i)
@ -961,7 +979,7 @@ inline bool run_test01()
return true;
}
template<typename T>
template <typename T>
struct test_ab
{
test_ab(std::string e, const std::string& v0, const std::string& v1, const T& r)
@ -1040,12 +1058,19 @@ inline bool run_test02()
test_ab<T>("inrange(a,b,c)" ,"aaa","bbb",T(1.0)),
test_ab<T>("inrange(a,b,'ccc')" ,"aaa","bbb",T(1.0)),
test_ab<T>("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)),
test_ab<T>("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)),
test_ab<T>("'!@#$%^&*([{}])-=' != ')]}{[(*&^%$#@!'","","",T(1.0)),
test_ab<T>("('!@#$%^&*([{}])-=') != (')]}{[(*&^%$#@!')","","",T(1.0)),
test_ab<T>("{[('a')]} == [{('a')}]","","",T(1.0)),
test_ab<T>("{[('!@#$%^&*([{}])-=')]} != [{(')]}{[(*&^%$#@!')}]","","",T(1.0)),
test_ab<T>("'!@#$%^&*([{}])-=' == '!@#$%^&*([{}])-='","","",T(1.0)),
test_ab<T>("('!@#$%^&*([{}])-=') == ('!@#$%^&*([{}])-=')","","",T(1.0)),
test_ab<T>("{[('!@#$%^&*([{}])-=')]} == [{('!@#$%^&*([{}])-=')}]","","",T(1.0))
};
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>);
const std::size_t rounds = 10000;
const std::size_t rounds = 1000;
for (std::size_t r = 0; r < rounds; ++r)
{
for (std::size_t i = 0; i < test_list_size; ++i)
@ -1122,7 +1147,7 @@ inline bool run_test03()
static const std::size_t variable_list_size = sizeof(variable_list) / sizeof(std::string);
static const std::size_t rounds = 10000;
static const std::size_t rounds = 1000;
for (std::size_t r = 0; r < rounds; ++r)
{
@ -1409,46 +1434,62 @@ inline bool run_test08()
"equal($f15(x,y,z),(z/(x/y)))",
"equal($f16(x,y,z),(z-(x/y)))",
"equal($f17(x,y,z),(z-(x/y)))",
"equal($f18(x,y,z,w),(w+((x+y)/z)))",
"equal($f19(x,y,z,w),(w+((x+y)*z)))",
"equal($f20(x,y,z,w),(w+((x-y)/z)))",
"equal($f21(x,y,z,w),(w+((x-y)*z)))",
"equal($f22(x,y,z,w),(w+((x*y)/z)))",
"equal($f23(x,y,z,w),(w+((x*y)*z)))",
"equal($f24(x,y,z,w),(w+((x/y)+z)))",
"equal($f25(x,y,z,w),(w+((x/y)/z)))",
"equal($f26(x,y,z,w),(w+((x/y)*z)))",
"equal($f27(x,y,z,w),(w-((x+y)/z)))",
"equal($f28(x,y,z,w),(w-((x+y)*z)))",
"equal($f29(x,y,z,w),(w-((x-y)/z)))",
"equal($f30(x,y,z,w),(w-((x-y)*z)))",
"equal($f31(x,y,z,w),(w-((x*y)/z)))",
"equal($f32(x,y,z,w),(w-((x*y)*z)))",
"equal($f33(x,y,z,w),(w-((x/y)/z)))",
"equal($f34(x,y,z,w),(w-((x/y)*z)))",
"equal($f35(x,y,z,w),(((x+y)*z)-w))",
"equal($f36(x,y,z,w),(((x-y)*z)-w))",
"equal($f37(x,y,z,w),(((x*y)*z)-w))",
"equal($f38(x,y,z,w),(((x/y)*z)-w))",
"equal($f39(x,y,z,w),(((x+y)/z)-w))",
"equal($f40(x,y,z,w),(((x-y)/z)-w))",
"equal($f41(x,y,z,w),(((x*y)/z)-w))",
"equal($f42(x,y,z,w),(((x/y)/z)-w))",
"equal($f18(x,y,z),(x*y^2+z))",
"equal($f19(x,y,z),(x*y^3+z))",
"equal($f20(x,y,z),(x*y^4+z))",
"equal($f21(x,y,z),(x*y^5+z))",
"equal($f22(x,y,z),(x*y^6+z))",
"equal($f23(x,y,z),(x*y^7+z))",
"equal($f24(x,y,z),(x*y^8+z))",
"equal($f25(x,y,z),(x*y^9+z))",
"equal($f26(x,y,z,w),(w+((x+y)/z)))",
"equal($f27(x,y,z,w),(w+((x+y)*z)))",
"equal($f28(x,y,z,w),(w+((x-y)/z)))",
"equal($f29(x,y,z,w),(w+((x-y)*z)))",
"equal($f30(x,y,z,w),(w+((x*y)/z)))",
"equal($f31(x,y,z,w),(w+((x*y)*z)))",
"equal($f32(x,y,z,w),(w+((x/y)+z)))",
"equal($f33(x,y,z,w),(w+((x/y)/z)))",
"equal($f34(x,y,z,w),(w+((x/y)*z)))",
"equal($f35(x,y,z,w),(w-((x+y)/z)))",
"equal($f36(x,y,z,w),(w-((x+y)*z)))",
"equal($f37(x,y,z,w),(w-((x-y)/z)))",
"equal($f38(x,y,z,w),(w-((x-y)*z)))",
"equal($f39(x,y,z,w),(w-((x*y)/z)))",
"equal($f40(x,y,z,w),(w-((x*y)*z)))",
"equal($f41(x,y,z,w),(w-((x/y)/z)))",
"equal($f42(x,y,z,w),(w-((x/y)*z)))",
"equal($f43(x,y,z,w),(((x+y)*z)-w))",
"equal($f44(x,y,z,w),(((x-y)*z)-w))",
"equal($f45(x,y,z,w),(((x*y)*z)-w))",
"equal($f46(x,y,z,w),(((x/y)*z)-w))",
"equal($f47(x,y,z,w),(((x+y)/z)-w))",
"equal($f48(x,y,z,w),(((x-y)/z)-w))",
"equal($f49(x,y,z,w),(((x*y)/z)-w))",
"equal($f50(x,y,z,w),(((x/y)/z)-w))",
"equal($f51(x,y,z,w),(x*y^2+z*w^2))",
"equal($f52(x,y,z,w),(x*y^3+z*w^3))",
"equal($f53(x,y,z,w),(x*y^4+z*w^4))",
"equal($f54(x,y,z,w),(x*y^5+z*w^5))",
"equal($f55(x,y,z,w),(x*y^6+z*w^6))",
"equal($f56(x,y,z,w),(x*y^7+z*w^7))",
"equal($f57(x,y,z,w),(x*y^8+z*w^8))",
"equal($f58(x,y,z,w),(x*y^9+z*w^9))"
};
static const std::size_t expr_str_size = sizeof(expr_str) / sizeof(std::string);
static const std::size_t rounds = 1000;
static const std::size_t rounds = 100;
for (std::size_t i = 0; i < rounds; ++i)
{
for (std::size_t j = 0; j < expr_str_size; ++j)
{
typedef exprtk::expression<T> expression_t;
T x = T(1.0);
T y = T(2.0);
T z = T(3.0);
T w = T(4.0);
T u = T(5.0);
T x = T(1.123);
T y = T(2.123);
T z = T(3.123);
T w = T(4.123);
T u = T(5.123);
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable("x",x);
@ -1470,6 +1511,7 @@ inline bool run_test08()
expression.value();
}
}
return true;
}
@ -1487,7 +1529,7 @@ struct myfunc : public exprtk::ifunction<T>
template <typename T>
inline bool run_test09()
{
static const std::size_t rounds = 100000;
static const std::size_t rounds = 10000;
for (std::size_t i = 0; i < rounds; ++i)
{
typedef exprtk::expression<T> expression_t;
@ -1496,24 +1538,24 @@ inline bool run_test09()
"myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+"
"myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+"
"myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)+"
"myfunc0(sin(1*pi),y/2)+myfunc1(sin(1*pi),y/2)+"
"myfunc2(sin(1*pi),y/2)+myfunc3(sin(1*pi),y/2)+"
"myfunc4(sin(1*pi),y/2)+myfunc5(sin(1*pi),y/2)+"
"myfunc6(sin(1*pi),y/2)+myfunc7(sin(1*pi),y/2)+"
"myfunc8(sin(1*pi),y/2)+myfunc9(sin(1*pi),y/2)+"
"myfunc0(sin(x*pi),2/2)+myfunc1(sin(x*pi),2/2)+"
"myfunc2(sin(x*pi),2/2)+myfunc3(sin(x*pi),2/2)+"
"myfunc4(sin(x*pi),2/2)+myfunc5(sin(x*pi),2/2)+"
"myfunc6(sin(x*pi),2/2)+myfunc7(sin(x*pi),2/2)+"
"myfunc8(sin(x*pi),2/2)+myfunc9(sin(x*pi),2/2)+"
"myfunc0(sin(1*pi),2/2)+myfunc1(sin(1*pi),2/2)+"
"myfunc2(sin(1*pi),2/2)+myfunc3(sin(1*pi),2/2)+"
"myfunc4(sin(1*pi),2/2)+myfunc5(sin(1*pi),2/2)+"
"myfunc6(sin(1*pi),2/2)+myfunc7(sin(1*pi),2/2)+"
"myfunc8(sin(1*pi),2/2)+myfunc9(sin(1*pi),2/2)";
"myfunc0(sin(x*pi),y/2)+myfunc1(sin(x*pi),y/2)+"
"myfunc2(sin(x*pi),y/2)+myfunc3(sin(x*pi),y/2)+"
"myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+"
"myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+"
"myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)+"
"myfunc0(sin(x*pi),y/2)+myfunc1(sin(x*pi),y/2)+"
"myfunc2(sin(x*pi),y/2)+myfunc3(sin(x*pi),y/2)+"
"myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+"
"myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+"
"myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)+"
"myfunc0(sin(x*pi),y/2)+myfunc1(sin(x*pi),y/2)+"
"myfunc2(sin(x*pi),y/2)+myfunc3(sin(x*pi),y/2)+"
"myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+"
"myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+"
"myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)";
T x = T(1.0);
T y = T(2.0);
T x = T(1.0) + (i/10000.0);
T y = T(2.0) + (i/10000.0);
myfunc<T> mf;
exprtk::symbol_table<T> symbol_table;
@ -1541,7 +1583,7 @@ inline bool run_test09()
std::cout << "run_test09() - Error: " << parser.error() << "\tExpression: " << expression_string << std::endl;
return false;
}
const T pi = T(3.14159265358979323846);
const T pi = T(3.141592653589793238462);
T result = expression.value();
T expected = T(4.0) *
@ -1607,7 +1649,7 @@ inline bool run_test10()
}
};
static const std::size_t rounds = 1000;
static const std::size_t rounds = 100;
for (std::size_t r = 0; r < rounds; ++r)
{
@ -1964,7 +2006,7 @@ inline bool run_test10()
T y0 = T(0);
T z0 = T(0);
std::string expression_string = "(x0 + y0) / z0";
static const std::size_t rounds = 10000000;
static const std::size_t rounds = 1000000;
for (std::size_t i = 0; i < rounds; ++i)
{
expression_t expression0;
@ -2023,7 +2065,7 @@ inline bool run_test11()
expression_t expression;
expression.register_symbol_table(symbol_table);
static const std::size_t rounds = 100000;
static const std::size_t rounds = 10000;
for (std::size_t i = 0; i < rounds; ++i)
{

View File

@ -30,7 +30,7 @@ operations, functions and processes:
(6) Conditional &
Loop statement: if-then-else, while
(7) Assigment: :=, <-
(7) Assigment: :=
[EXAMPLE EXPRESSIONS]
@ -93,6 +93,56 @@ Expression Library can be found at:
(*) Comeau C++ Compiler (4.3+)
[SPECIAL FUNCTIONS]
The purpose of special functions in ExprTk is to provide compiler
generated equivalents of common mathematical expressions which can be
invoked by using the 'special function' syntax (eg: $f12(x,y,z) or
$f24(x,y,z,w)).
Special functions dramatically decrease the total evaluation time of
expressions which would otherwise have been written using the common
form by reducing the total number of nodes in the evaluation tree of
an expression and by also leveraging the compiler's ability to
correctly optimize such expressions for a given architecture.
3-Parameter 4-Parameter
| Prototype | Operation | | Prototype | Operation |
+------------+-------------+ +--------------+------------------+
sf00(x,y,z) | (x + y) / z sf26(x,y,z,w) | w + ((x + y) / z)
sf01(x,y,z) | (x + y) * z sf27(x,y,z,w) | w + ((x + y) * z)
sf02(x,y,z) | (x - y) / z sf28(x,y,z,w) | w + ((x - y) / z)
sf03(x,y,z) | (x - y) * z sf29(x,y,z,w) | w + ((x - y) * z)
sf04(x,y,z) | (x * y) + z sf30(x,y,z,w) | w + ((x * y) / z)
sf05(x,y,z) | (x * y) - z sf31(x,y,z,w) | w + ((x * y) * z)
sf06(x,y,z) | (x * y) / z sf32(x,y,z,w) | w + ((x / y) + z)
sf07(x,y,z) | (x * y) * z sf33(x,y,z,w) | w + ((x / y) / z)
sf08(x,y,z) | (x / y) + z sf34(x,y,z,w) | w + ((x / y) * z)
sf09(x,y,z) | (x / y) - z sf35(x,y,z,w) | w - ((x + y) / z)
sf10(x,y,z) | (x / y) / z sf36(x,y,z,w) | w - ((x + y) * z)
sf11(x,y,z) | (x / y) * z sf37(x,y,z,w) | w - ((x - y) / z)
sf12(x,y,z) | z / (x + y) sf38(x,y,z,w) | w - ((x - y) * z)
sf13(x,y,z) | z / (x - y) sf39(x,y,z,w) | w - ((x * y) / z)
sf14(x,y,z) | z / (x * y) sf40(x,y,z,w) | w - ((x * y) * z)
sf15(x,y,z) | z / (x / y) sf41(x,y,z,w) | w - ((x / y) / z)
sf16(x,y,z) | z - (x / y) sf42(x,y,z,w) | w - ((x / y) * z)
sf17(x,y,z) | z - (x / y) sf43(x,y,z,w) | ((x + y) * z) - w
sf18(x,y,z) | x * y^2 + z sf44(x,y,z,w) | ((x - y) * z) - w
sf19(x,y,z) | x * y^3 + z sf45(x,y,z,w) | ((x * y) * z) - w
sf20(x,y,z) | x * y^4 + z sf46(x,y,z,w) | ((x / y) * z) - w
sf21(x,y,z) | x * y^5 + z sf47(x,y,z,w) | ((x + y) / z) - w
sf22(x,y,z) | x * y^6 + z sf48(x,y,z,w) | ((x - y) / z) - w
sf23(x,y,z) | x * y^7 + z sf49(x,y,z,w) | ((x * y) / z) - w
sf24(x,y,z) | x * y^8 + z sf50(x,y,z,w) | ((x / y) / z) - w
sf25(x,y,z) | x * y^9 + z sf51(x,y,z,w) | x * y^2 + z * w^2
sf52(x,y,z,w) | x * y^3 + z * w^3
sf53(x,y,z,w) | x * y^4 + z * w^4
sf54(x,y,z,w) | x * y^5 + z * w^5
sf55(x,y,z,w) | x * y^6 + z * w^6
sf56(x,y,z,w) | x * y^7 + z * w^7
sf57(x,y,z,w) | x * y^8 + z * w^8
sf58(x,y,z,w) | x * y^9 + z * w^9
[MACROS]
ExprTk utilizes certain macros to modify the underlying behaviour of
the parser and the evaluation engine. The following macros are used to