C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
1e90af47f9
commit
5c21af90e1
347
exprtk.hpp
347
exprtk.hpp
|
@ -8783,6 +8783,8 @@ namespace exprtk
|
||||||
virtual const T c() const = 0;
|
virtual const T c() const = 0;
|
||||||
|
|
||||||
virtual void set_c(const T) = 0;
|
virtual void set_c(const T) = 0;
|
||||||
|
|
||||||
|
virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -10227,6 +10229,12 @@ namespace exprtk
|
||||||
return branch_[0].first;
|
return branch_[0].first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline expression_node<T>* move_branch(const std::size_t&)
|
||||||
|
{
|
||||||
|
branch_[0].second = false;
|
||||||
|
return branch_[0].first;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boc_node(const boc_node<T,Operation>&);
|
boc_node(const boc_node<T,Operation>&);
|
||||||
|
@ -11430,6 +11438,7 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
tm_itr_t itr = map.begin();
|
tm_itr_t itr = map.begin();
|
||||||
tm_itr_t end = map.end();
|
tm_itr_t end = map.end();
|
||||||
|
|
||||||
while (end != itr)
|
while (end != itr)
|
||||||
{
|
{
|
||||||
deleter::process((*itr).second);
|
deleter::process((*itr).second);
|
||||||
|
@ -12082,8 +12091,7 @@ namespace exprtk
|
||||||
else if (!local_data().stringvar_store.symbol_exists(symbol_name))
|
else if (!local_data().stringvar_store.symbol_exists(symbol_name))
|
||||||
return false;
|
return false;
|
||||||
return (
|
return (
|
||||||
local_data().stringvar_store.symbol_exists(symbol_name)
|
local_data().stringvar_store.symbol_exists(symbol_name) ||
|
||||||
||
|
|
||||||
local_data().stringvar_store.is_constant (symbol_name)
|
local_data().stringvar_store.is_constant (symbol_name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16570,6 +16578,7 @@ namespace exprtk
|
||||||
inline expression_node_ptr parse_symtab_symbol()
|
inline expression_node_ptr parse_symtab_symbol()
|
||||||
{
|
{
|
||||||
const std::string symbol = current_token_.value;
|
const std::string symbol = current_token_.value;
|
||||||
|
|
||||||
// Are we dealing with a variable or a special constant?
|
// Are we dealing with a variable or a special constant?
|
||||||
expression_node_ptr variable = symbol_table_.get_variable(symbol);
|
expression_node_ptr variable = symbol_table_.get_variable(symbol);
|
||||||
if (variable)
|
if (variable)
|
||||||
|
@ -17365,6 +17374,38 @@ namespace exprtk
|
||||||
return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
|
return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool cocob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(details::e_add == operation) ||
|
||||||
|
(details::e_sub == operation) ||
|
||||||
|
(details::e_mul == operation) ||
|
||||||
|
(details::e_div == operation)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
|
||||||
|
(details::is_constant_node(branch[1]) && details::is_cob_node(branch[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool coboc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(details::e_add == operation) ||
|
||||||
|
(details::e_sub == operation) ||
|
||||||
|
(details::e_mul == operation) ||
|
||||||
|
(details::e_div == operation)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
|
||||||
|
(details::is_constant_node(branch[1]) && details::is_boc_node(branch[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
|
inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
|
||||||
{
|
{
|
||||||
if (!operation_optimizable(operation))
|
if (!operation_optimizable(operation))
|
||||||
|
@ -17546,6 +17587,25 @@ namespace exprtk
|
||||||
return result;
|
return result;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Possible reductions:
|
||||||
|
1. c o cob -> cob
|
||||||
|
2. cob o c -> cob
|
||||||
|
3. c o boc -> boc
|
||||||
|
4. boc o c -> boc
|
||||||
|
*/
|
||||||
|
expression_node_ptr result = error_node();
|
||||||
|
if (cocob_optimizable(operation,branch))
|
||||||
|
result = synthesize_cocob_expression::process(*this,operation,branch);
|
||||||
|
else if (coboc_optimizable(operation,branch) && (0 == result))
|
||||||
|
result = synthesize_coboc_expression::process(*this,operation,branch);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (uvouv_optimizable(operation,branch))
|
if (uvouv_optimizable(operation,branch))
|
||||||
return synthesize_uvouv_expression(operation,branch);
|
return synthesize_uvouv_expression(operation,branch);
|
||||||
else if (vob_optimizable(operation,branch))
|
else if (vob_optimizable(operation,branch))
|
||||||
|
@ -19172,6 +19232,289 @@ namespace exprtk
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct synthesize_cocob_expression
|
||||||
|
{
|
||||||
|
static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
|
||||||
|
const details::operator_type& operation,
|
||||||
|
expression_node_ptr (&branch)[2])
|
||||||
|
{
|
||||||
|
expression_node_ptr result = error_node();
|
||||||
|
|
||||||
|
// (cob) o c --> cob
|
||||||
|
if (details::is_cob_node(branch[0]))
|
||||||
|
{
|
||||||
|
details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
|
||||||
|
const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
|
||||||
|
|
||||||
|
bool op_addsub = (details::e_add == cobnode->operation()) ||
|
||||||
|
(details::e_sub == cobnode->operation());
|
||||||
|
|
||||||
|
if (op_addsub)
|
||||||
|
{
|
||||||
|
switch (operation)
|
||||||
|
{
|
||||||
|
case details::e_add : cobnode->set_c(cobnode->c() + c); break;
|
||||||
|
case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
|
||||||
|
default : return error_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
result = cobnode;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (details::e_mul == cobnode->operation())
|
||||||
|
{
|
||||||
|
switch (operation)
|
||||||
|
{
|
||||||
|
case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
|
||||||
|
case details::e_div : cobnode->set_c(cobnode->c() / c); break;
|
||||||
|
default : return error_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
result = cobnode;
|
||||||
|
}
|
||||||
|
else if (details::e_div == cobnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_mul == operation)
|
||||||
|
{
|
||||||
|
cobnode->set_c(cobnode->c() * c);
|
||||||
|
result = cobnode;
|
||||||
|
}
|
||||||
|
else if (details::e_div == operation)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
free_node(*expr_gen.node_allocator_,branch[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// c o (cob) --> cob
|
||||||
|
else if (details::is_cob_node(branch[1]))
|
||||||
|
{
|
||||||
|
details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
|
||||||
|
const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
|
||||||
|
|
||||||
|
if (details::e_add == cobnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_add == operation)
|
||||||
|
{
|
||||||
|
cobnode->set_c(c + cobnode->c());
|
||||||
|
result = cobnode;
|
||||||
|
}
|
||||||
|
else if (details::e_sub == operation)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (details::e_sub == cobnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_add == operation)
|
||||||
|
{
|
||||||
|
cobnode->set_c(c + cobnode->c());
|
||||||
|
result = cobnode;
|
||||||
|
}
|
||||||
|
else if (details::e_sub == operation)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (details::e_mul == cobnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_mul == operation)
|
||||||
|
{
|
||||||
|
cobnode->set_c(c * cobnode->c());
|
||||||
|
result = cobnode;
|
||||||
|
}
|
||||||
|
else if (details::e_div == operation)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (details::e_div == cobnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_mul == operation)
|
||||||
|
{
|
||||||
|
cobnode->set_c(c * cobnode->c());
|
||||||
|
result = cobnode;
|
||||||
|
}
|
||||||
|
else if (details::e_div == operation)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
free_node(*expr_gen.node_allocator_,branch[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct synthesize_coboc_expression
|
||||||
|
{
|
||||||
|
static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
|
||||||
|
const details::operator_type& operation,
|
||||||
|
expression_node_ptr (&branch)[2])
|
||||||
|
{
|
||||||
|
expression_node_ptr result = error_node();
|
||||||
|
|
||||||
|
// (boc) o c --> boc
|
||||||
|
if (details::is_boc_node(branch[0]))
|
||||||
|
{
|
||||||
|
details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
|
||||||
|
const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
|
||||||
|
|
||||||
|
if (details::e_add == bocnode->operation())
|
||||||
|
{
|
||||||
|
switch (operation)
|
||||||
|
{
|
||||||
|
case details::e_add : bocnode->set_c(bocnode->c() + c); break;
|
||||||
|
case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
|
||||||
|
default : return error_node();
|
||||||
|
}
|
||||||
|
result = bocnode;
|
||||||
|
}
|
||||||
|
else if (details::e_mul == bocnode->operation())
|
||||||
|
{
|
||||||
|
switch (operation)
|
||||||
|
{
|
||||||
|
case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
|
||||||
|
case details::e_div : bocnode->set_c(bocnode->c() / c); break;
|
||||||
|
default : return error_node();
|
||||||
|
}
|
||||||
|
result = bocnode;
|
||||||
|
}
|
||||||
|
else if (details::e_sub == bocnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_add == operation)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
bocnode->set_c(bocnode->c() + c);
|
||||||
|
result = bocnode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (details::e_div == bocnode->operation())
|
||||||
|
{
|
||||||
|
switch (operation)
|
||||||
|
{
|
||||||
|
case details::e_div : bocnode->set_c(bocnode->c() * c); break;
|
||||||
|
case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
|
||||||
|
default : return error_node();
|
||||||
|
}
|
||||||
|
result = bocnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
free_node(*expr_gen.node_allocator_,branch[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// c o (boc) --> boc
|
||||||
|
else if (details::is_boc_node(branch[1]))
|
||||||
|
{
|
||||||
|
details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
|
||||||
|
const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
|
||||||
|
|
||||||
|
if (details::e_add == bocnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_add == operation)
|
||||||
|
{
|
||||||
|
bocnode->set_c(c + bocnode->c());
|
||||||
|
result = bocnode;
|
||||||
|
}
|
||||||
|
else if (details::e_sub == operation)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (details::e_sub == bocnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_add == operation)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (details::e_mul == bocnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_mul == operation)
|
||||||
|
{
|
||||||
|
bocnode->set_c(c * bocnode->c());
|
||||||
|
result = bocnode;
|
||||||
|
}
|
||||||
|
else if (details::e_div == operation)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (details::e_div == bocnode->operation())
|
||||||
|
{
|
||||||
|
if (details::e_mul == operation)
|
||||||
|
{
|
||||||
|
bocnode->set_c(bocnode->c() / c);
|
||||||
|
result = bocnode;
|
||||||
|
}
|
||||||
|
else if (details::e_div == operation)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
free_node(*expr_gen.node_allocator_,branch[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef exprtk_disable_enhanced_features
|
#ifndef exprtk_disable_enhanced_features
|
||||||
inline bool synthesize_expression(const details::operator_type& operation,
|
inline bool synthesize_expression(const details::operator_type& operation,
|
||||||
expression_node_ptr (&branch)[2],
|
expression_node_ptr (&branch)[2],
|
||||||
|
|
|
@ -3309,6 +3309,34 @@ inline bool run_test10()
|
||||||
"var x := 6; var y := 3; -x / -y == 2",
|
"var x := 6; var y := 3; -x / -y == 2",
|
||||||
"var x := 3; var y := 6; -(-x * -y) == -18",
|
"var x := 3; var y := 6; -(-x * -y) == -18",
|
||||||
"var x := 6; var y := 3; -(-x / -y) == -2",
|
"var x := 6; var y := 3; -(-x / -y) == -2",
|
||||||
|
"var x:=1; 2+(3+abs(x)) == 6 ",
|
||||||
|
"var x:=1; (3+abs(x))+2 == 6 ",
|
||||||
|
"var x:=1; 2+(abs(x)+3) == 6 ",
|
||||||
|
"var x:=1; (abs(x)+3)+2 == 6 ",
|
||||||
|
"var x:=1; 2+(3-abs(x)) == 4 ",
|
||||||
|
"var x:=1; (3-abs(x))+2 == 4 ",
|
||||||
|
"var x:=1; 2+(abs(x)-3) == 0 ",
|
||||||
|
"var x:=1; (abs(x)-3)+2 == 0 ",
|
||||||
|
"var x:=1; 2-(3+abs(x)) == -2 ",
|
||||||
|
"var x:=1; (3+abs(x))-2 == 2 ",
|
||||||
|
"var x:=1; 2-(abs(x)+3) == -2 ",
|
||||||
|
"var x:=1; (abs(x)+3)-2 == 2 ",
|
||||||
|
"var x:=1; 2*(3*abs(x)) == 6 ",
|
||||||
|
"var x:=1; (3*abs(x))*2 == 6 ",
|
||||||
|
"var x:=1; 2*(abs(x)*3) == 6 ",
|
||||||
|
"var x:=1; (abs(x)*3)*2 == 6 ",
|
||||||
|
"var x:=1; 2*(3/abs(x)) == 6 ",
|
||||||
|
"var x:=1; (3/abs(x))*2 == 6 ",
|
||||||
|
"var x:=1; 2*(abs(x)/3) == (2/3)",
|
||||||
|
"var x:=1; (abs(x)/3)*2 == (2/3)",
|
||||||
|
"var x:=1; 2/(3*abs(x)) == (2/3)",
|
||||||
|
"var x:=1; (3*abs(x))/2 == (3/2)",
|
||||||
|
"var x:=1; 2/(abs(x)*3) == (2/3)",
|
||||||
|
"var x:=1; (abs(x)*3)/2 == (3/2)",
|
||||||
|
"var x:=1; 2/(3/abs(x)) == (2/3)",
|
||||||
|
"var x:=1; (3/abs(x))/2 == (3/2)",
|
||||||
|
"var x:=1; 2/(abs(x)/3) == 6 ",
|
||||||
|
"var x:=1; (abs(x)/3)/2 == (1/6)",
|
||||||
"var x:=3; var y:=6; -(-x)*-(-y) == 18",
|
"var x:=3; var y:=6; -(-x)*-(-y) == 18",
|
||||||
"var x:=3; var y:=6; -(-x)*-(-(-y)) == -18",
|
"var x:=3; var y:=6; -(-x)*-(-(-y)) == -18",
|
||||||
"var x:=3; var y:=6; -(-(-x))*-(-y) == -18",
|
"var x:=3; var y:=6; -(-(-x))*-(-y) == -18",
|
||||||
|
@ -5299,4 +5327,3 @@ int main()
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue