All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jscl.math.function.Root Maven / Gradle / Ivy

package jscl.math.function;

import jscl.math.*;
import jscl.math.polynomial.Polynomial;
import jscl.math.polynomial.UnivariatePolynomial;
import jscl.mathml.MathML;
import jscl.util.ArrayComparator;

import javax.annotation.Nonnull;

public class Root extends Algebraic {

	protected Generic subscript;

	public Root(Generic parameters[], Generic subscript) {
		super("root", parameters);
		this.subscript = subscript;
	}

	@Override
	public int getMaxParameters() {
		return Integer.MAX_VALUE;
	}

	public Root(Generic parameters[], int s) {
		this(parameters, JsclInteger.valueOf(s));
	}

	public Root(@Nonnull UnivariatePolynomial polynomial, int s) {
		this(polynomial.normalize().elements(), s);
	}

	public Generic subscript() {
		return subscript;
	}

	public Root rootValue() {
		return this;
	}

	public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException {
		boolean polynomial = true;
		for (Generic parameter : parameters) {
			polynomial = parameter.isPolynomial(variable);
			if (!polynomial) {
				break;
			}
		}

		if (polynomial) {
			return AntiDerivative.compute(this, variable);
		} else {
			throw new NotIntegrableException(this);
		}
	}

	@Nonnull
	public Generic derivative(@Nonnull Variable variable) {
		if (compareTo(variable) == 0) {
			return JsclInteger.valueOf(1);
		} else {
			Variable t = new TechnicalVariable("t");
			Generic a[] = new Generic[parameters.length];
			for (int i = 0; i < parameters.length; i++) a[i] = parameters[i].derivative(variable);
			UnivariatePolynomial fact = (UnivariatePolynomial) Polynomial.factory(this);
			UnivariatePolynomial p = fact.valueof(parameters);
			UnivariatePolynomial q = (UnivariatePolynomial) p.derivative().multiply(t.expressionValue()).add(fact.valueof(a));
			UnivariatePolynomial r = (UnivariatePolynomial) Polynomial.factory(t).valueOf(p.resultant(q));
			return new Root(r.elements(), subscript).selfExpand();
		}
	}

	public Generic derivative(int n) {
		return null;
	}

	public Generic substitute(@Nonnull Variable variable, @Nonnull Generic generic) {
		Root v = (Root) newInstance();
		for (int i = 0; i < parameters.length; i++) {
			v.parameters[i] = parameters[i].substitute(variable, generic);
		}
		v.subscript = subscript.substitute(variable, generic);
		if (v.isIdentity(variable)) return generic;
		else return v.selfExpand();
	}

	public Generic expand() {
		Root v = (Root) newInstance();
		for (int i = 0; i < parameters.length; i++) {
			v.parameters[i] = parameters[i].expand();
		}
		v.subscript = subscript.expand();
		return v.selfExpand();
	}

	public Generic factorize() {
		Root v = (Root) newInstance();
		for (int i = 0; i < parameters.length; i++) {
			v.parameters[i] = parameters[i].factorize();
		}
		v.subscript = subscript;
		return v.expressionValue();
	}

	public Generic elementary() {
		Root v = (Root) newInstance();
		for (int i = 0; i < parameters.length; i++) {
			v.parameters[i] = parameters[i].elementary();
		}
		v.subscript = subscript.elementary();
		return v.selfElementary();
	}

	public Generic simplify() {
		Root v = (Root) newInstance();
		for (int i = 0; i < parameters.length; i++) {
			v.parameters[i] = parameters[i].simplify();
		}
		v.subscript = subscript.simplify();
		return v.selfSimplify();
	}

	public Generic numeric() {
		Root v = (Root) newInstance();
		for (int i = 0; i < parameters.length; i++) {
			v.parameters[i] = parameters[i].numeric();
		}
		v.subscript = subscript;
		return v.selfNumeric();
	}

	public Generic selfExpand() {
		if (isZero()) return JsclInteger.valueOf(0);
		try {
			int s = subscript.integerValue().intValue();
			switch (degree()) {
				case 1:
					return new Fraction(parameters[0], parameters[1]).selfExpand().negate();
			}
		} catch (NotIntegerException e) {
		}
		return expressionValue();
	}

	public Generic selfElementary() {
		return selfExpand();
	}

	public Generic selfSimplify() {
		if (isZero()) return JsclInteger.valueOf(0);
		try {
			int s = subscript.integerValue().intValue();
			switch (degree()) {
				case 1:
					return linear(parameters);
				case 2:
					return quadratic(parameters, s);
				case 3:
					return cubic(parameters, s);
				case 4:
					return quartic(parameters, s);
				default:
					if (isNth() && s == 0) return nth(parameters);
			}
		} catch (NotIntegerException e) {
		}
		return expressionValue();
	}

