/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmathexpr.arithmetic.op;
import jmathexpr.Constant;
import jmathexpr.Expression;
import jmathexpr.Precedence;
import jmathexpr.arithmetic.ANumber;
import jmathexpr.arithmetic.func.Sqrt;
import jmathexpr.arithmetic.natural.NaturalNumber;
import jmathexpr.arithmetic.natural.Naturals;
import jmathexpr.arithmetic.real.Reals;
import jmathexpr.op.BinaryOperation;
import jmathexpr.op.Sign;
import jmathexpr.set.Set;
import jmathexpr.util.pattern.ExpressionPattern;
/**
*
* @author Elemér Furka
*/
public class Exponentiation extends BinaryOperation {
public Exponentiation(Expression base, Expression exponent) {
super (base, exponent, Sign.Exponentiation);
}
/**
* Returns the base of this exponentiation (in case of a^b: a).
*
* @return the base of this exponentiation
*/
public Expression base() {
return lhs;
}
/**
* Returns the exponent of this exponentiation (in case of a^b: b).
*
* @return the exponent
*/
public Expression exponent() {
return rhs;
}
@Override
public Expression evaluate() {
Expression simplified = simplify();
if (!(simplified instanceof Exponentiation)) return simplified;
Expression base = ((Exponentiation) simplified).lhs;
Expression exp = ((Exponentiation) simplified).rhs;
if (base instanceof ANumber && exp instanceof ANumber) {
return ((ANumber) base).pow((ANumber) exp);
}
return new Exponentiation(base, exp);
}
private Expression simplify() {
Expression base = lhs.evaluate();
Expression exp = rhs.evaluate();
NaturalNumber two = Naturals.getInstance().create(2);
if (exp.equals(two)) {
if (base instanceof Sqrt) {
return ((Sqrt) base).argument();
} else if (base instanceof Addition) {
Expression a = ((Addition) base).lhs();
Expression b = ((Addition) base).rhs();
return new Sum(new Exponentiation(a, two), new Exponentiation(b, two),
new Multiplication(two, new Multiplication(a, b))).evaluate();
} else if (base instanceof Subtraction) {
Expression a = ((Subtraction) base).lhs();
Expression b = ((Subtraction) base).rhs();
return new Sum(new Exponentiation(a, two), new Exponentiation(b, two),
new Negation(new Multiplication(two, new Multiplication(a, b)))).evaluate();
} else if (base instanceof Negation) {
return new Exponentiation(((Negation) base).getChild(), exp).evaluate();
}
}
if (base instanceof Multiplication) {
Expression a = ((Multiplication) base).lhs();
Expression b = ((Multiplication) base).rhs();
return new Multiplication(new Exponentiation(a, exp),
new Exponentiation(b, exp)).evaluate();
} else if (base instanceof Division) {
Expression a = ((Division) base).lhs();
Expression b = ((Division) base).rhs();
return new Division(new Exponentiation(a, exp),
new Exponentiation(b, exp)).evaluate();
}
return new Exponentiation(base, exp);
}
@Override
public Precedence getPrecedence() {
return Precedence.Exponentiation;
}
@Override
public Set domain() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Set codomain() {
return Reals.getInstance();
}
@Override
public boolean matches(Expression expr) {
boolean matches = super.matches(expr);
if (!matches) {
if (((ExpressionPattern) lhs).matches(expr) && rhs instanceof Constant) { // x matches x^1
((Constant) rhs).setValue(Naturals.one());
return true;
}
}
return matches;
}
@Override
public String toString() {
// String l = lhs instanceof Operation ? String.format("(%s)", lhs) : lhs.toString();
// String r = rhs instanceof Operation ? String.format("(%s)", rhs) : rhs.toString();
String l = lhs.getPrecedence().le(getPrecedence()) ? String.format("(%s)", lhs)
: lhs.toString();
String r = rhs.getPrecedence().le(getPrecedence()) ? String.format("(%s)", rhs)
: rhs.toString();
return String.format("%s%s%s", l, sign, r);
}
@Override
protected Exponentiation create(Expression lhs, Expression rhs) {
return new Exponentiation(lhs, rhs);
}
@Override
public boolean isCommutative() {
return false;
}
}