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

This commit is contained in:
Arash Partow 2014-06-26 04:24:20 +10:00
parent 13a256fcb2
commit 7d798d0dec
2 changed files with 121 additions and 6 deletions

View File

@ -3653,6 +3653,19 @@ namespace exprtk
return node && (details::expression_node<T>::e_function == node->type()); return node && (details::expression_node<T>::e_function == node->type());
} }
template <typename T> class unary_node;
template <typename T>
inline bool is_negate_node(const expression_node<T>* node)
{
if (node && is_unary_node(node))
{
return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
}
else
return false;
}
template <typename T> template <typename T>
inline bool branch_deletable(expression_node<T>* node) inline bool branch_deletable(expression_node<T>* node)
{ {
@ -4059,6 +4072,11 @@ namespace exprtk
return branch_; return branch_;
} }
inline void release()
{
branch_deletable_ = false;
}
protected: protected:
operator_type operation_; operator_type operation_;
@ -13514,10 +13532,16 @@ namespace exprtk
expression_node_ptr right_branch = parse_expression(current_state.right); expression_node_ptr right_branch = parse_expression(current_state.right);
expression_node_ptr new_expression = error_node(); expression_node_ptr new_expression = error_node();
details::operator_type current_operation = current_state.operation;
if (right_branch) if (right_branch)
{ {
simplify_negation(current_operation,
expression,
right_branch);
new_expression = expression_generator_( new_expression = expression_generator_(
current_state.operation, current_operation,
expression, expression,
right_branch right_branch
); );
@ -13553,6 +13577,77 @@ namespace exprtk
return expression; return expression;
} }
bool simplify_negation_branch(expression_node_ptr& right)
{
if (is_unary_node(right))
{
details::unary_node<T>* un = static_cast<details::unary_node<T>*>(right);
if (details::e_neg == un->operation())
{
expression_node_ptr un_r = un->branch(0);
un->release();
free_node(node_allocator_,right);
right = un_r;
return true;
}
}
return false;
}
void simplify_negation(details::operator_type& current_operation,
expression_node_ptr& left,
expression_node_ptr& right)
{
bool simplified = false;
do
{
simplified = false;
// (x + - y) --> (x - y)
if (details::e_add == current_operation)
{
if (is_negate_node(right))
{
if (simplify_negation_branch(right))
{
current_operation = details::e_sub;
simplified = true;
}
}
}
// (x - - y) --> (x + y)
else if (details::e_sub == current_operation)
{
if (is_negate_node(right))
{
if (simplify_negation_branch(right))
{
current_operation = details::e_add;
simplified = true;
}
}
}
// -x * - y --> x * y
// -x / - y --> x / y
else if (
(details::e_mul == current_operation) ||
(details::e_div == current_operation)
)
{
if (
is_negate_node(left ) &&
is_negate_node(right)
)
{
simplify_negation_branch(left );
simplify_negation_branch(right);
simplified = true;
}
}
}
while (simplified);
}
static inline expression_node_ptr error_node() static inline expression_node_ptr error_node()
{ {
return reinterpret_cast<expression_node_ptr>(0); return reinterpret_cast<expression_node_ptr>(0);
@ -16017,7 +16112,7 @@ namespace exprtk
!token_is(token_t::e_rsqrbracket,false) !token_is(token_t::e_rsqrbracket,false)
) )
{ {
if (!token_is(token_t::e_eof)) if (!token_is(token_t::e_eof,false))
{ {
set_error( set_error(
make_error(parser_error::e_syntax, make_error(parser_error::e_syntax,
@ -18686,8 +18781,8 @@ namespace exprtk
if (details::is_cob_node(branch[1])) if (details::is_cob_node(branch[1]))
{ {
// Simplify expressions of the form: // Simplify expressions of the form:
// 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) ---> 40320 * (9 + x) // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
// 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) ---> 45 + x // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
if ( if (
(operation == details::e_mul) || (operation == details::e_mul) ||
(operation == details::e_add) (operation == details::e_add)
@ -18794,8 +18889,8 @@ namespace exprtk
if (details::is_boc_node(branch[0])) if (details::is_boc_node(branch[0]))
{ {
// Simplify expressions of the form: // Simplify expressions of the form:
// 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) ---> (x + 9) * 40320 // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
// 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) ---> x + 45 // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
if ( if (
(operation == details::e_mul) || (operation == details::e_mul) ||
(operation == details::e_add) (operation == details::e_add)

View File

@ -342,6 +342,10 @@ static const test_t test_list[] =
test_t("+(1+2)",+3.0), test_t("+(1+2)",+3.0),
test_t("+(1-2)",-1.0), test_t("+(1-2)",-1.0),
test_t("-(1-2)",+1.0), test_t("-(1-2)",+1.0),
test_t("(-3*-6)",+18.0),
test_t("(-6*-3)",+18.0),
test_t("-(-3*-6)",-18.0),
test_t("-(-6*-3)",-18.0),
test_t("1.1+2.2+3.3",+6.6), test_t("1.1+2.2+3.3",+6.6),
test_t("+1.1+2.2+3.3",+6.6), test_t("+1.1+2.2+3.3",+6.6),
test_t("-1.1-2.2-3.3",-6.6), test_t("-1.1-2.2-3.3",-6.6),
@ -3277,6 +3281,22 @@ inline bool run_test10()
{ {
std::string expression_list[] = std::string expression_list[] =
{ {
"var x := 3; var y := 6; x + -y == -3",
"var x := 3; var y := 6; x - -y == 9",
"var x := 3; var y := 6; -x + -y == -9",
"var x := 3; var y := 6; -x - -y == 3",
"var x := 3; var y := 6; -x * -y == 18",
"var x := 6; var y := 3; -x / -y == 2",
"var x := 3; var y := 6; -(-x * -y) == -18",
"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:=3; var y:=6; -(-(-x))*-(-y) == -18",
"var x:=3; var y:=6; -(-(-x))*-(-(-y)) == 18",
"var x:=3; var y:=6; -(-(x+y))*-(-(y+x)) == 81",
"var x:=3; var y:=6; -(-(-(x+y)))*-(-(y+x)) == -81",
"var x:=3; var y:=6; -(-(x+y))*-(-(-(y+x))) == -81",
"var x:=3; var y:=6; -(-(-(x+y)))*-(-(-(y+x))) == 81",
"var x := 1; var y := 2; swap(x,y); (x == 2) and (y == 1)", "var x := 1; var y := 2; swap(x,y); (x == 2) and (y == 1)",
"var x := 1; var y := 2; x <=> y ; (x == 2) and (y == 1)", "var x := 1; var y := 2; x <=> y ; (x == 2) and (y == 1)",
"var v[2] := {1,2}; swap(v[0],v[1]); (v[0] == 2) and (v[1] == 1)", "var v[2] := {1,2}; swap(v[0],v[1]); (v[0] == 2) and (v[1] == 1)",