diff --git a/src/main/java/org/moddingx/libx/util/math/DoublePolynomial.java b/src/main/java/org/moddingx/libx/util/math/DoublePolynomial.java index 2e928cff..748a11ae 100644 --- a/src/main/java/org/moddingx/libx/util/math/DoublePolynomial.java +++ b/src/main/java/org/moddingx/libx/util/math/DoublePolynomial.java @@ -21,6 +21,11 @@ public final class DoublePolynomial extends Polynomial implements Double * The polynomial that is always zero. */ public static final DoublePolynomial ZERO = new DoublePolynomial(0); + + /** + * The polynomial that is always one. + */ + public static final DoublePolynomial ONE = new DoublePolynomial(1); /** * The identity polynomial. @@ -93,6 +98,83 @@ public Double apply(Double x) { return this.applyAsDouble(x); } + @Override + public DoublePolynomial derivative() { + if (this.coefficients.length == 0) return this; + double[] coefficients = new double[this.coefficients.length - 1]; + for (int i = 0; i < coefficients.length; i++) { + coefficients[i] = this.coefficients[i] * (this.coefficients.length - i - 1); + } + // Direct constructor, there will never be leading zeros. + return new DoublePolynomial(coefficients, true); + } + + /** + * Integrates this polynomial with constant part {@literal 0}. + */ + public DoublePolynomial integrate() { + return this.integrate(0); + } + + /** + * Integrates this polynomial with the given constant part. + */ + public DoublePolynomial integrate(double constant) { + double[] coefficients = new double[this.coefficients.length + 1]; + for (int i = 0; i < coefficients.length - 1; i++) { + coefficients[i] = this.coefficients[i] / (this.coefficients.length - i); + } + coefficients[coefficients.length - 1] = constant; + return new DoublePolynomial(coefficients, false); + } + + @Override + public DoublePolynomial negate() { + if (this.coefficients.length == 0) return this; + double[] coefficients = new double[this.coefficients.length]; + for (int i = 0; i < coefficients.length; i++) { + coefficients[i] = -this.coefficients[i]; + } + // Direct constructor, there will never be leading zeros. + return new DoublePolynomial(coefficients, true); + } + + @Override + public DoublePolynomial add(Polynomial other) { + double[] otherCoefficients = trustedCoefficients(other); + double[] coefficients = new double[Math.max(this.coefficients.length, otherCoefficients.length)]; + int thisOffset = coefficients.length - this.coefficients.length; + int otherOffset = coefficients.length - otherCoefficients.length; + for (int i = 0; i < coefficients.length; i++) { + double thisPart = (i - thisOffset) >= 0 ? this.coefficients[i - thisOffset] : 0; + double otherPart = (i - otherOffset) >= 0 ? otherCoefficients[i - otherOffset] : 0; + coefficients[i] = thisPart + otherPart; + } + return new DoublePolynomial(coefficients, false); + } + + @Override + public DoublePolynomial multiply(Polynomial other) { + double[] otherCoefficients = trustedCoefficients(other); + double[] coefficients = new double[this.coefficients.length + otherCoefficients.length]; + for (int i = 0; i < this.coefficients.length; i++) { + for (int j = 0; j < otherCoefficients.length; j++) { + int idx = coefficients.length - ((this.coefficients.length - i - 1) + (otherCoefficients.length - j - 1)) - 1; + coefficients[idx] += (this.coefficients[i] * otherCoefficients[j]); + } + } + return new DoublePolynomial(coefficients, false); + } + + // Returns trusted arrays. Don't modify. + private static double[] trustedCoefficients(Polynomial other) { + if (other instanceof DoublePolynomial polynomial) { + return polynomial.coefficients; + } else { + return other.coefficients().stream().mapToDouble(Double::valueOf).toArray(); + } + } + @Override public int hashCode() { return Arrays.hashCode(this.coefficients); diff --git a/src/main/java/org/moddingx/libx/util/math/IntPolynomial.java b/src/main/java/org/moddingx/libx/util/math/IntPolynomial.java index 9146376f..a7b4b8aa 100644 --- a/src/main/java/org/moddingx/libx/util/math/IntPolynomial.java +++ b/src/main/java/org/moddingx/libx/util/math/IntPolynomial.java @@ -22,7 +22,12 @@ public final class IntPolynomial extends Polynomial implements IntUnary * The polynomial that is always zero. */ public static final IntPolynomial ZERO = new IntPolynomial(0); - + + /** + * The polynomial that is always one. + */ + public static final IntPolynomial ONE = new IntPolynomial(1); + /** * The identity polynomial. */ @@ -94,6 +99,75 @@ public Integer apply(Integer x) { return this.applyAsInt(x); } + @Override + public IntPolynomial derivative() { + if (this.coefficients.length == 0) return this; + int[] coefficients = new int[this.coefficients.length - 1]; + for (int i = 0; i < coefficients.length; i++) { + coefficients[i] = this.coefficients[i] * (this.coefficients.length - i - 1); + } + // Direct constructor, there will never be leading zeros. + return new IntPolynomial(coefficients, true); + } + + @Override + public IntPolynomial negate() { + if (this.coefficients.length == 0) return this; + int[] coefficients = new int[this.coefficients.length]; + for (int i = 0; i < coefficients.length; i++) { + coefficients[i] = -this.coefficients[i]; + } + // Direct constructor, there will never be leading zeros. + return new IntPolynomial(coefficients, true); + } + + @Override + public IntPolynomial add(Polynomial other) { + int[] otherCoefficients = trustedCoefficients(other); + int[] coefficients = new int[Math.max(this.coefficients.length, otherCoefficients.length)]; + int thisOffset = coefficients.length - this.coefficients.length; + int otherOffset = coefficients.length - otherCoefficients.length; + for (int i = 0; i < coefficients.length; i++) { + int thisPart = (i - thisOffset) >= 0 ? this.coefficients[i - thisOffset] : 0; + int otherPart = (i - otherOffset) >= 0 ? otherCoefficients[i - otherOffset] : 0; + coefficients[i] = thisPart + otherPart; + } + return new IntPolynomial(coefficients, false); + } + + @Override + public IntPolynomial multiply(Polynomial other) { + int[] otherCoefficients = trustedCoefficients(other); + int[] coefficients = new int[this.coefficients.length + otherCoefficients.length]; + for (int i = 0; i < this.coefficients.length; i++) { + for (int j = 0; j < otherCoefficients.length; j++) { + int idx = coefficients.length - ((this.coefficients.length - i - 1) + (otherCoefficients.length - j - 1)) - 1; + coefficients[idx] += (this.coefficients[i] * otherCoefficients[j]); + } + } + return new IntPolynomial(coefficients, false); + } + + /** + * Converts this polynomial to a {@link DoublePolynomial}. + */ + public DoublePolynomial toDouble() { + double[] coefficients = new double[this.coefficients.length]; + for (int i = 0; i < coefficients.length; i++) { + coefficients[i] = this.coefficients[i]; + } + return new DoublePolynomial(coefficients); + } + + // Returns trusted arrays. Don't modify. + private static int[] trustedCoefficients(Polynomial other) { + if (other instanceof IntPolynomial polynomial) { + return polynomial.coefficients; + } else { + return other.coefficients().stream().mapToInt(Integer::valueOf).toArray(); + } + } + @Override public int hashCode() { return Arrays.hashCode(this.coefficients); diff --git a/src/main/java/org/moddingx/libx/util/math/Polynomial.java b/src/main/java/org/moddingx/libx/util/math/Polynomial.java index b69a378f..f597efd8 100644 --- a/src/main/java/org/moddingx/libx/util/math/Polynomial.java +++ b/src/main/java/org/moddingx/libx/util/math/Polynomial.java @@ -19,6 +19,33 @@ protected Polynomial() { * polynomial {@code 2x²+1}. */ public abstract List coefficients(); + + /** + * Computes the derivative of this polynomial. + */ + public abstract Polynomial derivative(); + + /** + * Negates this polynomial. + */ + public abstract Polynomial negate(); + + /** + * Adds two polynomials together. + */ + public abstract Polynomial add(Polynomial other); + + /** + * Subtracts two polynomials from each other. + */ + public Polynomial subtract(Polynomial other) { + return this.add(other.negate()); + } + + /** + * Multiplies two polynomials. + */ + public abstract Polynomial multiply(Polynomial other); @Override public String toString() {