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

This commit is contained in:
Arash Partow 2016-08-02 15:41:21 +10:00
parent 767a633b39
commit 3a684785a8
2 changed files with 322 additions and 151 deletions

View File

@ -2256,7 +2256,9 @@ namespace exprtk
inline void scan_token()
{
skip_whitespace();
skip_comments();
if (is_end(s_itr_))
{
return;
@ -2391,14 +2393,20 @@ namespace exprtk
{
/*
Attempt to match a valid numeric value in one of the following formats:
1. 123456
2. 123.456
3. 123.456e3
4. 123.456E3
5. 123.456e+3
6. 123.456E+3
7. 123.456e-3
8. 123.456E-3
01. 123456
02. 123.456
03. 123.456e3
04. 123.456E3
05. 123.456e+3
06. 123.456E+3
07. 123.456e-3
08. 123.456E-3
09. .1234
10. .1234e3
11. .1234E+3
12. .1234e+3
13. .1234E-3
14. .1234e-3
*/
const char* initial_itr = s_itr_;
bool dot_found = false;
@ -2825,30 +2833,27 @@ namespace exprtk
return changes;
}
#define token_inserter_empty_body \
{ \
return -1; \
} \
inline virtual int insert(const token&, token&)
{
return -1;
}
token_inserter_empty_body
inline virtual int insert(const token&, const token&, token&)
{
return -1;
}
token_inserter_empty_body
inline virtual int insert(const token&, const token&, const token&, token&)
{
return -1;
}
token_inserter_empty_body
inline virtual int insert(const token&, const token&, const token&, const token&, token&)
{
return -1;
}
token_inserter_empty_body
inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
{
return -1;
}
token_inserter_empty_body
#undef token_inserter_empty_body
private:
@ -2888,7 +2893,7 @@ namespace exprtk
std::size_t changes = 0;
for (std::size_t i = 0; i < g.token_list_.size() - 1; ++i)
for (std::size_t i = 0; i < (g.token_list_.size() - 1); ++i)
{
token t;
@ -2912,7 +2917,7 @@ namespace exprtk
std::size_t changes = 0;
for (std::size_t i = 0; i < g.token_list_.size() - 2; ++i)
for (std::size_t i = 0; i < (g.token_list_.size() - 2); ++i)
{
token t;
@ -3023,6 +3028,7 @@ namespace exprtk
t.type = lexer::token::e_assign;
t.value = ":=";
t.position = t0.position;
return true;
}
// '+ =' --> '+='
@ -3031,6 +3037,7 @@ namespace exprtk
t.type = lexer::token::e_addass;
t.value = "+=";
t.position = t0.position;
return true;
}
// '- =' --> '-='
@ -3039,6 +3046,7 @@ namespace exprtk
t.type = lexer::token::e_subass;
t.value = "-=";
t.position = t0.position;
return true;
}
// '* =' --> '*='
@ -3047,6 +3055,7 @@ namespace exprtk
t.type = lexer::token::e_mulass;
t.value = "*=";
t.position = t0.position;
return true;
}
// '/ =' --> '/='
@ -3055,6 +3064,7 @@ namespace exprtk
t.type = lexer::token::e_divass;
t.value = "/=";
t.position = t0.position;
return true;
}
// '% =' --> '%='
@ -3063,6 +3073,7 @@ namespace exprtk
t.type = lexer::token::e_modass;
t.value = "%=";
t.position = t0.position;
return true;
}
// '> =' --> '>='
@ -3071,6 +3082,7 @@ namespace exprtk
t.type = lexer::token::e_gte;
t.value = ">=";
t.position = t0.position;
return true;
}
// '< =' --> '<='
@ -3079,6 +3091,7 @@ namespace exprtk
t.type = lexer::token::e_lte;
t.value = "<=";
t.position = t0.position;
return true;
}
// '= =' --> '=='
@ -3087,6 +3100,7 @@ namespace exprtk
t.type = lexer::token::e_eq;
t.value = "==";
t.position = t0.position;
return true;
}
// '! =' --> '!='
@ -3095,6 +3109,7 @@ namespace exprtk
t.type = lexer::token::e_ne;
t.value = "!=";
t.position = t0.position;
return true;
}
// '< >' --> '<>'
@ -3103,6 +3118,7 @@ namespace exprtk
t.type = lexer::token::e_ne;
t.value = "<>";
t.position = t0.position;
return true;
}
// '<= >' --> '<=>'
@ -3111,6 +3127,7 @@ namespace exprtk
t.type = lexer::token::e_swap;
t.value = "<=>";
t.position = t0.position;
return true;
}
// '+ -' --> '-'
@ -3119,6 +3136,7 @@ namespace exprtk
t.type = lexer::token::e_sub;
t.value = "-";
t.position = t0.position;
return true;
}
// '- +' --> '-'
@ -3127,6 +3145,7 @@ namespace exprtk
t.type = lexer::token::e_sub;
t.value = "-";
t.position = t0.position;
return true;
}
// '- -' --> '-'
@ -3139,6 +3158,7 @@ namespace exprtk
t.type = lexer::token::e_add;
t.value = "+";
t.position = t0.position;
return true;
}
else
@ -3558,6 +3578,7 @@ namespace exprtk
}
token_scanner_list.push_back(scanner);
return true;
}
@ -3571,6 +3592,7 @@ namespace exprtk
}
token_modifier_list.push_back(modifier);
return true;
}
@ -3584,6 +3606,7 @@ namespace exprtk
}
token_joiner_list.push_back(joiner);
return true;
}
@ -3597,13 +3620,13 @@ namespace exprtk
}
token_inserter_list.push_back(inserter);
return true;
}
inline bool run_modifiers(lexer::generator& g)
{
error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
bool result = true;
for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
{
@ -3615,17 +3638,17 @@ namespace exprtk
if (!modifier.result())
{
error_token_modifier = token_modifier_list[i];
return false;
}
}
return result;
return true;
}
inline bool run_joiners(lexer::generator& g)
{
error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
bool result = true;
for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
{
@ -3637,17 +3660,17 @@ namespace exprtk
if (!joiner.result())
{
error_token_joiner = token_joiner_list[i];
return false;
}
}
return result;
return true;
}
inline bool run_inserters(lexer::generator& g)
{
error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
bool result = true;
for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
{
@ -3659,17 +3682,17 @@ namespace exprtk
if (!inserter.result())
{
error_token_inserter = token_inserter_list[i];
return false;
}
}
return result;
return true;
}
inline bool run_scanners(lexer::generator& g)
{
error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
bool result = true;
for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
{
@ -3681,11 +3704,12 @@ namespace exprtk
if (!scanner.result())
{
error_token_scanner = token_scanner_list[i];
return false;
}
}
return result;
return true;
}
std::vector<lexer::token_scanner*> token_scanner_list;
@ -14235,120 +14259,85 @@ namespace exprtk
virtual ~ifunction()
{}
#define empty_method_body \
{ \
return std::numeric_limits<T>::quiet_NaN(); \
} \
inline virtual T operator()()
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&,const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
{
return std::numeric_limits<T>::quiet_NaN();
}
empty_method_body
#undef empty_method_body
std::size_t param_count;
};
@ -14391,33 +14380,27 @@ namespace exprtk
virtual ~igeneric_function()
{}
#define igeneric_function_empty_body(N) \
{ \
exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
return std::numeric_limits<T>::quiet_NaN(); \
} \
// f(i_0,i_1,....,i_N) --> Scalar
inline virtual T operator()(parameter_list_t)
{
exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [1]\n"));
return std::numeric_limits<T>::quiet_NaN();
}
igeneric_function_empty_body(1)
// f(i_0,i_1,....,i_N) --> String
inline virtual T operator()(std::string&, parameter_list_t)
{
exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [2]\n"));
return std::numeric_limits<T>::quiet_NaN();
}
igeneric_function_empty_body(2)
// f(psi,i_0,i_1,....,i_N) --> Scalar
inline virtual T operator()(const std::size_t&, parameter_list_t)
{
exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [3]\n"));
return std::numeric_limits<T>::quiet_NaN();
}
igeneric_function_empty_body(3)
// f(psi,i_0,i_1,....,i_N) --> String
inline virtual T operator()(const std::size_t&, std::string&, parameter_list_t)
{
exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [4]\n"));
return std::numeric_limits<T>::quiet_NaN();
}
igeneric_function_empty_body(4)
std::string parameter_sequence;
return_type rtrn_type;
@ -14436,6 +14419,7 @@ namespace exprtk
typedef T (*ff3_functor)(T,T,T);
typedef T (*ff4_functor)(T,T,T,T);
typedef T (*ff5_functor)(T,T,T,T,T);
typedef T (*ff6_functor)(T,T,T,T,T,T);
protected:
@ -14479,6 +14463,14 @@ namespace exprtk
ff5_functor f;
};
struct freefunc6 : public exprtk::ifunction<T>
{
freefunc6(ff6_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
{ return f(v0,v1,v2,v3,v4,v5); }
ff5_functor f;
};
template <typename Type, typename RawType>
struct type_store
{
@ -14762,6 +14754,7 @@ namespace exprtk
static RawType null_type = init_type::set(RawType());
tm_const_itr_t itr = map.find(symbol_name);
if (map.end() == itr)
return null_type;
else
@ -15372,6 +15365,22 @@ namespace exprtk
return add_function(function_name,(*local_data().free_function_list_.back()));
}
inline bool add_function(const std::string& function_name, ff6_functor function)
{
if (!valid())
return false;
else if (!valid_symbol(function_name))
return false;
else if (symbol_exists(function_name))
return false;
exprtk::ifunction<T>* ifunc = new freefunc6(function);
local_data().free_function_list_.push_back(ifunc);
return add_function(function_name,(*local_data().free_function_list_.back()));
}
inline bool add_reserved_function(const std::string& function_name, function_t& function)
{
if (!valid())
@ -25968,6 +25977,7 @@ namespace exprtk
if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result))
{
free_node(*expr_gen.node_allocator_,branch[0]);
return result;
}
}
@ -26247,6 +26257,7 @@ namespace exprtk
if (details::e_pow == boc_opr)
{
bocnode->set_c(bocnode->c() * c);
return bocnode;
}
}
@ -26362,6 +26373,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
(cobnode->c() / c,cobnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[0]);
}
}
@ -26415,6 +26427,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
(c - cobnode->c(),cobnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[1]);
}
}
@ -26430,6 +26443,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
(c - cobnode->c(),cobnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[1]);
}
}
@ -26445,6 +26459,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
(c / cobnode->c(),cobnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[1]);
}
}
@ -26460,6 +26475,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
(c / cobnode->c(),cobnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[1]);
}
}
@ -26517,6 +26533,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
(bocnode->move_branch(0),c - bocnode->c());
free_node(*expr_gen.node_allocator_,branch[0]);
}
else if (details::e_sub == operation)
@ -26561,6 +26578,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
(c - bocnode->c(),bocnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[1]);
}
}
@ -26571,6 +26589,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
(bocnode->move_branch(0),c - bocnode->c());
free_node(*expr_gen.node_allocator_,branch[1]);
}
else if (details::e_sub == operation)
@ -26578,6 +26597,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
(c + bocnode->c(),bocnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[1]);
}
}
@ -26593,6 +26613,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
(c / bocnode->c(),bocnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[1]);
}
}
@ -26608,6 +26629,7 @@ namespace exprtk
result = expr_gen.node_allocator_->
template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
(c * bocnode->c(),bocnode->move_branch(0));
free_node(*expr_gen.node_allocator_,branch[1]);
}
}
@ -32504,66 +32526,71 @@ namespace exprtk
virtual ~polynomial()
{}
#define poly_rtrn(NN) \
return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
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());
poly_rtrn(1) poly_impl<T,1>::evaluate(x,c1,c0);
}
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());
poly_rtrn(2) poly_impl<T,2>::evaluate(x,c2,c1,c0);
}
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());
poly_rtrn(3) poly_impl<T,3>::evaluate(x,c3,c2,c1,c0);
}
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());
poly_rtrn(4) poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0);
}
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());
poly_rtrn(5) poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0);
}
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());
poly_rtrn(6) poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0);
}
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());
poly_rtrn(7) poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0);
}
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());
poly_rtrn(8) poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0);
}
inline virtual T operator()(const T& x, const T& c9, 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 ((9 == N) ? poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
poly_rtrn(9) poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
}
inline virtual T operator()(const T& x, const T& c10, const T& c9, 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 ((10 == N) ? poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
poly_rtrn(10) poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
}
inline virtual T operator()(const T& x, const T& c11, const T& c10, const T& c9, 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 ((11 == N) ? poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
poly_rtrn(11) poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
}
inline virtual T operator()(const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 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 ((12 == N) ? poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
poly_rtrn(12) poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
}
#undef poly_rtrn
inline virtual T operator()()
{
return std::numeric_limits<T>::quiet_NaN();
@ -32645,6 +32672,19 @@ namespace exprtk
v_.push_back(v2); v_.push_back(v3);
}
function(const std::string& name,
const std::string& expression,
const std::string& v0, const std::string& v1,
const std::string& v2, const std::string& v3,
const std::string& v4)
: name_(name),
expression_(expression)
{
v_.push_back(v0); v_.push_back(v1);
v_.push_back(v2); v_.push_back(v3);
v_.push_back(v4);
}
inline function& name(const std::string& n)
{
name_ = n;
@ -32893,16 +32933,30 @@ namespace exprtk
typedef const T& type;
template <typename BaseFuncType>
struct scoped_bft
{
scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }
~scoped_bft() { bft_.post(); }
BaseFuncType& bft_;
private:
scoped_bft(scoped_bft&);
scoped_bft& operator=(scoped_bft&);
};
struct func_1param : public base_func
{
func_1param() : base_func(1) {}
inline T operator()(type v0)
{
base_func::pre();
scoped_bft<func_1param> sb(*this);
base_func::update(v0);
T result = this->value(base_func::expression);
base_func::post();
return result;
}
};
@ -32913,10 +32967,10 @@ namespace exprtk
inline T operator()(type v0, type v1)
{
base_func::pre();
scoped_bft<func_2param> sb(*this);
base_func::update(v0,v1);
T result = this->value(base_func::expression);
base_func::post();
return result;
}
};
@ -32927,10 +32981,10 @@ namespace exprtk
inline T operator()(type v0, type v1, type v2)
{
base_func::pre();
scoped_bft<func_3param> sb(*this);
base_func::update(v0,v1,v2);
T result = this->value(base_func::expression);
base_func::post();
return result;
}
};
@ -32941,10 +32995,10 @@ namespace exprtk
inline T operator()(type v0, type v1, type v2, type v3)
{
base_func::pre();
scoped_bft<func_4param> sb(*this);
base_func::update(v0,v1,v2,v3);
T result = this->value(base_func::expression);
base_func::post();
return result;
}
};
@ -32955,10 +33009,10 @@ namespace exprtk
inline T operator()(type v0, type v1, type v2, type v3, type v4)
{
base_func::pre();
scoped_bft<func_5param> sb(*this);
base_func::update(v0,v1,v2,v3,v4);
T result = this->value(base_func::expression);
base_func::post();
return result;
}
};
@ -32969,10 +33023,10 @@ namespace exprtk
inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
{
base_func::pre();
scoped_bft<func_6param> sb(*this);
base_func::update(v0,v1,v2,v3,v4,v5);
T result = this->value(base_func::expression);
base_func::post();
return result;
}
};
@ -33040,6 +33094,7 @@ namespace exprtk
if (compile_expression(name,expression,var_list))
{
fp_map_[n][name]->setup(expr_map_[name]);
return true;
}
else