	boolean isZero() {
		boolean b = degree() > 0;
		for (int i = 0; i < degree(); i++) b = b && parameters[i].signum() == 0;
		b = b && parameters[degree()].signum() != 0;
		return b;
	}

	boolean isNth() {
		boolean b = degree() > 0;
		for (int i = 1; i < degree(); i++) b = b && parameters[i].signum() == 0;
		b = b && parameters[degree()].signum() != 0;
		return b;
	}

	static Generic nth(Generic parameter[]) {
		int degree = parameter.length - 1;
		Generic a = new Fraction(parameter[0], parameter[degree]).selfSimplify();
		return new Pow(
				a.negate(),
				new Inverse(JsclInteger.valueOf(degree)).selfSimplify()
		).selfSimplify();
	}

	static Generic linear(Generic parameter[]) {
		Generic a = new Fraction(parameter[0], parameter[1]).selfSimplify();
		return a.negate();
	}

	static Generic quadratic(Generic parameter[], int subscript) {
		Generic a = new Fraction(parameter[1], parameter[2]).selfSimplify();
		Generic b = new Fraction(parameter[0], parameter[2]).selfSimplify();
		Generic y = new Sqrt(
				a.pow(2).subtract(JsclInteger.valueOf(4).multiply(b))
		).selfSimplify();
		switch (subscript) {
			case 0:
				return new Fraction(
						a.subtract(y),
						JsclInteger.valueOf(2)
				).selfSimplify().negate();
			default:
				return new Fraction(
						a.add(y),
						JsclInteger.valueOf(2)
				).selfSimplify().negate();
		}
	}

	static Generic cubic(Generic parameter[], int subscript) {
		Generic a = new Fraction(parameter[2], parameter[3]).selfSimplify();
		Generic b = new Fraction(parameter[1], parameter[3]).selfSimplify();
		Generic c = new Fraction(parameter[0], parameter[3]).selfSimplify();
		Generic y[] = new Generic[2];
		for (int i = 0; i < y.length; i++) {
			y[i] = new Cubic(
					new Root(
							new Generic[]{
									a.pow(6).subtract(JsclInteger.valueOf(9).multiply(a.pow(4)).multiply(b)).add(JsclInteger.valueOf(27).multiply(a.pow(2)).multiply(b.pow(2))).subtract(JsclInteger.valueOf(27).multiply(b.pow(3))),
									JsclInteger.valueOf(2).multiply(a.pow(3)).subtract(JsclInteger.valueOf(9).multiply(a).multiply(b)).add(JsclInteger.valueOf(27).multiply(c)),
									JsclInteger.valueOf(1)
							},
							i
					).selfSimplify()
			).selfSimplify();
		}
		switch (subscript) {
			case 0:
				return new Fraction(
						a.subtract(y[0]).subtract(y[1]),
						JsclInteger.valueOf(3)
				).selfSimplify().negate();
			case 1:
				return new Fraction(
						a.subtract(Constants.Generic.J.multiply(y[0])).subtract(Constants.Generic.J_BAR.multiply(y[1])),
						JsclInteger.valueOf(3)
				).selfSimplify().negate();
			default:
				return new Fraction(
						a.subtract(Constants.Generic.J_BAR.multiply(y[0])).subtract(Constants.Generic.J.multiply(y[1])),
						JsclInteger.valueOf(3)
				).selfSimplify().negate();
		}
	}

