expr_ptr recursive_apply(expr_ptr& expr, expr_ptr (simplifier)(expr_ptr& expr, bool&), bool& mod) { switch(expr->get_type()) { case MULT : { binary*b=(binary*) expr.release(); expr = Binary{new multiplication{ recursive_apply(b->first, simplifier, mod), recursive_apply(b->second, simplifier, mod) }}; break; } case DIV : { binary*b=(binary*) expr.release(); expr = Binary{new division { recursive_apply(b->first, simplifier, mod), recursive_apply(b->second, simplifier, mod) }}; break; } case ADD : { binary*b=(binary*) expr.release(); expr = Binary{new addition { recursive_apply(b->first, simplifier, mod), recursive_apply(b->second, simplifier, mod) }}; break; } case SUB : { binary*b=(binary*) expr.release(); expr = Binary{new subtraction { recursive_apply(b->first, simplifier, mod), recursive_apply(b->second, simplifier, mod) }}; break; } case EXPO : { break; } case LOG : { break; } case NEGATE : { Negation n{(negation*) expr.release()}; expr = recursive_apply(n->orig, simplifier, mod); break; } case VARIABLE : { break; } case INTERVAL : { break; } case IEEE : { break; } case REAL : { break; } case COMPLEX : { break; } case ZERO : { break; } case UNITY : { break; } case ANYTHING : { break; } case NAN : { break; } case INFINITY : { break; } default: trap("Unable to simplify expression of type: " + expr->get_text()); } return simplifier(expr, mod); }
expr_ptr build_rightmost_tree( expr_ptr const &a, expr_ptr &node, expression_type in ) { expr_ptr right_tree = build_tree_for( in ); right_tree->set_children( 1, a ); right_tree.swap( node ); node->set_children( 0, right_tree ); return node->get_children( 1 ); }
void attach( expr_ptr const &a, std::deque<expression_type> &operator_deq, std::deque<expr_ptr> &children_deq ) { for( size_t i = 0; i != a->num_children(); ++i ){ expression_type type_of_expr = a->get_children( i )->get_type(); if( type_of_expr == expression_type::Plus ){ operator_deq.push_back( type_of_expr ); attach( a->get_children( i ), operator_deq, children_deq ); } else { children_deq.push_back( a->get_children( i ) ); } } }
expr_ptr linearize( expr_ptr const & expression ) { std::deque<expr_ptr> child_deq {}; std::deque<expression_type> op_deq { expression->get_type() }; expr_ptr tree_to_build = nullptr, ptr = nullptr; expr *x = tree_to_build.get(); attach( expression, op_deq, child_deq ); while( !op_deq.empty() ){ if( !tree_to_build ){ tree_to_build = build_tree_for( op_deq.front() ); op_deq.pop_front(); tree_to_build->set_children( 0, child_deq.front() ); child_deq.pop_front(); tree_to_build->set_children( 1, child_deq.front() ); child_deq.pop_front(); ptr = tree_to_build->get_children( 1 ); x = tree_to_build.get(); } else { auto foo = build_rightmost_tree( child_deq.front(), ptr, op_deq.front() ); op_deq.pop_front(); child_deq.pop_front(); x->set_children( 1, ptr ); x = x->get_children( 1 ).get(); ptr = foo; } } return tree_to_build; }
expr_ptr simplify_expression(expr_ptr& expr) { bool mod; do { mod = false; expr = recursive_apply(expr, simplify_an_expression, mod); } while (mod); return expr_ptr{expr.release()}; }
expr_ptr simplify_an_expression(expr_ptr& expr, bool& mod) { // expr->append_text(std::cout << "simplifying: ") << std::endl; switch(expr->get_type()) { case REAL : /* return simplify (Real {(real *) expr.release()}, mod); */ break; case COMPLEX : /* return simplify (Complex {(complex *) expr.release()}, mod); */ break; case MULT : return simplify_mult(Multiplication {(multiplication *) expr.release()}, mod); case DIV : /* return simplify (Division {(division *) expr.release()}, mod); */ break; case ADD : return simplify_add (Addition {(addition *) expr.release()}, mod); case SUB : /* return simplify (Subtraction {(subtraction *) expr.release()}, mod); */ break; case EXPO : /* return simplify (Exponent {(exponent *) expr.release()}, mod); */ break; case NEGATE : return simplify_neg (Negation {(negation *) expr.release()}, mod); case VARIABLE: /* return simplify (Variable {(variable *) expr.release()}, mod); */ break; case LOG : /* return simplify (expr_ptr {(expression_raw *) expr.release()}, mod); */ break; case INTERVAL: /* return simplify (expr_ptr {(expression_raw *) expr.release()}, mod); */ break; case IEEE : /* return simplify (expr_ptr {(expression_raw *) expr.release()}, mod); */ break; case ZERO : /* return expr_ptr{expr.release()}; */ break; case UNITY : /* return expr_ptr{expr.release()}; */ break; case ANYTHING: /* return expr_ptr{expr.release()}; */ break; case NAN : /* return expr_ptr{expr.release()}; */ break; case INFINITY: /* return expr_ptr{expr.release()}; */ break; default: trap("Unable to simplify expression of type: " + expr->get_text()); } return expr_ptr{expr.release()}; }