package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Sqrt extends Algebraic {
public Sqrt(Generic parameter) {
super("√", new Generic[]{parameter});
}
public Root rootValue() {
return new Root(new Generic[]{parameters[0].negate(), JsclInteger.valueOf(0), JsclInteger.valueOf(1)}, 0);
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
Root r = rootValue();
Generic g[] = r.getParameters();
if (g[0].isPolynomial(variable)) {
return AntiDerivative.compute(r, variable);
} else {
throw new NotIntegrableException(this);
}
}
public Generic derivative(int n) {
return Constants.Generic.HALF.multiply(new Inverse(selfExpand()).selfExpand());
}
public boolean imaginary() {
return parameters[0] != null && parameters[0].compareTo(JsclInteger.valueOf(-1)) == 0;
}
public Generic selfExpand() {
Generic result;
try {
final JsclInteger p = parameters[0].integerValue();
if (p.signum() < 0) {
// result will be complex => evaluate
result = expressionValue();
} else {
final Generic sqrt = p.sqrt();
if (sqrt.pow(2).compareTo(p) == 0) {
result = sqrt;
} else {
result = expressionValue();
}
}
} catch (NotIntegerException e) {
result = expressionValue();
}
return result;
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
Generic result = null;
try {
final JsclInteger p = parameters[0].integerValue();
if (p.signum() < 0) {
return Constants.Generic.I.multiply(new Sqrt(p.negate()).selfSimplify());
} else {
final Generic sqrt = p.sqrt();
if (sqrt.pow(2).compareTo(p) == 0) {
return sqrt;
}
}
result = simplify0(p);
} catch (NotIntegerException e) {
result = simplify0(parameters[0]);
}
if (result == null) {
return expressionValue();
} else {
return result;
}
}
@Nullable
private Generic simplifyFractions() {
final Generic n[] = Fraction.separateCoefficient(parameters[0]);
if (n[0].compareTo(JsclInteger.valueOf(1)) != 0 || n[1].compareTo(JsclInteger.valueOf(1)) != 0) {
// n
final Generic numerator = new Sqrt(n[0]).selfSimplify();
// d
final Generic denominator = new Sqrt(n[1]).selfSimplify();
// fraction = n / d
final Generic fraction = new Fraction(numerator, denominator).selfSimplify();
return new Sqrt(n[2]).selfSimplify().multiply(fraction);
}
return null;
}
@Nullable
private Generic simplify0(@Nonnull Generic generic) {
Generic result;
try {
// let's try to present sqrt expression as products
final Generic products[] = generic.factorize().productValue();
result = JsclInteger.valueOf(1);
for (Generic product : products) {
// and try sqrt for each product
final Power power = product.powerValue();
Generic q = power.value(true);
int c = power.exponent();
result = result.multiply(q.pow(c / 2).multiply(new Sqrt(q).expressionValue().pow(c % 2)));
}
} catch (NotPowerException e) {
result = simplifyFractions();
} catch (NotProductException e) {
result = simplifyFractions();
}
return result;
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).sqrt();
}
public String toJava() {
if (parameters[0].compareTo(JsclInteger.valueOf(-1)) == 0) {
return "Complex.valueOf(0, 1)";
} else {
final StringBuilder result = new StringBuilder();
result.append(parameters[0].toJava());
result.append(".").append(name).append("()");
return result.toString();
}
}
@Override
public String toString() {
final Generic parameter = parameters[0];
if (parameter != null) {
try {
if (JsclInteger.ONE.negate().equals(parameter.integerValue())) {
return Constants.I.getName();
} else {
return super.toString();
}
} catch (NotIntegerException e) {
return super.toString();
}
} else {
return super.toString();
}
}
void bodyToMathML(MathML element, boolean fenced) {
if (parameters[0].compareTo(JsclInteger.valueOf(-1)) == 0) {
MathML e1 = element.element("mi");
e1.appendChild(element.text(/*"\u2148"*/"i"));
element.appendChild(e1);
} else {
MathML e1 = element.element("msqrt");
parameters[0].toMathML(e1, null);
element.appendChild(e1);
}
}
@Nonnull
public Variable newInstance() {
return new Sqrt(null);
}
}