	static Generic quartic(Generic parameter[], int subscript) {
		Generic a = new Fraction(parameter[3], parameter[4]).selfSimplify();
		Generic b = new Fraction(parameter[2], parameter[4]).selfSimplify();
		Generic c = new Fraction(parameter[1], parameter[4]).selfSimplify();
		Generic d = new Fraction(parameter[0], parameter[4]).selfSimplify();
		Generic y[] = new Generic[3];
		for (int i = 0; i < y.length; i++) {
			y[i] = new Sqrt(
					new Root(
							new Generic[]{
									a.pow(6).subtract(JsclInteger.valueOf(8).multiply(a.pow(4)).multiply(b)).add(JsclInteger.valueOf(16).multiply(a.pow(2)).multiply(b.pow(2))).add(JsclInteger.valueOf(16).multiply(a.pow(3)).multiply(c)).subtract(JsclInteger.valueOf(64).multiply(a).multiply(b).multiply(c)).add(JsclInteger.valueOf(64).multiply(c.pow(2))),
									JsclInteger.valueOf(-3).multiply(a.pow(4)).add(JsclInteger.valueOf(16).multiply(a.pow(2)).multiply(b)).subtract(JsclInteger.valueOf(16).multiply(b.pow(2))).subtract(JsclInteger.valueOf(16).multiply(a).multiply(c)).add(JsclInteger.valueOf(64).multiply(d)),
									JsclInteger.valueOf(3).multiply(a.pow(2)).subtract(JsclInteger.valueOf(8).multiply(b)),
									JsclInteger.valueOf(-1)
							},
							i
					).selfSimplify()
			).selfSimplify();
		}
		switch (subscript) {
			case 0:
				return new Fraction(
						a.add(y[0]).subtract(y[1]).subtract(y[2]),
						JsclInteger.valueOf(4)
				).selfSimplify().negate();
			case 1:
				return new Fraction(
						a.subtract(y[0]).subtract(y[1]).add(y[2]),
						JsclInteger.valueOf(4)
				).selfSimplify().negate();
			case 2:
				return new Fraction(
						a.add(y[0]).add(y[1]).add(y[2]),
						JsclInteger.valueOf(4)
				).selfSimplify().negate();
			default:
				return new Fraction(
						a.subtract(y[0]).add(y[1]).subtract(y[2]),
						JsclInteger.valueOf(4)
				).selfSimplify().negate();
		}
	}

	public int degree() {
		return parameters.length - 1;
	}

	public Generic selfNumeric() {
		return NumericWrapper.root(subscript.integerValue().intValue(), parameters);
	}

	public int compareTo(Variable that) {
		if (this == that) return 0;
		int c = comparator.compare(this, that);
		if (c < 0) return -1;
		else if (c > 0) return 1;
		else {
			Root v = (Root) that;
			c = ArrayComparator.comparator.compare(parameters, v.parameters);
			if (c < 0) return -1;
			else if (c > 0) return 1;
			else return subscript.compareTo(v.subscript);
		}
	}

	public static Generic sigma(Generic parameter[], int n) {
		Sigma s = new Sigma(parameter, n);
		s.compute();
		return s.getValue();
	}

	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append(name);
		buffer.append("[").append(subscript).append("]");
		buffer.append("(");
		for (int i = 0; i < parameters.length; i++) {
			buffer.append(parameters[i]).append(i < parameters.length - 1 ? ", " : "");
		}
		buffer.append(")");
		return buffer.toString();
	}

	public String toJava() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("Numeric.").append(name).append("(");
		buffer.append(subscript.integerValue().intValue());
		buffer.append(", new Numeric[] {");
		for (int i = 0; i < parameters.length; i++) {
			buffer.append(parameters[i].toJava()).append(i < parameters.length - 1 ? ", " : "");
		}
		buffer.append("})");
		return buffer.toString();
	}

	public void toMathML(MathML element, Object data) {
		MathML e1;
		int exponent = data instanceof Integer ? ((Integer) data).intValue() : 1;
		if (exponent == 1) {
			e1 = element.element("msub");
			nameToMathML(e1);
			subscript.toMathML(e1, null);
			element.appendChild(e1);
		} else {
			e1 = element.element("msubsup");
			nameToMathML(e1);
			subscript.toMathML(e1, null);
			MathML e2 = element.element("mn");
			e2.appendChild(element.text(String.valueOf(exponent)));
			e1.appendChild(e2);
			element.appendChild(e1);
		}
		e1 = element.element("mfenced");
		for (int i = 0; i < parameters.length; i++) {
			parameters[i].toMathML(e1, null);
		}
		element.appendChild(e1);
	}

	void bodyToMathML(MathML element, boolean fenced) {
	}

	@Nonnull
	public Variable newInstance() {
		return new Root(new Generic[parameters.length], null);
	}
}

class Sigma {
	Generic root[];
	Generic generic;
	boolean place[];
	int n;

	Sigma(Generic parameter[], int n) {
		root = new Generic[parameter.length - 1];
		for (int i = 0; i < root.length; i++) root[i] = new Root(parameter, i).expressionValue();
		place = new boolean[root.length];
		this.n = n;
	}

	void compute() {
		generic = JsclInteger.valueOf(0);
		compute(0, n);
	}

	void compute(int p, int nn) {
		if (nn > 0) {
			for (int i = p; i < root.length; i++) {
				place[i] = true;
				compute(i + 1, nn - 1);
				place[i] = false;
			}
		} else {
			Generic s = JsclInteger.valueOf(1);
			for (int i = 0; i < root.length; i++) {
				if (place[i]) s = s.multiply(root[i]);
			}
			generic = generic.add(s);
		}
	}

	Generic getValue() {
		return generic;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy