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

This commit is contained in:
Arash Partow 2016-10-06 08:20:01 +11:00
parent 3a82d4af1b
commit 5e3733ad8a
3 changed files with 486 additions and 63 deletions

View File

@ -3950,9 +3950,12 @@ namespace exprtk
{ {
data_ = data; data_ = data;
if (data_ref_) if (!data_ref_.empty())
{ {
(*data_ref_) = data; for (std::size_t i = 0; i < data_ref_.size(); ++i)
{
(*data_ref_[i]) = data;
}
} }
} }
@ -3978,14 +3981,14 @@ namespace exprtk
void set_ref(data_ptr_t* data_ref) void set_ref(data_ptr_t* data_ref)
{ {
data_ref_ = data_ref; data_ref_.push_back(data_ref);
} }
private: private:
std::size_t size_; std::size_t size_;
data_ptr_t data_; data_ptr_t data_;
data_ptr_t* data_ref_; std::vector<data_ptr_t*> data_ref_;
}; };
template <typename T> template <typename T>
@ -4751,11 +4754,11 @@ namespace exprtk
e_vovocov , e_vocovov , e_covovov , e_covocov , e_vovocov , e_vocovov , e_covovov , e_covocov ,
e_vocovoc , e_covovoc , e_vococov , e_sf3ext , e_vocovoc , e_covovoc , e_vococov , e_sf3ext ,
e_sf4ext , e_nulleq , e_strass , e_vector , e_sf4ext , e_nulleq , e_strass , e_vector ,
e_vecelem , e_vecdefass , e_vecvalass , e_vecvecass , e_vecelem , e_rbvecelem , e_rbveccelem , e_vecdefass ,
e_vecopvalass , e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvalass , e_vecvecass , e_vecopvalass , e_vecopvecass ,
e_vecvecineq , e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecfunc , e_vecvecswap , e_vecvecineq , e_vecvalineq ,
e_vecvalarith , e_valvecarith , e_vecunaryop , e_break , e_valvecineq , e_vecvecarith , e_vecvalarith , e_valvecarith ,
e_continue , e_swap e_vecunaryop , e_break , e_continue , e_swap
}; };
typedef T value_type; typedef T value_type;
@ -4846,7 +4849,9 @@ namespace exprtk
return node && return node &&
( (
details::expression_node<T>::e_variable == node->type() || details::expression_node<T>::e_variable == node->type() ||
details::expression_node<T>::e_vecelem == node->type() details::expression_node<T>::e_vecelem == node->type() ||
details::expression_node<T>::e_rbvecelem == node->type() ||
details::expression_node<T>::e_rbveccelem == node->type()
); );
} }
@ -4856,6 +4861,18 @@ namespace exprtk
return node && (details::expression_node<T>::e_vecelem == node->type()); return node && (details::expression_node<T>::e_vecelem == node->type());
} }
template <typename T>
inline bool is_rebasevector_elem_node(const expression_node<T>* node)
{
return node && (details::expression_node<T>::e_rbvecelem == node->type());
}
template <typename T>
inline bool is_rebasevector_celem_node(const expression_node<T>* node)
{
return node && (details::expression_node<T>::e_rbveccelem == node->type());
}
template <typename T> template <typename T>
inline bool is_vector_node(const expression_node<T>* node) inline bool is_vector_node(const expression_node<T>* node)
{ {
@ -5071,6 +5088,11 @@ namespace exprtk
return value_at(0); return value_at(0);
} }
virtual inline bool rebaseable() const
{
return false;
}
virtual void set_ref(value_ptr*) {} virtual void set_ref(value_ptr*) {}
protected: protected:
@ -5157,6 +5179,11 @@ namespace exprtk
vec_view_.set_ref(ref); vec_view_.set_ref(ref);
} }
virtual inline bool rebaseable() const
{
return true;
}
protected: protected:
value_ptr value_at(const std::size_t& index) const value_ptr value_at(const std::size_t& index) const
@ -5217,6 +5244,11 @@ namespace exprtk
return vector_holder_base_->set_ref(ref); return vector_holder_base_->set_ref(ref);
} }
bool rebaseable() const
{
return vector_holder_base_->rebaseable();
}
private: private:
mutable vector_holder_base* vector_holder_base_; mutable vector_holder_base* vector_holder_base_;
@ -6912,6 +6944,118 @@ namespace exprtk
bool index_deletable_; bool index_deletable_;
}; };
template <typename T>
class rebasevector_elem_node : public expression_node<T>,
public ivariable <T>
{
public:
typedef expression_node<T>* expression_ptr;
typedef vector_holder<T> vector_holder_t;
typedef vector_holder_t* vector_holder_ptr;
typedef vec_data_store<T> vds_t;
rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
: index_(index),
index_deletable_(branch_deletable(index_)),
vector_holder_(vec_holder),
vds_((*vector_holder_).size(),(*vector_holder_)[0])
{
vector_holder_->set_ref(&vds_.ref());
}
~rebasevector_elem_node()
{
if (index_ && index_deletable_)
{
delete index_;
}
}
inline T value() const
{
return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
}
inline T& ref()
{
return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
}
inline const T& ref() const
{
return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_rbvecelem;
}
inline vector_holder_t& vec_holder()
{
return (*vector_holder_);
}
private:
expression_ptr index_;
bool index_deletable_;
vector_holder_ptr vector_holder_;
vds_t vds_;
};
template <typename T>
class rebasevector_celem_node : public expression_node<T>,
public ivariable <T>
{
public:
typedef expression_node<T>* expression_ptr;
typedef vector_holder<T> vector_holder_t;
typedef vector_holder_t* vector_holder_ptr;
typedef vec_data_store<T> vds_t;
rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
: index_(index),
vector_holder_(vec_holder),
vds_((*vector_holder_).size(),(*vector_holder_)[0])
{
vector_holder_->set_ref(&vds_.ref());
}
inline T value() const
{
return *(vds_.data() + index_);
}
inline T& ref()
{
return *(vds_.data() + index_);
}
inline const T& ref() const
{
return *(vds_.data() + index_);
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_rbveccelem;
}
inline vector_holder_t& vec_holder()
{
return (*vector_holder_);
}
private:
std::size_t index_;
vector_holder_ptr vector_holder_;
vds_t vds_;
};
template <typename T> template <typename T>
class vector_assignment_node : public expression_node<T> class vector_assignment_node : public expression_node<T>
{ {
@ -9096,6 +9240,82 @@ namespace exprtk
vector_elem_node<T>* vec_node_ptr_; vector_elem_node<T>* vec_node_ptr_;
}; };
template <typename T>
class assignment_rebasevec_elem_node : public binary_node<T>
{
public:
typedef expression_node<T>* expression_ptr;
assignment_rebasevec_elem_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
rbvec_node_ptr_(0)
{
if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
{
rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
}
}
inline T value() const
{
if (rbvec_node_ptr_)
{
T& result = rbvec_node_ptr_->ref();
result = binary_node<T>::branch_[1].first->value();
return result;
}
else
return std::numeric_limits<T>::quiet_NaN();
}
private:
rebasevector_elem_node<T>* rbvec_node_ptr_;
};
template <typename T>
class assignment_rebasevec_celem_node : public binary_node<T>
{
public:
typedef expression_node<T>* expression_ptr;
assignment_rebasevec_celem_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
rbvec_node_ptr_(0)
{
if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
{
rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
}
}
inline T value() const
{
if (rbvec_node_ptr_)
{
T& result = rbvec_node_ptr_->ref();
result = binary_node<T>::branch_[1].first->value();
return result;
}
else
return std::numeric_limits<T>::quiet_NaN();
}
private:
rebasevector_celem_node<T>* rbvec_node_ptr_;
};
template <typename T> template <typename T>
class assignment_vec_node : public binary_node <T>, class assignment_vec_node : public binary_node <T>,
public vector_interface<T> public vector_interface<T>
@ -9436,6 +9656,80 @@ namespace exprtk
vector_elem_node<T>* vec_node_ptr_; vector_elem_node<T>* vec_node_ptr_;
}; };
template <typename T, typename Operation>
class assignment_rebasevec_elem_op_node : public binary_node<T>
{
public:
typedef expression_node<T>* expression_ptr;
assignment_rebasevec_elem_op_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
rbvec_node_ptr_(0)
{
if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
{
rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
}
}
inline T value() const
{
if (rbvec_node_ptr_)
{
T& v = rbvec_node_ptr_->ref();
v = Operation::process(v,binary_node<T>::branch_[1].first->value());
return v;
}
else
return std::numeric_limits<T>::quiet_NaN();
}
private:
rebasevector_elem_node<T>* rbvec_node_ptr_;
};
template <typename T, typename Operation>
class assignment_rebasevec_celem_op_node : public binary_node<T>
{
public:
typedef expression_node<T>* expression_ptr;
assignment_rebasevec_celem_op_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
rbvec_node_ptr_(0)
{
if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
{
rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
}
}
inline T value() const
{
if (rbvec_node_ptr_)
{
T& v = rbvec_node_ptr_->ref();
v = Operation::process(v,binary_node<T>::branch_[1].first->value());
return v;
}
else
return std::numeric_limits<T>::quiet_NaN();
}
private:
rebasevector_celem_node<T>* rbvec_node_ptr_;
};
template <typename T, typename Operation> template <typename T, typename Operation>
class assignment_vec_op_node : public binary_node <T>, class assignment_vec_op_node : public binary_node <T>,
public vector_interface<T> public vector_interface<T>
@ -10790,10 +11084,8 @@ namespace exprtk
typedef type_store<T> type_store_t; typedef type_store<T> type_store_t;
typedef expression_node<T>* expression_ptr; typedef expression_node<T>* expression_ptr;
typedef variable_node<T> variable_node_t; typedef variable_node<T> variable_node_t;
typedef vector_elem_node<T> vector_elem_node_t;
typedef vector_node<T> vector_node_t; typedef vector_node<T> vector_node_t;
typedef variable_node_t* variable_node_ptr_t; typedef variable_node_t* variable_node_ptr_t;
typedef vector_elem_node_t* vector_elem_node_ptr_t;
typedef vector_node_t* vector_node_ptr_t; typedef vector_node_t* vector_node_ptr_t;
typedef range_interface<T> range_interface_t; typedef range_interface<T> range_interface_t;
typedef range_data_type<T> range_data_type_t; typedef range_data_type<T> range_data_type_t;
@ -16858,6 +17150,7 @@ namespace exprtk
if (expr && details::branch_deletable(expr)) if (expr && details::branch_deletable(expr))
{ {
delete expr; delete expr;
expr = reinterpret_cast<expression_ptr>(0);
} }
if (!local_data_list.empty()) if (!local_data_list.empty())
@ -17351,6 +17644,8 @@ namespace exprtk
typedef details::switch_node <T> switch_node_t; typedef details::switch_node <T> switch_node_t;
typedef details::variable_node <T> variable_node_t; typedef details::variable_node <T> variable_node_t;
typedef details::vector_elem_node<T> vector_elem_node_t; typedef details::vector_elem_node<T> vector_elem_node_t;
typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t;
typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
typedef details::vector_node <T> vector_node_t; typedef details::vector_node <T> vector_node_t;
typedef details::range_pack <T> range_t; typedef details::range_pack <T> range_t;
#ifndef exprtk_disable_string_capabilities #ifndef exprtk_disable_string_capabilities
@ -17366,7 +17661,9 @@ namespace exprtk
typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
#endif #endif
typedef details::assignment_node<T> assignment_node_t; typedef details::assignment_node<T> assignment_node_t;
typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; typedef details::assignment_vec_elem_node <T> assignment_vec_elem_node_t;
typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;
typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
typedef details::assignment_vec_node <T> assignment_vec_node_t; typedef details::assignment_vec_node <T> assignment_vec_node_t;
typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t; typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t;
typedef details::scand_node<T> scand_node_t; typedef details::scand_node<T> scand_node_t;
@ -17437,6 +17734,7 @@ namespace exprtk
typedef details::vector_holder<T> vector_holder_t; typedef details::vector_holder<T> vector_holder_t;
typedef variable_node_t* variable_node_ptr; typedef variable_node_t* variable_node_ptr;
typedef vector_holder_t* vector_holder_ptr; typedef vector_holder_t* vector_holder_ptr;
typedef expression_node_t* expression_node_ptr;
#ifndef exprtk_disable_string_capabilities #ifndef exprtk_disable_string_capabilities
typedef stringvar_node_t* stringvar_node_ptr; typedef stringvar_node_t* stringvar_node_ptr;
#endif #endif
@ -17503,7 +17801,7 @@ namespace exprtk
element_type type; element_type type;
bool active; bool active;
void* data; void* data;
variable_node_ptr var_node; expression_node_ptr var_node;
vector_holder_ptr vec_node; vector_holder_ptr vec_node;
#ifndef exprtk_disable_string_capabilities #ifndef exprtk_disable_string_capabilities
stringvar_node_ptr str_node; stringvar_node_ptr str_node;
@ -17514,6 +17812,7 @@ namespace exprtk
{ {
public: public:
typedef expression_node_t* expression_node_ptr;
typedef variable_node_t* variable_node_ptr; typedef variable_node_t* variable_node_ptr;
typedef parser<T> parser_t; typedef parser<T> parser_t;
@ -17630,7 +17929,7 @@ namespace exprtk
{ {
switch (se.type) switch (se.type)
{ {
case scope_element::e_variable: if (se.data ) delete (T*) se.data; case scope_element::e_variable : if (se.data ) delete (T*) se.data;
if (se.var_node) delete se.var_node; if (se.var_node) delete se.var_node;
break; break;
@ -17670,22 +17969,28 @@ namespace exprtk
return ++input_param_cnt_; return ++input_param_cnt_;
} }
inline variable_node_ptr get_variable(const T& v) inline expression_node_ptr get_variable(const T& v)
{ {
for (std::size_t i = 0; i < element_.size(); ++i) for (std::size_t i = 0; i < element_.size(); ++i)
{ {
scope_element& se = element_[i]; scope_element& se = element_[i];
if (se.active && se.var_node) if (
se.active &&
se.var_node &&
details::is_variable_node(se.var_node)
)
{ {
if (&se.var_node->ref() == (&v)) variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
if (&(vn->ref()) == (&v))
{ {
return se.var_node; return se.var_node;
} }
} }
} }
return variable_node_ptr(0); return expression_node_ptr(0);
} }
private: private:
@ -23179,7 +23484,7 @@ namespace exprtk
return parse_define_string_statement(var_name,initialisation_expression); return parse_define_string_statement(var_name,initialisation_expression);
} }
variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0); expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
scope_element& se = sem_.get_element(var_name); scope_element& se = sem_.get_element(var_name);
@ -23271,7 +23576,7 @@ namespace exprtk
return error_node(); return error_node();
} }
variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0); expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
scope_element& se = sem_.get_element(var_name); scope_element& se = sem_.get_element(var_name);
@ -24773,7 +25078,9 @@ namespace exprtk
else else
return ( return (
!details::is_variable_node (branch[0]) && !details::is_variable_node (branch[0]) &&
!details::is_vector_elem_node(branch[0]) && !details::is_vector_elem_node (branch[0]) &&
!details::is_rebasevector_elem_node (branch[0]) &&
!details::is_rebasevector_celem_node(branch[0]) &&
!details::is_vector_node (branch[0]) !details::is_vector_node (branch[0])
) )
|| b1_is_genstring; || b1_is_genstring;
@ -26119,7 +26426,10 @@ namespace exprtk
details::free_node(*node_allocator_,index); details::free_node(*node_allocator_,index);
Type* v = (*vector_base)[i]; if (vector_base->rebaseable())
{
return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
}
scope_element& se = parser_->sem_.get_element(symbol,i); scope_element& se = parser_->sem_.get_element(symbol,i);
@ -26137,7 +26447,7 @@ namespace exprtk
nse.index = i; nse.index = i;
nse.depth = parser_->state_.scope_depth; nse.depth = parser_->state_.scope_depth;
nse.data = 0; nse.data = 0;
nse.var_node = new variable_node_t((*v)); nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
if (!parser_->sem_.add_element(nse)) if (!parser_->sem_.add_element(nse))
{ {
@ -26155,8 +26465,10 @@ namespace exprtk
result = nse.var_node; result = nse.var_node;
} }
} }
else if (vector_base->rebaseable())
result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
else else
result = node_allocator_->allocate<details::vector_elem_node<Type> >(index,vector_base); result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
return result; return result;
} }
@ -26257,6 +26569,18 @@ namespace exprtk
return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
} }
else if (details::is_rebasevector_elem_node(branch[0]))
{
lodge_assignment(e_st_vecelem,branch[0]);
return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
}
else if (details::is_rebasevector_celem_node(branch[0]))
{
lodge_assignment(e_st_vecelem,branch[0]);
return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
}
#ifndef exprtk_disable_string_capabilities #ifndef exprtk_disable_string_capabilities
else if (details::is_string_node(branch[0])) else if (details::is_string_node(branch[0]))
{ {
@ -26329,6 +26653,42 @@ namespace exprtk
default : return error_node(); default : return error_node();
} }
} }
else if (details::is_rebasevector_elem_node(branch[0]))
{
switch (operation)
{
#define case_stmt(op0,op1) \
case op0 : return node_allocator_-> \
template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
(operation,branch[0],branch[1]); \
case_stmt(details::e_addass,details::add_op)
case_stmt(details::e_subass,details::sub_op)
case_stmt(details::e_mulass,details::mul_op)
case_stmt(details::e_divass,details::div_op)
case_stmt(details::e_modass,details::mod_op)
#undef case_stmt
default : return error_node();
}
}
else if (details::is_rebasevector_celem_node(branch[0]))
{
switch (operation)
{
#define case_stmt(op0,op1) \
case op0 : return node_allocator_-> \
template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
(operation,branch[0],branch[1]); \
case_stmt(details::e_addass,details::add_op)
case_stmt(details::e_subass,details::sub_op)
case_stmt(details::e_mulass,details::mul_op)
case_stmt(details::e_divass,details::div_op)
case_stmt(details::e_modass,details::mod_op)
#undef case_stmt
default : return error_node();
}
}
else if (details::is_vector_node(branch[0])) else if (details::is_vector_node(branch[0]))
{ {
lodge_assignment(e_st_vector,branch[0]); lodge_assignment(e_st_vector,branch[0]);

View File

@ -6273,6 +6273,69 @@ inline bool run_test18()
return false; return false;
} }
{
bool failure = false;
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T> expression_t;
typedef exprtk::parser<T> parser_t;
std::vector<T> v0;
std::vector<T> s;
#define pb(v,N) \
v.push_back(T(N)); \
pb(v0,0) pb(v0,1) pb(v0,2) pb(v0,3) pb(v0,4)
pb(v0,5) pb(v0,6) pb(v0,7) pb(v0,8) pb(v0,9)
pb(s, 3) pb(s, 6) pb(s, 9) pb(s,12)
pb(s,15) pb(s,18) pb(s,21)
#undef pb
const std::string expr_string = "v[0] + v[1] + v[2]";
exprtk::vector_view<T> v = exprtk::make_vector_view(v0,4);
symbol_table_t symbol_table;
symbol_table.add_vector("v",v);
expression_t expression;
expression.register_symbol_table(symbol_table);
parser_t parser;
if (!parser.compile(expr_string,expression))
{
printf("run_test18() - Error: %s\tExpression: %s\n",
parser.error().c_str(),
expr_string.c_str());
failure = true;
}
for (std::size_t i = 0; i < v0.size() - 4; ++i)
{
v.rebase(v0.data() + i);
T sum = expression.value();
if (not_equal(sum,s[i]))
{
printf("run_test18() - Error in evaluation! (7) Expression: %s Expected: %5.3f Computed: %5.3f\n",
expr_string.c_str(),
s[i],
sum);
failure = true;
}
}
if (failure)
return false;
}
return true; return true;
} }

View File

@ -749,10 +749,10 @@ The symbol table supports adding references to external instances of
types that can be accessed within expressions via the following types that can be accessed within expressions via the following
methods: methods:
1. bool add_variable (const std::string& name, scalar_t) 1. bool add_variable (const std::string& name, scalar_t&)
2. bool add_constant (const std::string& name,const scalar_t) 2. bool add_constant (const std::string& name, const scalar_t&)
3. bool add_stringvar(const std::string& name, std::string) 3. bool add_stringvar(const std::string& name, std::string&)
4. bool add_vector (const std::string& name, vector_type) 4. bool add_vector (const std::string& name, vector_type&)
The 'vector' type must consist of a contiguous array of scalars which The 'vector' type must consist of a contiguous array of scalars which