package jscl.math.function;
import jscl.math.*;
import jscl.mathml.MathML;
import javax.annotation.Nonnull;
public class Fraction extends Algebraic {
// fraction: n/d
// where n = numerator,
// d = denominator
public Fraction(Generic numerator, Generic denominator) {
super("frac", new Generic[]{numerator, denominator});
}
/**
* @param generic any generic value
* @return array of 3 elements where
* a[0] =
*/
static Generic[] separateCoefficient(@Nonnull Generic generic) {
if (generic.signum() < 0) {
Generic n[] = separateCoefficient(generic.negate());
return new Generic[]{n[0], n[1], n[2].negate()};
}
try {
final Variable v = generic.variableValue();
if (v instanceof Fraction) {
final Generic parameters[] = ((Fraction) v).getParameters();
// v = n / d
// numerator
final Generic n = parameters[0].expressionValue();
// denumerator
final Generic d = parameters[1].expressionValue();
// na = [gcd(n), n/(gcd(n))]
Generic na[] = n.gcdAndNormalize();
// nd = [gcd(d), d/(gcd(d))]
Generic nd[] = d.gcdAndNormalize();
return new Generic[]{na[0], nd[0], new Fraction(na[1], nd[1]).selfExpand()};
}
} catch (NotVariableException e) {
try {
Generic a = generic.expressionValue();
Generic n[] = a.gcdAndNormalize();
return new Generic[]{n[0], JsclInteger.valueOf(1), n[1]};
} catch (NotExpressionException e2) {
}
}
return new Generic[]{JsclInteger.valueOf(1), JsclInteger.valueOf(1), generic};
}
@Override
public int getMinParameters() {
return 2;
}
public Root rootValue() {
return new Root(new Generic[]{parameters[0].negate(), parameters[1]}, 0);
}
public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
if (parameters[0].isPolynomial(variable) && parameters[1].isPolynomial(variable)) {
return AntiDerivative.compute(this, variable);
} else throw new NotIntegrableException(this);
}
public Generic derivative(int n) {
if (n == 0) {
return new Inverse(parameters[1]).selfExpand();
} else {
return parameters[0].multiply(new Inverse(parameters[1]).selfExpand().pow(2).negate());
}
}
public boolean integer() {
try {
if (parameters[0] != null && parameters[1] != null) {
parameters[0].integerValue().intValue();
parameters[1].integerValue().intValue();
return true;
}
} catch (NotIntegerException e) {
}
return false;
}
public Generic selfExpand() {
if (parameters[0].compareTo(JsclInteger.valueOf(1)) == 0) {
return new Inverse(parameters[1]).selfExpand();
}
try {
return parameters[0].divide(parameters[1]);
} catch (NotDivisibleException e) {
} catch (ArithmeticException e) {
}
return expressionValue();
}
public Generic selfElementary() {
return selfExpand();
}
public Generic selfSimplify() {
if (parameters[0].signum() < 0) {
return new Fraction(parameters[0].negate(), parameters[1]).selfSimplify().negate();
}
if (parameters[1].signum() < 0) {
return new Fraction(parameters[0].negate(), parameters[1].negate()).selfSimplify();
}
return selfExpand();
}
public Generic selfNumeric() {
return ((NumericWrapper) parameters[0]).divide((NumericWrapper) parameters[1]);
}
public String toString() {
final StringBuilder result = new StringBuilder();
try {
parameters[0].powerValue();
result.append(parameters[0]);
} catch (NotPowerException e) {
result.append(GenericVariable.valueOf(parameters[0]));
}
result.append("/");
try {
final Variable v = parameters[1].variableValue();
if (v instanceof Fraction) {
result.append(GenericVariable.valueOf(parameters[1]));
} else {
result.append(v);
}
} catch (NotVariableException e) {
try {
parameters[1].abs().powerValue();
result.append(parameters[1]);
} catch (NotPowerException e2) {
result.append(GenericVariable.valueOf(parameters[1]));
}
}
return result.toString();
}
public String toJava() {
final StringBuilder result = new StringBuilder();
result.append(parameters[0].toJava());
result.append(".divide(");
result.append(parameters[1].toJava());
result.append(")");
return result.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("mfrac");
parameters[0].toMathML(e1, null);
parameters[1].toMathML(e1, null);
element.appendChild(e1);
}
@Nonnull
public Variable newInstance() {
return new Fraction(null, null);
}
}