package jscl.math.function; import jscl.JsclMathEngine; import jscl.math.*; import jscl.mathml.MathML; import jscl.util.ArrayComparator; import javax.annotation.Nonnull; import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class Constant extends Variable { public static final int PRIME_CHARS = 3; private final int prime; private final Generic subscripts[]; private Object[] hashArray; public Constant(String name) { this(name, 0, new Generic[0]); } public Constant(String name, int prime, Generic subscripts[]) { super(name); this.prime = prime; this.subscripts = subscripts; } static String primeChars(int n) { StringBuilder buffer = new StringBuilder(); for (int i = 0; i < n; i++) buffer.append("'"); return buffer.toString(); } static String underscores(int n) { StringBuilder buffer = new StringBuilder(); for (int i = 0; i < n; i++) buffer.append("_"); return buffer.toString(); } static void primeCharsToMathML(MathML element, int n) { MathML e1 = element.element("mo"); for (int i = 0; i < n; i++) e1.appendChild(element.text("\u2032")); element.appendChild(e1); } public int prime() { return prime; } public Generic[] subscript() { return subscripts; } public Generic antiDerivative(Variable variable) throws NotIntegrableException { return null; } @Nonnull public Generic derivative(Variable variable) { if (isIdentity(variable)) { return JsclInteger.valueOf(1); } else { return JsclInteger.valueOf(0); } } public Generic substitute(Variable variable, Generic generic) { Constant v = (Constant) newInstance(); for (int i = 0; i < subscripts.length; i++) { v.subscripts[i] = subscripts[i].substitute(variable, generic); } if (v.isIdentity(variable)) { return generic; } else { return v.expressionValue(); } } public Generic expand() { Constant v = (Constant) newInstance(); for (int i = 0; i < subscripts.length; i++) { v.subscripts[i] = subscripts[i].expand(); } return v.expressionValue(); } public Generic factorize() { Constant v = (Constant) newInstance(); for (int i = 0; i < subscripts.length; i++) { v.subscripts[i] = subscripts[i].factorize(); } return v.expressionValue(); } public Generic elementary() { Constant v = (Constant) newInstance(); for (int i = 0; i < subscripts.length; i++) { v.subscripts[i] = subscripts[i].elementary(); } return v.expressionValue(); } public Generic simplify() { Constant v = (Constant) newInstance(); for (int i = 0; i < subscripts.length; i++) { v.subscripts[i] = subscripts[i].simplify(); } return v.expressionValue(); } public Generic numeric() { return new NumericWrapper(this); } public boolean isConstant(Variable variable) { return !isIdentity(variable); } public int compareTo(Variable variable) { if (this == variable) { return 0; } int c = comparator.compare(this, variable); if (c == 0) { final Constant that = (Constant) variable; c = name.compareTo(that.name); if (c == 0) { c = ArrayComparator.comparator.compare(this.subscripts, that.subscripts); if (c == 0) { if (prime < that.prime) { return -1; } else if (prime > that.prime) { return 1; } else return 0; } else { return c; } } else { return c; } } else { return c; } } @Override public int hashCode() { final Object[] hashArray = getHashArray(); hashArray[0] = Constant.class; hashArray[1] = name; hashArray[2] = subscripts; hashArray[3] = prime; return Arrays.deepHashCode(this.hashArray); } @Nonnull private Object[] getHashArray() { if(hashArray == null) { hashArray = new Object[4]; } return hashArray; } public String toString() { final StringBuilder result = new StringBuilder(); result.append(name); for (Generic subscript : subscripts) { result.append("[").append(subscript).append("]"); } if (prime != 0) { if (prime <= PRIME_CHARS) result.append(primeChars(prime)); else result.append("{").append(prime).append("}"); } return result.toString(); } public String toJava() { final IConstant constantFromRegistry = JsclMathEngine.getInstance().getConstantsRegistry().get(getName()); if (constantFromRegistry != null) { return constantFromRegistry.toJava(); } final StringBuilder result = new StringBuilder(); result.append(name); if (prime != 0) { if (prime <= PRIME_CHARS) result.append(underscores(prime)); else result.append("_").append(prime); } for (Generic subscript : subscripts) { result.append("[").append(subscript.integerValue().intValue()).append("]"); } return result.toString(); } public void toMathML(MathML element, Object data) { int exponent = data instanceof Integer ? (Integer) data : 1; if (exponent == 1) bodyToMathML(element); else { MathML e1 = element.element("msup"); bodyToMathML(e1); MathML e2 = element.element("mn"); e2.appendChild(element.text(String.valueOf(exponent))); e1.appendChild(e2); element.appendChild(e1); } } public void bodyToMathML(MathML element) { if (subscripts.length == 0) { if (prime == 0) { nameToMathML(element); } else { MathML e1 = element.element("msup"); nameToMathML(e1); primeToMathML(e1); element.appendChild(e1); } } else { if (prime == 0) { MathML e1 = element.element("msub"); nameToMathML(e1); MathML e2 = element.element("mrow"); for (int i = 0; i < subscripts.length; i++) { subscripts[i].toMathML(e2, null); } e1.appendChild(e2); element.appendChild(e1); } else { MathML e1 = element.element("msubsup"); nameToMathML(e1); MathML e2 = element.element("mrow"); for (int i = 0; i < subscripts.length; i++) { subscripts[i].toMathML(e2, null); } e1.appendChild(e2); primeToMathML(e1); element.appendChild(e1); } } } void primeToMathML(MathML element) { if (prime <= PRIME_CHARS) { primeCharsToMathML(element, prime); } else { MathML e1 = element.element("mfenced"); MathML e2 = element.element("mn"); e2.appendChild(element.text(String.valueOf(prime))); e1.appendChild(e2); element.appendChild(e1); } } @Nonnull public Variable newInstance() { return new Constant(name, prime, new Generic[subscripts.length]); } @Nonnull @Override public Set<? extends Constant> getConstants() { final Set<Constant> result = new HashSet<Constant>(); result.add(this); return result; } }