package jscl.math; import jscl.math.function.Conjugate; import jscl.math.function.Constant; import jscl.math.function.Fraction; import jscl.mathml.MathML; import jscl.util.ArrayComparator; import javax.annotation.Nonnull; import java.util.HashSet; import java.util.Set; public class JsclVector extends Generic { @Nonnull protected final Generic elements[]; protected final int rows; public JsclVector(@Nonnull Generic elements[]) { this.elements = elements; this.rows = elements.length; } @Nonnull public static JsclVector unity(int dimension) { final JsclVector result = new JsclVector(new Generic[dimension]); for (int i = 0; i < result.rows; i++) { if (i == 0) { result.elements[i] = JsclInteger.valueOf(1); } else { result.elements[i] = JsclInteger.valueOf(0); } } return result; } @Nonnull public Generic[] elements() { return elements; } public JsclVector add(@Nonnull JsclVector vector) { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].add(vector.elements[i]); } return result; } @Nonnull public Generic add(@Nonnull Generic that) { if (that instanceof JsclVector) { return add((JsclVector) that); } else { return add(valueOf(that)); } } public JsclVector subtract(@Nonnull JsclVector vector) { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].subtract(vector.elements[i]); } return result; } @Nonnull public Generic subtract(@Nonnull Generic that) { if (that instanceof JsclVector) { return subtract((JsclVector) that); } else { return subtract(valueOf(that)); } } @Nonnull public Generic multiply(@Nonnull Generic that) { if (that instanceof JsclVector) { return scalarProduct((JsclVector) that); } else if (that instanceof Matrix) { return ((Matrix) that).transpose().multiply(this); } else { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].multiply(that); } return result; } } @Nonnull public Generic divide(@Nonnull Generic that) throws NotDivisibleException { if (that instanceof JsclVector) { throw new ArithmeticException("Unable to divide vector by vector!"); } else if (that instanceof Matrix) { return multiply(that.inverse()); } else { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { try { result.elements[i] = elements[i].divide(that); } catch (NotDivisibleException e) { result.elements[i] = new Fraction(elements[i], that).selfExpand(); } } return result; } } public Generic gcd(@Nonnull Generic generic) { return null; } @Nonnull public Generic gcd() { return null; } public Generic negate() { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].negate(); } return result; } public int signum() { for (int i = 0; i < rows; i++) { int c = elements[i].signum(); if (c < 0) { return -1; } else if (c > 0) { return 1; } } return 0; } public int degree() { return 0; } public Generic antiDerivative(@Nonnull Variable variable) throws NotIntegrableException { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].antiDerivative(variable); } return result; } public Generic derivative(@Nonnull Variable variable) { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].derivative(variable); } return result; } public Generic substitute(@Nonnull Variable variable, Generic generic) { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].substitute(variable, generic); } return result; } public Generic expand() { JsclVector v = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) v.elements[i] = elements[i].expand(); return v; } public Generic factorize() { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].factorize(); } return result; } public Generic elementary() { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].elementary(); } return result; } public Generic simplify() { final JsclVector result = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { result.elements[i] = elements[i].simplify(); } return result; } public Generic numeric() { return new NumericWrapper(this); } public Generic valueOf(@Nonnull Generic generic) { if (generic instanceof JsclVector || generic instanceof Matrix) { throw new ArithmeticException("Unable to create vector: vector of vectors or vector of matrices are forbidden!"); } else { JsclVector v = (JsclVector) unity(rows).multiply(generic); return newInstance(v.elements); } } public Generic[] sumValue() { return new Generic[]{this}; } public Generic[] productValue() throws NotProductException { return new Generic[]{this}; } public Power powerValue() throws NotPowerException { return new Power(this, 1); } public Expression expressionValue() throws NotExpressionException { throw new NotExpressionException(); } public JsclInteger integerValue() throws NotIntegerException { throw NotIntegerException.get(); } @Override public double doubleValue() throws NotDoubleException { throw NotDoubleException.get(); } @Override public boolean isInteger() { return false; } public Variable variableValue() throws NotVariableException { throw new NotVariableException(); } public Variable[] variables() { return null; } public boolean isPolynomial(@Nonnull Variable variable) { return false; } public boolean isConstant(@Nonnull Variable variable) { return false; } public Generic magnitude2() { return scalarProduct(this); } public Generic scalarProduct(@Nonnull JsclVector vector) { Generic result = JsclInteger.valueOf(0); for (int i = 0; i < rows; i++) { result = result.add(elements[i].multiply(vector.elements[i])); } return result; } public JsclVector vectorProduct(@Nonnull JsclVector vector) { final JsclVector result = (JsclVector) newInstance(); Generic m[][] = { {JsclInteger.valueOf(0), elements[2].negate(), elements[1]}, {elements[2], JsclInteger.valueOf(0), elements[0].negate()}, {elements[1].negate(), elements[0], JsclInteger.valueOf(0)} }; JsclVector v2 = (JsclVector) new Matrix(m).multiply(vector); for (int i = 0; i < rows; i++) { result.elements[i] = i < v2.rows ? v2.elements[i] : JsclInteger.valueOf(0); } return result; } public JsclVector complexProduct(JsclVector vector) { return product(new Clifford(0, 1).operator(), vector); } public JsclVector quaternionProduct(JsclVector vector) { return product(new Clifford(0, 2).operator(), vector); } public JsclVector geometricProduct(JsclVector vector, int algebra[]) { return product(new Clifford(algebra == null ? new int[]{Clifford.log2e(rows), 0} : algebra).operator(), vector); } JsclVector product(int product[][], JsclVector vector) { JsclVector v = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) v.elements[i] = JsclInteger.valueOf(0); for (int i = 0; i < rows; i++) { for (int j = 0; j < rows; j++) { Generic a = elements[i].multiply(vector.elements[j]); int k = Math.abs(product[i][j]) - 1; v.elements[k] = v.elements[k].add(product[i][j] < 0 ? a.negate() : a); } } return v; } public Generic divergence(Variable variable[]) { Generic a = JsclInteger.valueOf(0); for (int i = 0; i < rows; i++) a = a.add(elements[i].derivative(variable[i])); return a; } public JsclVector curl(Variable variable[]) { JsclVector v = (JsclVector) newInstance(); v.elements[0] = elements[2].derivative(variable[1]).subtract(elements[1].derivative(variable[2])); v.elements[1] = elements[0].derivative(variable[2]).subtract(elements[2].derivative(variable[0])); v.elements[2] = elements[1].derivative(variable[0]).subtract(elements[0].derivative(variable[1])); for (int i = 3; i < rows; i++) v.elements[i] = elements[i]; return v; } public Matrix jacobian(Variable variable[]) { Matrix m = new Matrix(new Generic[rows][variable.length]); for (int i = 0; i < rows; i++) { for (int j = 0; j < variable.length; j++) { m.elements[i][j] = elements[i].derivative(variable[j]); } } return m; } public Generic del(Variable variable[], int algebra[]) { return differential(new Clifford(algebra == null ? new int[]{Clifford.log2e(rows), 0} : algebra).operator(), variable); } JsclVector differential(int product[][], Variable variable[]) { JsclVector v = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) v.elements[i] = JsclInteger.valueOf(0); int l = Clifford.log2e(rows); for (int i = 1; i <= l; i++) { for (int j = 0; j < rows; j++) { Generic a = elements[j].derivative(variable[i - 1]); int k = Math.abs(product[i][j]) - 1; v.elements[k] = v.elements[k].add(product[i][j] < 0 ? a.negate() : a); } } return v; } public Generic conjugate() { JsclVector v = (JsclVector) newInstance(); for (int i = 0; i < rows; i++) { v.elements[i] = new Conjugate(elements[i]).selfExpand(); } return v; } public int compareTo(JsclVector vector) { return ArrayComparator.comparator.compare(elements, vector.elements); } public int compareTo(Generic generic) { if (generic instanceof JsclVector) { return compareTo((JsclVector) generic); } else { return compareTo(valueOf(generic)); } } public String toString() { final StringBuilder result = new StringBuilder(); result.append("["); for (int i = 0; i < rows; i++) { result.append(elements[i]).append(i < rows - 1 ? ", " : ""); } result.append("]"); return result.toString(); } public String toJava() { final StringBuilder result = new StringBuilder(); result.append("new Vector(new Numeric[] {"); for (int i = 0; i < rows; i++) { result.append(elements[i].toJava()).append(i < rows - 1 ? ", " : ""); } result.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); } } @Nonnull @Override public Set<? extends Constant> getConstants() { final Set<Constant> result = new HashSet<Constant>(elements.length); for (Generic element : elements) { result.addAll(element.getConstants()); } return result; } protected void bodyToMathML(MathML e0) { MathML e1 = e0.element("mfenced"); MathML e2 = e0.element("mtable"); for (int i = 0; i < rows; i++) { MathML e3 = e0.element("mtr"); MathML e4 = e0.element("mtd"); elements[i].toMathML(e4, null); e3.appendChild(e4); e2.appendChild(e3); } e1.appendChild(e2); e0.appendChild(e1); } @Nonnull protected Generic newInstance() { return newInstance(new Generic[rows]); } @Nonnull protected Generic newInstance(@Nonnull Generic element[]) { return new JsclVector(element); } }