Author: luc Date: Sun Feb 1 20:56:12 2009 New Revision: 739834 URL: http://svn.apache.org/viewvc?rev=739834&view=rev Log: Added add, subtract, negate, multiply and toString methods to PolynomialFunction
Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/analysis/polynomials/PolynomialFunction.java commons/proper/math/trunk/src/site/xdoc/changes.xml commons/proper/math/trunk/src/test/org/apache/commons/math/analysis/polynomials/PolynomialFunctionTest.java Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/analysis/polynomials/PolynomialFunction.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/analysis/polynomials/PolynomialFunction.java?rev=739834&r1=739833&r2=739834&view=diff ============================================================================== --- commons/proper/math/trunk/src/java/org/apache/commons/math/analysis/polynomials/PolynomialFunction.java (original) +++ commons/proper/math/trunk/src/java/org/apache/commons/math/analysis/polynomials/PolynomialFunction.java Sun Feb 1 20:56:12 2009 @@ -32,25 +32,26 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction, Serializable { /** Serializable version identifier */ - private static final long serialVersionUID = 3322454535052136809L; - + private static final long serialVersionUID = -7726511984200295583L; + /** * The coefficients of the polynomial, ordered by degree -- i.e., * coefficients[0] is the constant term and coefficients[n] is the * coefficient of x^n where n is the degree of the polynomial. */ - private double coefficients[]; + private final double coefficients[]; /** * Construct a polynomial with the given coefficients. The first element * of the coefficients array is the constant term. Higher degree * coefficients follow in sequence. The degree of the resulting polynomial - * is the length of the array minus 1. + * is the index of the last non-null element of the array, or 0 if all elements + * are null. * <p> * The constructor makes a copy of the input array and assigns the copy to * the coefficients property.</p> * - * @param c polynominal coefficients + * @param c polynomial coefficients * @throws NullPointerException if c is null * @throws IllegalArgumentException if c is empty */ @@ -59,8 +60,12 @@ if (c.length < 1) { throw new IllegalArgumentException("Polynomial coefficient array must have postive length."); } - this.coefficients = new double[c.length]; - System.arraycopy(c, 0, this.coefficients, 0, c.length); + int l = c.length; + while ((l > 1) && (c[l - 1] == 0)) { + --l; + } + this.coefficients = new double[l]; + System.arraycopy(c, 0, this.coefficients, 0, l); } /** @@ -97,9 +102,7 @@ * @return a fresh copy of the coefficients array */ public double[] getCoefficients() { - double[] out = new double[coefficients.length]; - System.arraycopy(coefficients,0, out, 0, coefficients.length); - return out; + return coefficients.clone(); } /** @@ -123,7 +126,96 @@ } return result; } - + + /** + * Add a polynomial to the instance. + * @param p polynomial to add + * @return a new polynomial which is the sum of the instance and p + */ + public PolynomialFunction add(final PolynomialFunction p) { + + // identify the lowest degree polynomial + final int lowLength = Math.min(coefficients.length, p.coefficients.length); + final int highLength = Math.max(coefficients.length, p.coefficients.length); + + // build the coefficients array + double[] newCoefficients = new double[highLength]; + for (int i = 0; i < lowLength; ++i) { + newCoefficients[i] = coefficients[i] + p.coefficients[i]; + } + System.arraycopy((coefficients.length < p.coefficients.length) ? + p.coefficients : coefficients, + lowLength, + newCoefficients, lowLength, + highLength - lowLength); + + return new PolynomialFunction(newCoefficients); + + } + + /** + * Subtract a polynomial from the instance. + * @param p polynomial to subtract + * @return a new polynomial which is the difference the instance minus p + */ + public PolynomialFunction subtract(final PolynomialFunction p) { + + // identify the lowest degree polynomial + int lowLength = Math.min(coefficients.length, p.coefficients.length); + int highLength = Math.max(coefficients.length, p.coefficients.length); + + // build the coefficients array + double[] newCoefficients = new double[highLength]; + for (int i = 0; i < lowLength; ++i) { + newCoefficients[i] = coefficients[i] - p.coefficients[i]; + } + if (coefficients.length < p.coefficients.length) { + for (int i = lowLength; i < highLength; ++i) { + newCoefficients[i] = -p.coefficients[i]; + } + } else { + System.arraycopy(coefficients, lowLength, newCoefficients, lowLength, + highLength - lowLength); + } + + return new PolynomialFunction(newCoefficients); + + } + + /** + * Negate the instance. + * @return a new polynomial + */ + public PolynomialFunction negate() { + double[] newCoefficients = new double[coefficients.length]; + for (int i = 0; i < coefficients.length; ++i) { + newCoefficients[i] = -coefficients[i]; + } + return new PolynomialFunction(newCoefficients); + } + + /** + * Multiply the instance by a polynomial. + * @param p polynomial to multiply by + * @return a new polynomial + */ + public PolynomialFunction multiply(final PolynomialFunction p) { + + double[] newCoefficients = new double[coefficients.length + p.coefficients.length - 1]; + + for (int i = 0; i < newCoefficients.length; ++i) { + newCoefficients[i] = 0.0; + for (int j = Math.max(0, i + 1 - p.coefficients.length); + j < Math.min(coefficients.length, i + 1); + ++j) { + newCoefficients[i] += coefficients[j] * p.coefficients[i-j]; + } + } + + return new PolynomialFunction(newCoefficients); + + } + /** * Returns the coefficients of the derivative of the polynomial with the given coefficients. * @@ -164,5 +256,66 @@ public UnivariateRealFunction derivative() { return polynomialDerivative(); } - + + /** Returns a string representation of the polynomial. + + * <p>The representation is user oriented. Terms are displayed lowest + * degrees first. The multiplications signs, coefficients equals to + * one and null terms are not displayed (except if the polynomial is 0, + * in which case the 0 constant term is displayed). Addition of terms + * with negative coefficients are replaced by subtraction of terms + * with positive coefficients except for the first displayed term + * (i.e. we display <code>-3</code> for a constant negative polynomial, + * but <code>1 - 3 x + x^2</code> if the negative coefficient is not + * the first one displayed).</p> + + * @return a string representation of the polynomial + + */ + public String toString() { + + StringBuffer s = new StringBuffer(); + if (coefficients[0] == 0.0) { + if (coefficients.length == 1) { + return "0"; + } + } else { + s.append(Double.toString(coefficients[0])); + } + + for (int i = 1; i < coefficients.length; ++i) { + + if (coefficients[i] != 0) { + + if (s.length() > 0) { + if (coefficients[i] < 0) { + s.append(" - "); + } else { + s.append(" + "); + } + } else { + if (coefficients[i] < 0) { + s.append("-"); + } + } + + double absAi = Math.abs(coefficients[i]); + if ((absAi - 1) != 0) { + s.append(Double.toString(absAi)); + s.append(' '); + } + + s.append("x"); + if (i > 1) { + s.append('^'); + s.append(Integer.toString(i)); + } + } + + } + + return s.toString(); + + } + } Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=739834&r1=739833&r2=739834&view=diff ============================================================================== --- commons/proper/math/trunk/src/site/xdoc/changes.xml (original) +++ commons/proper/math/trunk/src/site/xdoc/changes.xml Sun Feb 1 20:56:12 2009 @@ -39,6 +39,9 @@ </properties> <body> <release version="2.0" date="TBD" description="TBD"> + <action dev="luc" type="add" > + Added add, subtract, negate, multiply and toString methods to PolynomialFunction. + </action> <action dev="psteitz" type="update" issue="MATH-189"> Changed FractionFormat to extend NumberFormat. </action> Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/analysis/polynomials/PolynomialFunctionTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/analysis/polynomials/PolynomialFunctionTest.java?rev=739834&r1=739833&r2=739834&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/org/apache/commons/math/analysis/polynomials/PolynomialFunctionTest.java (original) +++ commons/proper/math/trunk/src/test/org/apache/commons/math/analysis/polynomials/PolynomialFunctionTest.java Sun Feb 1 20:56:12 2009 @@ -160,4 +160,80 @@ } + public void testString() { + PolynomialFunction p = new PolynomialFunction(new double[] { -5.0, 3.0, 1.0 }); + checkPolynomial(p, "-5.0 + 3.0 x + x^2"); + checkPolynomial(new PolynomialFunction(new double[] { 0.0, -2.0, 3.0 }), + "-2.0 x + 3.0 x^2"); + checkPolynomial(new PolynomialFunction(new double[] { 1.0, -2.0, 3.0 }), + "1.0 - 2.0 x + 3.0 x^2"); + checkPolynomial(new PolynomialFunction(new double[] { 0.0, 2.0, 3.0 }), + "2.0 x + 3.0 x^2"); + checkPolynomial(new PolynomialFunction(new double[] { 1.0, 2.0, 3.0 }), + "1.0 + 2.0 x + 3.0 x^2"); + checkPolynomial(new PolynomialFunction(new double[] { 1.0, 0.0, 3.0 }), + "1.0 + 3.0 x^2"); + checkPolynomial(new PolynomialFunction(new double[] { 0.0 }), + "0"); + } + + public void testAddition() { + + PolynomialFunction p1 = new PolynomialFunction(new double[] { -2.0, 1.0 }); + PolynomialFunction p2 = new PolynomialFunction(new double[] { 2.0, -1.0, 0.0 }); + checkNullPolynomial(p1.add(p2)); + + p2 = p1.add(p1); + checkPolynomial(p2, "-4.0 + 2.0 x"); + + p1 = new PolynomialFunction(new double[] { 1.0, -4.0, 2.0 }); + p2 = new PolynomialFunction(new double[] { -1.0, 3.0, -2.0 }); + p1 = p1.add(p2); + assertEquals(1, p1.degree()); + checkPolynomial(p1, "-x"); + + } + + public void testSubtraction() { + + PolynomialFunction p1 = new PolynomialFunction(new double[] { -2.0, 1.0 }); + checkNullPolynomial(p1.subtract(p1)); + + PolynomialFunction p2 = new PolynomialFunction(new double[] { -2.0, 6.0 }); + p2 = p2.subtract(p1); + checkPolynomial(p2, "5.0 x"); + + p1 = new PolynomialFunction(new double[] { 1.0, -4.0, 2.0 }); + p2 = new PolynomialFunction(new double[] { -1.0, 3.0, 2.0 }); + p1 = p1.subtract(p2); + assertEquals(1, p1.degree()); + checkPolynomial(p1, "2.0 - 7.0 x"); + + } + + public void testMultiplication() { + + PolynomialFunction p1 = new PolynomialFunction(new double[] { -3.0, 2.0 }); + PolynomialFunction p2 = new PolynomialFunction(new double[] { 3.0, 2.0, 1.0 }); + checkPolynomial(p1.multiply(p2), "-9.0 + x^2 + 2.0 x^3"); + + p1 = new PolynomialFunction(new double[] { 0.0, 1.0 }); + p2 = p1; + for (int i = 2; i < 10; ++i) { + p2 = p2.multiply(p1); + checkPolynomial(p2, "x^" + i); + } + + } + + public void checkPolynomial(PolynomialFunction p, String reference) { + assertEquals(reference, p.toString()); + } + + private void checkNullPolynomial(PolynomialFunction p) { + for (double coefficient : p.getCoefficients()) { + assertEquals(0.0, coefficient, 1.0e-15); + } + } + }