View File

@ -94,6 +94,7 @@ locations:
(a) Download: http://www.partow.net/programming/exprtk/index.html
(b) Repository: https://github.com/ArashPartow/exprtk
https://github.com/ArashPartow/exprtk-extras
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -240,7 +241,7 @@ of C++ compilers:
| ceil | Smallest integer that is greater than or equal to x. |
+----------+---------------------------------------------------------+
| clamp | Clamp x in range between r0 and r1, where r0 < r1. |
| | (eg: clamp(r0,x,r1) |
| | (eg: clamp(r0,x,r1)) |
+----------+---------------------------------------------------------+
| equal | Equality test between x and y using normalized epsilon |
+----------+---------------------------------------------------------+
@ -762,12 +763,12 @@ Expression: z := (x + y^-2.345) * sin(pi / min(w - 7.3,v))
Variable(z) [Multiplication]
____________/ \___________
/ \
/ [Unary-Func(sin)]
/ [Unary-Function(sin)]
[Addition] |
____/ \____ [Division]
/ \ ___/ \___
Variable(x) [Exponentiation] / \
______/ \______ Constant(pi) [Binary-Func(min)]
______/ \______ Constant(pi) [Binary-Function(min)]
/ \ ____/ \____
Variable(y) [Negation] / \
| / Variable(v)
@ -801,6 +802,118 @@ error status code, with a more detailed description of the error(s)
and its location within the input provided by the 'get_error'
interface.
Note: The exprtk::expression and exprtk::symbol_table components are
reference counted entities. Copy constructing or assigning to or from
either component will result in a shallow copy and a reference count
increment, rather than a complete replication. Furthermore the
expression and symbol_table components being Default-Constructible,
Copy-Constructible and Copy-Assignable make them compatible with
various C++ standard library containers and adaptors such as
std::vector, std::map, std::stack etc.
The following is an example of two unique expressions, after having
being instantiated and compiled, one expression is assigned to the
other. The diagrams depict their initial and post assignment states,
including which control block each expression references and their
associated reference counts.
exprtk::expression e0; // constructed expression, eg: x + 1
exprtk::expression e1; // constructed expression, eg: 2z + y
+-----[ e0 cntrl block]----+ +-----[ e1 cntrl block]-----+
| 1. Expression Node 'x+1' | | 1. Expression Node '2z+y' |
| 2. Ref Count: 1 |<-+ | 2. Ref Count: 1 |<-+
+--------------------------+ | +---------------------------+ |
| |
+--[ e0 expression]--+ | +--[ e1 expression]--+ |
| 1. Reference to ]------+ | 1. Reference to ]-------+
| e0 Control Block | | e1 Control Block |
+--------------------+ +--------------------+
e0 = e1; // e0 and e1 are now 2z+y
+-----[ e1 cntrl block]-----+
| 1. Expression Node '2z+y' |
+----------->| 2. Ref Count: 2 |<----------+
| +---------------------------+ |
| |
| +--[ e0 expression]--+ +--[ e1 expression]--+ |
+---[ 1. Reference to | | 1. Reference to ]---+
| e1 Control Block | | e1 Control Block |
+--------------------+ +--------------------+
The reason for the above complexity and restrictions of deep copies
for the expression and symbol_table components is because expressions
may include user defined variables or functions. These are embedded as
references into the expression's AST. When copying an expression, said
references need to also be copied. if the references are blindly
copied, then it will result in two or more identical expressions
utilizing the exact same references for variables. This obviously is
not the default assumed scenario and will give rise to non-obvious
behaviours when using the expressions in various contexts such as
muli-threading et al.
The prescribed method for cloning an expression is to compile it from
its string form. Doing so will allow the one to properly consider the
exact source of user defined variables and functions.
Note: The exprtk::parser is a non-copyable and non-thread safe
component, and should only be shared via either a reference, a shared
pointer or a std::ref mechanism, and considerations relating to
synchronisation taken into account where appropriate. The parser
represents an object factory, specifically a factory of expressions,
and generally should not be instantiated solely on a per expression
compilation basis.
The following diagram and example depicts the flow of data and
operations for compiling multiple expressions via the parser and
inserting the newly minted exprtk::expression instances into a
std::vector.
+--[exprtk::parser]--+
| expression factory |
+---->- compile(....) ->---+
| +--------------------+ |
Expressions | | Expressions as
in string form A V exprtk::expression
| | instances
[s0:'x+1' ]-+ | | +-[e0: x+1]
| | | |
[s1:'2z+y']-----+--+ +-->+-[e1: 2z+y]
| |
[s2:'sin(k+w)']-+ +-[e2: sin(k+w)]
const std::string expression_str[3]
= { "x + 1", "2x + y", "sin(k + w)" };
std::vector<expression_t> expression_list;
parser_t parser;
expression_t expression;
symbol_table_t symbol_table;
expression.register_symbol_table(symbol_table);
for (std::size_t i = 0; i < 3; ++i)
{
if (parser.compile(expression_str[i],expression))
{
expression_list.push_back(expression);
}
else
std::cout << "Error in " << expression_str[i] << "\n";
}
for (auto e : expression_list)
{
e.value();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[11 - COMPILATION OPTIONS]
@ -1060,9 +1173,9 @@ zero. The following are examples of vector definitions:
(3) String Definition
Strings are a sequence of 8-bit characters. They can only be defined
with an explicit initialisation value. The following are examples of
string variable definitions:
Strings are sequences comprised of 8-bit characters. They can only be
defined with an explicit initialisation value. The following are
examples of string variable definitions:
(a) Initialise to a string
var x := 'abc';
@ -1096,6 +1209,9 @@ variable definitions, the value to which the variable is initialised
will be returned. Where as for vectors, the value of the first element
(eg: v[0]) will be returned.
8 == ((var x := 7;) + 1)
4 == (var y[3] := {4, 5, 6};)
(5) Variable/Vector Assignment
The value of a variable can be assigned to a vector and a vector or a