package edu.neu.ccs.evergreen.util; /** * Generic polynomial class. */ public class Polynomial { /** * How close close doubles need to be to be considered equal. */ public static final double DELTA = Math.pow(10, -6); private double coefficients[] = new double[4]; /** * Create a new polynomial with the given coefficients. * * @param x_3 * Coefficient for x^3 * @param x_2 * Coefficient for x^2 * @param x_1 * Coefficient for x^1 * @param x_0 * Coefficient for x^0 */ public Polynomial(double x_3, double x_2, double x_1, double x_0) { coefficients[0] = x_0; coefficients[1] = x_1; coefficients[2] = x_2; coefficients[3] = x_3; } /** * Used internally when creating results. */ private Polynomial() { } /** * Multiple all coefficients in the polynomial by the given value. * * @param value * Value to multiply by * @return Polynomial with all values multiplied */ public Polynomial multiply(double value) { Polynomial result = new Polynomial(); for (int i = 0; i < coefficients.length; i++) { result.coefficients[i] = coefficients[i] * value; } return result; } /** * Add one polynomial to another. * * @param polynomial * Polynomial to add * @return Sum of the two polynomials */ public Polynomial add(Polynomial polynomial) { Polynomial result = new Polynomial(); for (int i = 0; i < coefficients.length; i++) { result.coefficients[i] = coefficients[i] + polynomial.coefficients[i]; } return result; } /** * Add one polynomial to another. * * @param polynomial * Polynomial to add * @return Sum of the two polynomials */ public Polynomial subtract(Polynomial polynomial) { Polynomial result = new Polynomial(); for (int i = 0; i < coefficients.length; i++) { result.coefficients[i] = coefficients[i] - polynomial.coefficients[i]; } return result; } /** * Compute and return the derivative of the polynomial. * * @return Derivative */ public Polynomial differentiate() { Polynomial result = new Polynomial(); result.coefficients[2] = coefficients[3] * 3; result.coefficients[1] = coefficients[2] * 2; result.coefficients[0] = coefficients[1]; return result; } /** * Return the coefficient for the given power. * * @param power * Power to return * @return Coefficient */ public double getCoefficient(int power) { return coefficients[power]; } /** * Determine if the value is equal to 0 within the set tolerance. * * @param value * Value to check * @return True if equal to 0 */ private boolean equalToZero(double value) { return (Math.abs(0 - value) <= DELTA); } /** * Return the degree of the polynomial. * * @return degree */ public int degree() { for (int i = 3; i > 0; i--) { if (!equalToZero(coefficients[i])) { return i; } } return 0; } /** * Solve the polynomial for when it equals 0. * * @return Array of solutions */ public double[] solve0() { int degree = degree(); if ((degree == 3) || (degree == 0)) { throw new UnsupportedOperationException("Can't solve degree " + degree + "."); } if (degree == 2) { double temp = coefficients[1] * coefficients[1] - 4 * coefficients[2] * coefficients[0]; if (temp < 0.0) { return new double[] {}; } double plus = (-coefficients[1] + Math.sqrt(temp)) / (2 * coefficients[2]); double minus = (-coefficients[1] - Math.sqrt(temp)) / (2 * coefficients[2]); return new double[] { plus, minus }; } return new double[] { (-coefficients[0]) / coefficients[1] }; } /** * Compute the value of the polynomial for the given x. * * @param x * X * @return value */ public double eval(double x) { double result = 0; for (int i = 0; i < coefficients.length; i++) { result += coefficients[i] * Math.pow(x, i); } return result; } // r(R) s r(R)-s x^s*(1-x)^(r(R)-s) x^3 x^2 x^1 x^0 // 0 0 0 x^0*(1-x)^0 0 0 0 1 // 1 0 1 x^0*(1-x)^1 0 0 -1 1 // 2 0 2 x^0*(1-x)^2 0 1 -2 1 // 3 0 3 x^0*(1-x)^3 -1 3 -3 1 // 1 1 0 x^1*(1-x)^0 0 0 1 0 // 2 1 1 x^1*(1-x)^1 0 -1 1 0 // 3 1 2 x^1*(1-x)^2 1 -2 1 0 // 2 2 0 x^2*(1-x)^0 0 1 0 0 // 3 2 1 x^2*(1-x)^1 -1 1 0 0 // 3 3 0 x^3*(1-x)^0 1 0 0 0 private static final Polynomial C00 = new Polynomial(0, 0, 0, 1); private static final Polynomial C01 = new Polynomial(0, 0, -1, 1); private static final Polynomial C02 = new Polynomial(0, 1, -2, 1); private static final Polynomial C03 = new Polynomial(-1, 3, -3, 1); private static final Polynomial C10 = new Polynomial(0, 0, 1, 0); private static final Polynomial C11 = new Polynomial(0, -1, 1, 0); private static final Polynomial C12 = new Polynomial(1, -2, 1, 0); private static final Polynomial C20 = new Polynomial(0, 1, 0, 0); private static final Polynomial C21 = new Polynomial(-1, 1, 0, 0); private static final Polynomial C30 = new Polynomial(1, 0, 0, 0); /** * Return the polynomial for the given rank and s. * * @param rank * Rank * @param s * S * @return coefficients */ public static Polynomial getPolynomial(int rank, int s) { int rank_minus_s = rank - s; if ((s == 0) && (rank_minus_s == 0)) { return C00; } if ((s == 0) && (rank_minus_s == 1)) { return C01; } if ((s == 0) && (rank_minus_s == 2)) { return C02; } if ((s == 0) && (rank_minus_s == 3)) { return C03; } if ((s == 1) && (rank_minus_s == 0)) { return C10; } if ((s == 1) && (rank_minus_s == 1)) { return C11; } if ((s == 1) && (rank_minus_s == 2)) { return C12; } if ((s == 2) && (rank_minus_s == 0)) { return C20; } if ((s == 2) && (rank_minus_s == 1)) { return C21; } if ((s == 3) && (rank_minus_s == 0)) { return C30; } throw new IllegalArgumentException("S = " + s + " and Rank = " + rank + " is not valid."); } /** * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer data = new StringBuffer(); for (int i = coefficients.length - 1; i >= 0; i--) { if (!equalToZero(coefficients[i])) { if ((data.length() > 0) && (coefficients[i] >= 0.0)) { data.append("+"); } data.append(coefficients[i]); if (i > 0) { data.append("x"); if (i > 1) { data.append("^"); data.append(i); } } } } return data.toString(); } }