package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import static jscl.math.JsclInteger.ONE;
import static jscl.math.JsclInteger.ZERO;
public class Pow extends Algebraic {
private static final int MAX_ARRAY_SIZE = 10000;
public Pow(Generic generic, Generic exponent) {
super("pow", new Generic[]{generic, exponent});
}
static Generic root_minus_1(int d) {
switch (d) {
case 1:
return JsclInteger.valueOf(-1);
case 2:
return Constants.Generic.I;
case 3:
return Constants.Generic.J_BAR.negate();
case 4:
return new Sqrt(Constants.Generic.HALF).expressionValue().multiply(JsclInteger.valueOf(1).add(Constants.Generic.I));
case 6:
return Constants.Generic.HALF.multiply(new Sqrt(JsclInteger.valueOf(3)).expressionValue().add(Constants.Generic.I));
default:
return null;
}
}
@Override
public int getMinParameters() {
return 2;
}
public Root rootValue() throws NotRootException {
try {
Variable v = parameters[1].variableValue();
if (v instanceof Inverse) {
Generic g = ((Inverse) v).parameter();
try {
int d = g.integerValue().intValue();
if (d > 0 && d < MAX_ARRAY_SIZE) {
Generic a[] = new Generic[d + 1];
a[0] = parameters[0].negate();
for (int i = 1; i < d; i++) {
a[i] = ZERO;
}
a[d] = ONE;
return new Root(a, 0);
}
} catch (NotIntegerException e) {
}
}
} catch (NotVariableException e) {
}
throw new NotRootException();
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
try {
Root r = rootValue();
Generic g[] = r.getParameters();
if (g[0].isPolynomial(variable)) {
return AntiDerivative.compute(r, variable);
} else throw new NotIntegrableException(this);
} catch (NotRootException e) {
}
return super.antiDerivative(variable);
}
public Generic antiDerivative(int n) throws NotIntegrableException {
if (n == 0) {
return new Pow(parameters[0], parameters[1].add(JsclInteger.valueOf(1))).selfExpand().multiply(new Inverse(parameters[1].add(JsclInteger.valueOf(1))).selfExpand());
} else {
return new Pow(parameters[0], parameters[1]).selfExpand().multiply(new Inverse(new Ln(parameters[0]).selfExpand()).selfExpand());
}
}
public Generic derivative(int n) {
if (n == 0) {
return new Pow(parameters[0], parameters[1].subtract(JsclInteger.valueOf(1))).selfExpand().multiply(parameters[1]);
} else {
return new Pow(parameters[0], parameters[1]).selfExpand().multiply(new Ln(parameters[0]).selfExpand());
}
}
public Generic selfExpand() {
if (parameters[0].compareTo(JsclInteger.valueOf(1)) == 0) {
return JsclInteger.valueOf(1);
}
if (parameters[1].signum() < 0) {
return new Pow(new Inverse(parameters[0]).selfExpand(), parameters[1].negate()).selfExpand();
}
try {
int c = parameters[1].integerValue().intValue();
return parameters[0].pow(c);
} catch (NotIntegerException e) {
}
try {
Root r = rootValue();
int d = r.degree();
Generic g[] = r.getParameters();
Generic a = g[0].negate();
try {
JsclInteger en = a.integerValue();
if (en.signum() < 0) ;
else {
Generic rt = en.nthrt(d);
if (rt.pow(d).compareTo(en) == 0) return rt;
}
} catch (NotIntegerException e) {
}
} catch (NotRootException e) {
}
return expressionValue();
}
public Generic selfElementary() {
return new Exp(
new Ln(
parameters[0]
).selfElementary().multiply(
parameters[1]
)
).selfElementary();
}
public Generic selfSimplify() {
// a ^ b
// a = 1 => for any b: 1 ^ b = 1
if (parameters[0].compareTo(ONE) == 0) {
return JsclInteger.valueOf(1);
}
// b < 0 => a ^ b = (1 / a) ^ (-b)
if (parameters[1].signum() < 0) {
return new Pow(new Inverse(parameters[0]).selfSimplify(), parameters[1].negate()).selfSimplify();
}
try {
// if b is integer => just calculate the result
int intPower = parameters[1].integerValue().intValue();
return parameters[0].pow(intPower);
} catch (NotIntegerException e) {
}
try {
Root r = rootValue();
int d = r.degree();
Generic g[] = r.getParameters();
Generic a = g[0].negate();
try {
JsclInteger en = a.integerValue();
if (en.signum() < 0) ;
else {
Generic rt = en.nthrt(d);
if (rt.pow(d).compareTo(en) == 0) return rt;
}
} catch (NotIntegerException e) {
}
switch (d) {
case 2:
return new Sqrt(a).selfSimplify();
case 3:
case 4:
case 6:
if (a.compareTo(JsclInteger.valueOf(-1)) == 0) return root_minus_1(d);
}
} catch (NotRootException e) {
Generic n[] = Fraction.separateCoefficient(parameters[1]);
if (n[0].compareTo(ONE) == 0 && n[1].compareTo(ONE) == 0) {
// do nothing
} else {
return new Pow(
new Pow(
new Pow(
parameters[0],
n[2]
).selfSimplify(),
new Inverse(
n[1]
).selfSimplify()
).selfSimplify(),
n[0]
).selfSimplify();
}
}
return expressionValue();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).pow(parameters[1]);
}
public String toString() {
StringBuffer buffer = new StringBuffer();
try {
JsclInteger en = parameters[0].integerValue();
if (en.signum() < 0) buffer.append(GenericVariable.valueOf(en, true));
else buffer.append(en);
} catch (NotIntegerException e) {
try {
Variable v = parameters[0].variableValue();
if (v instanceof Fraction || v instanceof Pow) {
buffer.append(GenericVariable.valueOf(parameters[0]));
} else buffer.append(v);
} catch (NotVariableException e2) {
try {
Power o = parameters[0].powerValue();
if (o.exponent() == 1) buffer.append(o.value(true));
else buffer.append(GenericVariable.valueOf(parameters[0]));
} catch (NotPowerException e3) {
buffer.append(GenericVariable.valueOf(parameters[0]));
}
}
}
buffer.append("^");
try {
JsclInteger en = parameters[1].integerValue();
buffer.append(en);
} catch (NotIntegerException e) {
try {
Variable v = parameters[1].variableValue();
if (v instanceof Fraction) {
buffer.append(GenericVariable.valueOf(parameters[1]));
} else buffer.append(v);
} catch (NotVariableException e2) {
try {
parameters[1].powerValue();
buffer.append(parameters[1]);
} catch (NotPowerException e3) {
buffer.append(GenericVariable.valueOf(parameters[1]));
}
}
}
return buffer.toString();
}
public String toJava() {
StringBuffer buffer = new StringBuffer();
buffer.append(parameters[0].toJava());
buffer.append(".pow(");
buffer.append(parameters[1].toJava());
buffer.append(")");
return buffer.toString();
}
void bodyToMathML(MathML element, boolean fenced) {
if (fenced) {
MathML e1 = element.element("mfenced");
bodyToMathML(e1);
element.appendChild(e1);
} else {
bodyToMathML(element);
}
}
void bodyToMathML(MathML element) {
MathML e1 = element.element("msup");
try {
Variable v = parameters[0].variableValue();
if (v instanceof Fraction || v instanceof Pow || v instanceof Exp) {
GenericVariable.valueOf(parameters[0]).toMathML(e1, null);
} else parameters[0].toMathML(e1, null);
} catch (NotVariableException e2) {
try {
Power o = parameters[0].powerValue();
if (o.exponent() == 1) o.value(true).toMathML(e1, null);
else GenericVariable.valueOf(parameters[0]).toMathML(e1, null);
} catch (NotPowerException e3) {
GenericVariable.valueOf(parameters[0]).toMathML(e1, null);
}
}
parameters[1].toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new Pow(null, null);
}
}