package jscl.math; import jscl.math.function.*; import jscl.math.operator.Factorial; import jscl.math.operator.Operator; import jscl.mathml.MathML; import jscl.text.ParseException; import org.solovyev.common.math.MathEntity; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Set; public abstract class Variable implements Comparable, MathEntity { @Nonnull public static final Comparator<Variable> comparator = VariableComparator.comparator; protected static final com.google.common.base.Function<Generic, Generic> FACTORIZE_CONVERTER = new com.google.common.base.Function<Generic, Generic>() { @Nonnull @Override public Generic apply(@Nonnull Generic generic) { return generic.factorize(); } }; protected static final com.google.common.base.Function<Generic, Generic> ELEMENTARY_CONVERTER = new com.google.common.base.Function<Generic, Generic>() { @Nonnull @Override public Generic apply(@Nonnull Generic generic) { return generic.elementary(); } }; protected static final com.google.common.base.Function<Generic, Generic> EXPAND_CONVERTER = new com.google.common.base.Function<Generic, Generic>() { @Nonnull @Override public Generic apply(@Nonnull Generic generic) { return generic.expand(); } }; protected static final com.google.common.base.Function<Generic, Generic> NUMERIC_CONVERTER = new com.google.common.base.Function<Generic, Generic>() { @Nonnull @Override public Generic apply(@Nonnull Generic generic) { return generic.numeric(); } }; static final Map<String, String> special = new HashMap<>(); static { special.put("Alpha", "\u0391"); special.put("Beta", "\u0392"); special.put("Gamma", "\u0393"); special.put("Delta", "\u0394"); special.put("Epsilon", "\u0395"); special.put("Zeta", "\u0396"); special.put("Eta", "\u0397"); special.put("Theta", "\u0398"); special.put("Iota", "\u0399"); special.put("Kappa", "\u039A"); special.put("Lambda", "\u039B"); special.put("Mu", "\u039C"); special.put("Nu", "\u039D"); special.put("Xi", "\u039E"); special.put("Pi", "\u03A0"); special.put("Rho", "\u03A1"); special.put("Sigma", "\u03A3"); special.put("Tau", "\u03A4"); special.put("Upsilon", "\u03A5"); special.put("Phi", "\u03A6"); special.put("Chi", "\u03A7"); special.put("Psi", "\u03A8"); special.put("Omega", "\u03A9"); special.put("alpha", "\u03B1"); special.put("beta", "\u03B2"); special.put("gamma", "\u03B3"); special.put("delta", "\u03B4"); special.put("epsilon", "\u03B5"); special.put("zeta", "\u03B6"); special.put("eta", "\u03B7"); special.put("theta", "\u03B8"); special.put("iota", "\u03B9"); special.put("kappa", "\u03BA"); special.put("lambda", "\u03BB"); special.put("mu", "\u03BC"); special.put("nu", "\u03BD"); special.put("xi", "\u03BE"); special.put("pi", "\u03C0"); special.put("rho", "\u03C1"); special.put("sigma", "\u03C3"); special.put("tau", "\u03C4"); special.put("upsilon", "\u03C5"); special.put("phi", "\u03C6"); special.put("chi", "\u03C7"); special.put("psi", "\u03C8"); special.put("omega", "\u03C9"); special.put("infin", "\u221E"); special.put("nabla", "\u2207"); special.put("aleph", "\u2135"); special.put("hbar", "\u210F"); special.put("hamilt", "\u210B"); special.put("lagran", "\u2112"); special.put("square", "\u25A1"); } @Nonnull protected String name; private Integer id; private boolean system = true; public Variable(@Nonnull String name) { this.name = name; } public static Variable valueOf(String str) throws ParseException, NotVariableException { return Expression.valueOf(str).variableValue(); } public static Variable[] valueOf(String str[]) throws ParseException, NotVariableException { int n = str.length; Variable var[] = new Variable[n]; for (int i = 0; i < n; i++) var[i] = valueOf(str[i]); return var; } @Nonnull @Override public Integer getId() { return id; } public void setId(@Nonnull Integer id) { this.id = id; } @Override public boolean isIdDefined() { return id != null; } @Nonnull public final String getName() { return name; } public boolean isSystem() { return system; } public void setSystem(boolean system) { this.system = system; } public void copy(@Nonnull MathEntity that) { if (that instanceof Variable) { this.name = ((Variable) that).name; this.id = ((Variable) that).id; this.system = ((Variable) that).system; } } public abstract Generic antiDerivative(Variable variable) throws NotIntegrableException; @Nonnull public abstract Generic derivative(Variable variable); public abstract Generic substitute(Variable variable, Generic generic); public abstract Generic expand(); public abstract Generic factorize(); public abstract Generic elementary(); public abstract Generic simplify(); public abstract Generic numeric(); @Nonnull public Expression expressionValue() { return Expression.valueOf(this); } public abstract boolean isConstant(Variable variable); public boolean isIdentity(@Nonnull Variable variable) { return this.compareTo(variable) == 0; } public abstract int compareTo(Variable variable); public int compareTo(Object o) { return compareTo((Variable) o); } public boolean equals(Object obj) { if (this == obj) { return true; } return obj instanceof Variable && compareTo((Variable) obj) == 0; } public String toString() { return name; } public String toJava() { return name; } public void toMathML(MathML element, @Nullable Object data) { int exponent = data instanceof Integer ? (Integer) data : 1; if (exponent == 1) nameToMathML(element); else { MathML e1 = element.element("msup"); nameToMathML(e1); MathML e2 = element.element("mn"); e2.appendChild(element.text(String.valueOf(exponent))); e1.appendChild(e2); element.appendChild(e1); } } protected void nameToMathML(MathML element) { MathML e1 = element.element("mi"); e1.appendChild(element.text(special.containsKey(name) ? special.get(name) : name)); element.appendChild(e1); } @Nonnull public abstract Variable newInstance(); @Nonnull public abstract Set<? extends Constant> getConstants(); } class VariableComparator implements Comparator<Variable> { public static final Comparator<Variable> comparator = new VariableComparator(); private VariableComparator() { } static int value(Variable v) { int n; if (v instanceof TechnicalVariable) n = 0; else if (v instanceof IntegerVariable) n = 1; else if (v instanceof DoubleVariable) n = 2; else if (v instanceof Fraction && ((Fraction) v).integer()) n = 3; else if (v instanceof Sqrt && ((Sqrt) v).imaginary()) n = 4; else if (v instanceof Constant) n = 5; else if (v instanceof Root) n = 6; else if (v instanceof Algebraic) n = 7; else if (v instanceof ImplicitFunction) n = 8; else if (v instanceof Function) n = 9; else if (v instanceof Factorial) n = 10; else if (v instanceof Operator) n = 11; else if (v instanceof ExpressionVariable) n = 12; else if (v instanceof VectorVariable) n = 13; else if (v instanceof MatrixVariable) n = 14; else throw new ArithmeticException("Forget to add compare object of type: " + v.getClass()); return n; } public int compare(Variable o1, Variable o2) { return value(o1) - value(o2); } }