/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmathexpr.arithmetic.op;
import jmathexpr.Expression;
import jmathexpr.arithmetic.ANumber;
import jmathexpr.arithmetic.real.Reals;
import jmathexpr.op.UnaryOperation;
import jmathexpr.op.Sign;
import jmathexpr.set.Set;
/**
*
* @author Elemér Furka
*/
public final class Negation extends UnaryOperation {
public Negation(Expression operand) {
super(operand, Sign.Subtraction);
}
@Override
public Expression evaluate() {
Expression simplified = simplify();
if (!(simplified instanceof Negation)) {
return simplified;
}
Expression o = ((Negation) simplified).operand;
Expression value;
if (o instanceof ANumber) {
value = ((ANumber) o).negate();
} else if (o instanceof Multiplication) {
Multiplication t = (Multiplication) o;
if (t.lhs() instanceof ANumber && ((ANumber) t.lhs()).isNegative()) {
value = new Multiplication(((ANumber) t.lhs()).negate(), t.rhs());
} else {
value = new Negation(o);
}
} else {
value = new Negation(o);
}
return value;
}
private Expression simplify() {
Expression evaluated = operand.evaluate();
if (evaluated instanceof Addition) { // -(a + b) = -a - b : needed by Sum.evaluation
Addition sum = (Addition) evaluated;
return new Subtraction(new Negation(sum.lhs()), sum.rhs()).evaluate();
} else if (evaluated instanceof Subtraction) {
Subtraction diff = (Subtraction) evaluated;
return new Subtraction(diff.rhs(), diff.lhs()).evaluate();
} else if (evaluated instanceof Sum) {
return ((Sum) evaluated).negate().evaluate();
} else if (evaluated instanceof Division) {
Expression n = ((Division) evaluated).lhs();
Expression d = ((Division) evaluated).rhs();
return new Division(new Negation(n), d).evaluate();
}
return new Negation(evaluated);
}
/**
* Converts this negated expression into a Multiplication if the expression
* is a multiplication and its first factor is a constant
* The first factor will be negated.
*
* @return either a Multiplication instance or this
*/
public Expression toMultiplication() {
if (operand instanceof Multiplication) {
Multiplication m = (Multiplication) operand;
if (m.lhs().isConstant()) {
if (m.lhs() instanceof ANumber) {
return new Multiplication(((ANumber) m.lhs()).negate(), m.rhs());
} else {
return new Multiplication(new Negation(m.lhs()), m.rhs());
}
}
}
return this;
}
@Override
public Set domain() {
return Reals.getInstance();
}
@Override
public Set codomain() {
return Reals.getInstance();
}
public Expression getChild() {
return operand;
}
@Override
protected UnaryOperation create(Expression operand) {
return new Negation(operand);
}
}