Simplified string representation (when a coefficient is an integer number).
Upgraded unit tests to JUnit 4.
Code and Javadoc formatting clean-up.


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1075048 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2011-02-27 12:58:10 +00:00
parent 3402d1c3c9
commit 4117b2a53a
3 changed files with 270 additions and 263 deletions

View File

@ -29,17 +29,15 @@ import org.apache.commons.math.util.FastMath;
* Immutable representation of a real polynomial function with real coefficients. * Immutable representation of a real polynomial function with real coefficients.
* <p> * <p>
* <a href="http://mathworld.wolfram.com/HornersMethod.html">Horner's Method</a> * <a href="http://mathworld.wolfram.com/HornersMethod.html">Horner's Method</a>
* is used to evaluate the function.</p> * is used to evaluate the function.</p>
* *
* @version $Revision$ $Date$ * @version $Revision$ $Date$
*/ */
public class PolynomialFunction implements DifferentiableUnivariateRealFunction, Serializable { public class PolynomialFunction implements DifferentiableUnivariateRealFunction, Serializable {
/** /**
* Serialization identifier * Serialization identifier
*/ */
private static final long serialVersionUID = -7726511984200295583L; private static final long serialVersionUID = -7726511984200295583L;
/** /**
* The coefficients of the polynomial, ordered by degree -- i.e., * The coefficients of the polynomial, ordered by degree -- i.e.,
* coefficients[0] is the constant term and coefficients[n] is the * coefficients[0] is the constant term and coefficients[n] is the
@ -57,9 +55,9 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
* The constructor makes a copy of the input array and assigns the copy to * The constructor makes a copy of the input array and assigns the copy to
* the coefficients property.</p> * the coefficients property.</p>
* *
* @param c polynomial coefficients * @param c Polynomial coefficients.
* @throws NullPointerException if c is null * @throws NullPointerException if {@code c} is {@code null}.
* @throws NoDataException if c is empty * @throws NoDataException if {@code c} is empty.
*/ */
public PolynomialFunction(double c[]) { public PolynomialFunction(double c[]) {
super(); super();
@ -77,23 +75,22 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
/** /**
* Compute the value of the function for the given argument. * Compute the value of the function for the given argument.
* <p> * <p>
* The value returned is <br> * The value returned is <br/>
* <code>coefficients[n] * x^n + ... + coefficients[1] * x + coefficients[0]</code> * <code>coefficients[n] * x^n + ... + coefficients[1] * x + coefficients[0]</code>
* </p> * </p>
* *
* @param x the argument for which the function value should be computed * @param x Argument for which the function value should be computed.
* @return the value of the polynomial at the given point * @return the value of the polynomial at the given point.
* @see UnivariateRealFunction#value(double) * @see UnivariateRealFunction#value(double)
*/ */
public double value(double x) { public double value(double x) {
return evaluate(coefficients, x); return evaluate(coefficients, x);
} }
/** /**
* Returns the degree of the polynomial * Returns the degree of the polynomial.
* *
* @return the degree of the polynomial * @return the degree of the polynomial.
*/ */
public int degree() { public int degree() {
return coefficients.length - 1; return coefficients.length - 1;
@ -105,7 +102,7 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
* Changes made to the returned copy will not affect the coefficients of * Changes made to the returned copy will not affect the coefficients of
* the polynomial.</p> * the polynomial.</p>
* *
* @return a fresh copy of the coefficients array * @return a fresh copy of the coefficients array.
*/ */
public double[] getCoefficients() { public double[] getCoefficients() {
return coefficients.clone(); return coefficients.clone();
@ -115,11 +112,11 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
* Uses Horner's Method to evaluate the polynomial with the given coefficients at * Uses Horner's Method to evaluate the polynomial with the given coefficients at
* the argument. * the argument.
* *
* @param coefficients the coefficients of the polynomial to evaluate * @param coefficients Coefficients of the polynomial to evaluate.
* @param argument the input value * @param argument Input value.
* @return the value of the polynomial * @return the value of the polynomial.
* @throws NoDataException if coefficients is empty * @throws NoDataException if {@code coefficients} is empty.
* @throws NullPointerException if coefficients is null * @throws NullPointerException if {@code coefficients} is {@code null}.
*/ */
protected static double evaluate(double[] coefficients, double argument) { protected static double evaluate(double[] coefficients, double argument) {
int n = coefficients.length; int n = coefficients.length;
@ -135,11 +132,11 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
/** /**
* Add a polynomial to the instance. * Add a polynomial to the instance.
* @param p polynomial to add *
* @return a new polynomial which is the sum of the instance and p * @param p Polynomial to add.
* @return a new polynomial which is the sum of the instance and {@code p}.
*/ */
public PolynomialFunction add(final PolynomialFunction p) { public PolynomialFunction add(final PolynomialFunction p) {
// identify the lowest degree polynomial // identify the lowest degree polynomial
final int lowLength = FastMath.min(coefficients.length, p.coefficients.length); final int lowLength = FastMath.min(coefficients.length, p.coefficients.length);
final int highLength = FastMath.max(coefficients.length, p.coefficients.length); final int highLength = FastMath.max(coefficients.length, p.coefficients.length);
@ -156,16 +153,15 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
highLength - lowLength); highLength - lowLength);
return new PolynomialFunction(newCoefficients); return new PolynomialFunction(newCoefficients);
} }
/** /**
* Subtract a polynomial from the instance. * Subtract a polynomial from the instance.
* @param p polynomial to subtract *
* @return a new polynomial which is the difference the instance minus p * @param p Polynomial to subtract.
* @return a new polynomial which is the difference the instance minus {@code p}.
*/ */
public PolynomialFunction subtract(final PolynomialFunction p) { public PolynomialFunction subtract(final PolynomialFunction p) {
// identify the lowest degree polynomial // identify the lowest degree polynomial
int lowLength = FastMath.min(coefficients.length, p.coefficients.length); int lowLength = FastMath.min(coefficients.length, p.coefficients.length);
int highLength = FastMath.max(coefficients.length, p.coefficients.length); int highLength = FastMath.max(coefficients.length, p.coefficients.length);
@ -185,12 +181,12 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
} }
return new PolynomialFunction(newCoefficients); return new PolynomialFunction(newCoefficients);
} }
/** /**
* Negate the instance. * Negate the instance.
* @return a new polynomial *
* @return a new polynomial.
*/ */
public PolynomialFunction negate() { public PolynomialFunction negate() {
double[] newCoefficients = new double[coefficients.length]; double[] newCoefficients = new double[coefficients.length];
@ -202,11 +198,11 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
/** /**
* Multiply the instance by a polynomial. * Multiply the instance by a polynomial.
* @param p polynomial to multiply by *
* @return a new polynomial * @param p Polynomial to multiply by.
* @return a new polynomial.
*/ */
public PolynomialFunction multiply(final PolynomialFunction p) { public PolynomialFunction multiply(final PolynomialFunction p) {
double[] newCoefficients = new double[coefficients.length + p.coefficients.length - 1]; double[] newCoefficients = new double[coefficients.length + p.coefficients.length - 1];
for (int i = 0; i < newCoefficients.length; ++i) { for (int i = 0; i < newCoefficients.length; ++i) {
@ -219,16 +215,15 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
} }
return new PolynomialFunction(newCoefficients); return new PolynomialFunction(newCoefficients);
} }
/** /**
* Returns the coefficients of the derivative of the polynomial with the given coefficients. * Returns the coefficients of the derivative of the polynomial with the given coefficients.
* *
* @param coefficients the coefficients of the polynomial to differentiate * @param coefficients Coefficients of the polynomial to differentiate.
* @return the coefficients of the derivative or null if coefficients has length 1. * @return the coefficients of the derivative or {@code null} if coefficients has length 1.
* @throws NoDataException if coefficients is empty * @throws NoDataException if {@code coefficients} is empty.
* @throws NullPointerException if coefficients is null * @throws NullPointerException if {@code coefficients} is {@code null}.
*/ */
protected static double[] differentiate(double[] coefficients) { protected static double[] differentiate(double[] coefficients) {
int n = coefficients.length; int n = coefficients.length;
@ -239,32 +234,33 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
return new double[]{0}; return new double[]{0};
} }
double[] result = new double[n - 1]; double[] result = new double[n - 1];
for (int i = n - 1; i > 0; i--) { for (int i = n - 1; i > 0; i--) {
result[i - 1] = i * coefficients[i]; result[i - 1] = i * coefficients[i];
} }
return result; return result;
} }
/** /**
* Returns the derivative as a PolynomialRealFunction * Returns the derivative as a {@link PolynomialFunction}.
* *
* @return the derivative polynomial * @return the derivative polynomial.
*/ */
public PolynomialFunction polynomialDerivative() { public PolynomialFunction polynomialDerivative() {
return new PolynomialFunction(differentiate(coefficients)); return new PolynomialFunction(differentiate(coefficients));
} }
/** /**
* Returns the derivative as a UnivariateRealFunction * Returns the derivative as a {@link UnivariateRealFunction}.
* *
* @return the derivative function * @return the derivative function.
*/ */
public UnivariateRealFunction derivative() { public UnivariateRealFunction derivative() {
return polynomialDerivative(); return polynomialDerivative();
} }
/** Returns a string representation of the polynomial. /**
* Returns a string representation of the polynomial.
*
* <p>The representation is user oriented. Terms are displayed lowest * <p>The representation is user oriented. Terms are displayed lowest
* degrees first. The multiplications signs, coefficients equals to * degrees first. The multiplications signs, coefficients equals to
* one and null terms are not displayed (except if the polynomial is 0, * one and null terms are not displayed (except if the polynomial is 0,
@ -274,56 +270,67 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
* (i.e. we display <code>-3</code> for a constant negative polynomial, * (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 * but <code>1 - 3 x + x^2</code> if the negative coefficient is not
* the first one displayed).</p> * the first one displayed).</p>
*
* @return a string representation of the polynomial * @return a string representation of the polynomial.
*/ */
@Override @Override
public String toString() { public String toString() {
StringBuilder s = new StringBuilder();
if (coefficients[0] == 0.0) {
if (coefficients.length == 1) {
return "0";
}
} else {
// s.append(Double.toString(coefficients[0])); XXX
s.append(toString(coefficients[0]));
}
StringBuilder s = new StringBuilder(); for (int i = 1; i < coefficients.length; ++i) {
if (coefficients[0] == 0.0) { if (coefficients[i] != 0) {
if (coefficients.length == 1) { if (s.length() > 0) {
return "0"; if (coefficients[i] < 0) {
} s.append(" - ");
} else { } else {
s.append(Double.toString(coefficients[0])); s.append(" + ");
} }
} else {
if (coefficients[i] < 0) {
s.append("-");
}
}
for (int i = 1; i < coefficients.length; ++i) { double absAi = FastMath.abs(coefficients[i]);
if ((absAi - 1) != 0) {
// s.append(Double.toString(absAi)); XXX
s.append(toString(absAi));
s.append(' ');
}
if (coefficients[i] != 0) { s.append("x");
if (i > 1) {
s.append('^');
s.append(Integer.toString(i));
}
}
}
if (s.length() > 0) { return s.toString();
if (coefficients[i] < 0) { }
s.append(" - ");
} else {
s.append(" + ");
}
} else {
if (coefficients[i] < 0) {
s.append("-");
}
}
double absAi = FastMath.abs(coefficients[i]); /**
if ((absAi - 1) != 0) { * Creates a string representing a coefficient, removing ".0" endings.
s.append(Double.toString(absAi)); *
s.append(' '); * @param coeff Coefficient.
} * @return a string representation of {@code coeff}.
*/
s.append("x"); private static String toString(double coeff) {
if (i > 1) { final String c = Double.toString(coeff);
s.append('^'); if (c.endsWith(".0")) {
s.append(Integer.toString(i)); return c.substring(0, c.length() - 2);
} } else {
} return c;
}
} }
return s.toString();
}
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
@ -337,14 +344,16 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) if (this == obj) {
return true; return true;
if (!(obj instanceof PolynomialFunction)) }
if (!(obj instanceof PolynomialFunction)) {
return false; return false;
}
PolynomialFunction other = (PolynomialFunction) obj; PolynomialFunction other = (PolynomialFunction) obj;
if (!Arrays.equals(coefficients, other.coefficients)) if (!Arrays.equals(coefficients, other.coefficients)) {
return false; return false;
}
return true; return true;
} }
} }

View File

@ -18,40 +18,40 @@ package org.apache.commons.math.analysis.polynomials;
import org.apache.commons.math.TestUtils; import org.apache.commons.math.TestUtils;
import org.apache.commons.math.util.FastMath; import org.apache.commons.math.util.FastMath;
// junit
import junit.framework.TestCase; import org.junit.Test;
import org.junit.Assert;
/** /**
* Tests the PolynomialFunction implementation of a UnivariateRealFunction. * Tests the PolynomialFunction implementation of a UnivariateRealFunction.
* *
* @version $Revision$ * @version $Revision$
* @author Matt Cliff <matt@mattcliff.com>
*/ */
public final class PolynomialFunctionTest extends TestCase { public final class PolynomialFunctionTest {
/** Error tolerance for tests */ /** Error tolerance for tests */
protected double tolerance = 1.0e-12; protected double tolerance = 1e-12;
/** /**
* tests the value of a constant polynomial. * tests the value of a constant polynomial.
* *
* <p>value of this is 2.5 everywhere.</p> * <p>value of this is 2.5 everywhere.</p>
*/ */
@Test
public void testConstants() { public void testConstants() {
double[] c = { 2.5 }; double[] c = { 2.5 };
PolynomialFunction f = new PolynomialFunction( c ); PolynomialFunction f = new PolynomialFunction(c);
// verify that we are equal to c[0] at several (nonsymmetric) places // verify that we are equal to c[0] at several (nonsymmetric) places
assertEquals( f.value( 0.0), c[0], tolerance ); Assert.assertEquals(f.value(0), c[0], tolerance);
assertEquals( f.value( -1.0), c[0], tolerance ); Assert.assertEquals(f.value(-1), c[0], tolerance);
assertEquals( f.value( -123.5), c[0], tolerance ); Assert.assertEquals(f.value(-123.5), c[0], tolerance);
assertEquals( f.value( 3.0), c[0], tolerance ); Assert.assertEquals(f.value(3), c[0], tolerance);
assertEquals( f.value( 456.89), c[0], tolerance ); Assert.assertEquals(f.value(456.89), c[0], tolerance);
assertEquals(f.degree(), 0); Assert.assertEquals(f.degree(), 0);
assertEquals(f.derivative().value(0), 0, tolerance); Assert.assertEquals(f.derivative().value(0), 0, tolerance);
assertEquals(f.polynomialDerivative().derivative().value(0), 0, tolerance); Assert.assertEquals(f.polynomialDerivative().derivative().value(0), 0, tolerance);
} }
/** /**
@ -59,77 +59,72 @@ public final class PolynomialFunctionTest extends TestCase {
* *
* <p>This will test the function f(x) = 3*x - 1.5</p> * <p>This will test the function f(x) = 3*x - 1.5</p>
* <p>This will have the values * <p>This will have the values
* <tt>f(0.0) = -1.5, f(-1.0) = -4.5, f(-2.5) = -9.0, * <tt>f(0) = -1.5, f(-1) = -4.5, f(-2.5) = -9,
* f(0.5) = 0.0, f(1.5) = 3.0</tt> and <tt>f(3.0) = 7.5</tt> * f(0.5) = 0, f(1.5) = 3</tt> and <tt>f(3) = 7.5</tt>
* </p> * </p>
*/ */
@Test
public void testLinear() { public void testLinear() {
double[] c = { -1.5, 3.0 }; double[] c = { -1.5, 3 };
PolynomialFunction f = new PolynomialFunction( c ); PolynomialFunction f = new PolynomialFunction(c);
// verify that we are equal to c[0] when x=0 // verify that we are equal to c[0] when x=0
assertEquals( f.value( 0.0), c[0], tolerance ); Assert.assertEquals(f.value(0), c[0], tolerance);
// now check a few other places // now check a few other places
assertEquals( -4.5, f.value( -1.0), tolerance ); Assert.assertEquals(-4.5, f.value(-1), tolerance);
assertEquals( -9.0, f.value( -2.5), tolerance ); Assert.assertEquals(-9, f.value(-2.5), tolerance);
assertEquals( 0.0, f.value( 0.5), tolerance ); Assert.assertEquals(0, f.value(0.5), tolerance);
assertEquals( 3.0, f.value( 1.5), tolerance ); Assert.assertEquals(3, f.value(1.5), tolerance);
assertEquals( 7.5, f.value( 3.0), tolerance ); Assert.assertEquals(7.5, f.value(3), tolerance);
assertEquals(f.degree(), 1); Assert.assertEquals(f.degree(), 1);
assertEquals(f.polynomialDerivative().derivative().value(0), 0, tolerance);
Assert.assertEquals(f.polynomialDerivative().derivative().value(0), 0, tolerance);
} }
/** /**
* Tests a second order polynomial. * Tests a second order polynomial.
* <p> This will test the function f(x) = 2x^2 - 3x -2 = (2x+1)(x-2)</p> * <p> This will test the function f(x) = 2x^2 - 3x -2 = (2x+1)(x-2)</p>
*
*/ */
@Test
public void testQuadratic() { public void testQuadratic() {
double[] c = { -2.0, -3.0, 2.0 }; double[] c = { -2, -3, 2 };
PolynomialFunction f = new PolynomialFunction( c ); PolynomialFunction f = new PolynomialFunction(c);
// verify that we are equal to c[0] when x=0 // verify that we are equal to c[0] when x=0
assertEquals( f.value( 0.0), c[0], tolerance ); Assert.assertEquals(f.value(0), c[0], tolerance);
// now check a few other places // now check a few other places
assertEquals( 0.0, f.value( -0.5), tolerance ); Assert.assertEquals(0, f.value(-0.5), tolerance);
assertEquals( 0.0, f.value( 2.0), tolerance ); Assert.assertEquals(0, f.value(2), tolerance);
assertEquals( -2.0, f.value( 1.5), tolerance ); Assert.assertEquals(-2, f.value(1.5), tolerance);
assertEquals( 7.0, f.value( -1.5), tolerance ); Assert.assertEquals(7, f.value(-1.5), tolerance);
assertEquals( 265.5312, f.value( 12.34), tolerance ); Assert.assertEquals(265.5312, f.value(12.34), tolerance);
} }
/** /**
* This will test the quintic function * This will test the quintic function
* f(x) = x^2(x-5)(x+3)(x-1) = x^5 - 3x^4 -13x^3 + 15x^2</p> * f(x) = x^2(x-5)(x+3)(x-1) = x^5 - 3x^4 -13x^3 + 15x^2</p>
*
*/ */
@Test
public void testQuintic() { public void testQuintic() {
double[] c = { 0.0, 0.0, 15.0, -13.0, -3.0, 1.0 }; double[] c = { 0, 0, 15, -13, -3, 1 };
PolynomialFunction f = new PolynomialFunction( c ); PolynomialFunction f = new PolynomialFunction(c);
// verify that we are equal to c[0] when x=0 // verify that we are equal to c[0] when x=0
assertEquals( f.value( 0.0), c[0], tolerance ); Assert.assertEquals(f.value(0), c[0], tolerance);
// now check a few other places // now check a few other places
assertEquals( 0.0, f.value( 5.0), tolerance ); Assert.assertEquals(0, f.value(5), tolerance);
assertEquals( 0.0, f.value( 1.0), tolerance ); Assert.assertEquals(0, f.value(1), tolerance);
assertEquals( 0.0, f.value( -3.0), tolerance ); Assert.assertEquals(0, f.value(-3), tolerance);
assertEquals( 54.84375, f.value( -1.5), tolerance ); Assert.assertEquals(54.84375, f.value(-1.5), tolerance);
assertEquals( -8.06637, f.value( 1.3), tolerance ); Assert.assertEquals(-8.06637, f.value(1.3), tolerance);
assertEquals(f.degree(), 5);
Assert.assertEquals(f.degree(), 5);
} }
/** /**
* tests the firstDerivative function by comparison * tests the firstDerivative function by comparison
* *
@ -137,97 +132,96 @@ public final class PolynomialFunctionTest extends TestCase {
* <tt>f(x) = x^3 - 2x^2 + 6x + 3, g(x) = 3x^2 - 4x + 6</tt> * <tt>f(x) = x^3 - 2x^2 + 6x + 3, g(x) = 3x^2 - 4x + 6</tt>
* and <tt>h(x) = 6x - 4</tt> * and <tt>h(x) = 6x - 4</tt>
*/ */
@Test
public void testfirstDerivativeComparison() { public void testfirstDerivativeComparison() {
double[] f_coeff = { 3.0, 6.0, -2.0, 1.0 }; double[] f_coeff = { 3, 6, -2, 1 };
double[] g_coeff = { 6.0, -4.0, 3.0 }; double[] g_coeff = { 6, -4, 3 };
double[] h_coeff = { -4.0, 6.0 }; double[] h_coeff = { -4, 6 };
PolynomialFunction f = new PolynomialFunction( f_coeff ); PolynomialFunction f = new PolynomialFunction(f_coeff);
PolynomialFunction g = new PolynomialFunction( g_coeff ); PolynomialFunction g = new PolynomialFunction(g_coeff);
PolynomialFunction h = new PolynomialFunction( h_coeff ); PolynomialFunction h = new PolynomialFunction(h_coeff);
// compare f' = g // compare f' = g
assertEquals( f.derivative().value(0.0), g.value(0.0), tolerance ); Assert.assertEquals(f.derivative().value(0), g.value(0), tolerance);
assertEquals( f.derivative().value(1.0), g.value(1.0), tolerance ); Assert.assertEquals(f.derivative().value(1), g.value(1), tolerance);
assertEquals( f.derivative().value(100.0), g.value(100.0), tolerance ); Assert.assertEquals(f.derivative().value(100), g.value(100), tolerance);
assertEquals( f.derivative().value(4.1), g.value(4.1), tolerance ); Assert.assertEquals(f.derivative().value(4.1), g.value(4.1), tolerance);
assertEquals( f.derivative().value(-3.25), g.value(-3.25), tolerance ); Assert.assertEquals(f.derivative().value(-3.25), g.value(-3.25), tolerance);
// compare g' = h // compare g' = h
assertEquals( g.derivative().value(FastMath.PI), h.value(FastMath.PI), tolerance ); Assert.assertEquals(g.derivative().value(FastMath.PI), h.value(FastMath.PI), tolerance);
assertEquals( g.derivative().value(FastMath.E), h.value(FastMath.E), tolerance ); Assert.assertEquals(g.derivative().value(FastMath.E), h.value(FastMath.E), tolerance);
} }
@Test
public void testString() { public void testString() {
PolynomialFunction p = new PolynomialFunction(new double[] { -5.0, 3.0, 1.0 }); PolynomialFunction p = new PolynomialFunction(new double[] { -5, 3, 1 });
checkPolynomial(p, "-5.0 + 3.0 x + x^2"); checkPolynomial(p, "-5 + 3 x + x^2");
checkPolynomial(new PolynomialFunction(new double[] { 0.0, -2.0, 3.0 }), checkPolynomial(new PolynomialFunction(new double[] { 0, -2, 3 }),
"-2.0 x + 3.0 x^2"); "-2 x + 3 x^2");
checkPolynomial(new PolynomialFunction(new double[] { 1.0, -2.0, 3.0 }), checkPolynomial(new PolynomialFunction(new double[] { 1, -2, 3 }),
"1.0 - 2.0 x + 3.0 x^2"); "1 - 2 x + 3 x^2");
checkPolynomial(new PolynomialFunction(new double[] { 0.0, 2.0, 3.0 }), checkPolynomial(new PolynomialFunction(new double[] { 0, 2, 3 }),
"2.0 x + 3.0 x^2"); "2 x + 3 x^2");
checkPolynomial(new PolynomialFunction(new double[] { 1.0, 2.0, 3.0 }), checkPolynomial(new PolynomialFunction(new double[] { 1, 2, 3 }),
"1.0 + 2.0 x + 3.0 x^2"); "1 + 2 x + 3 x^2");
checkPolynomial(new PolynomialFunction(new double[] { 1.0, 0.0, 3.0 }), checkPolynomial(new PolynomialFunction(new double[] { 1, 0, 3 }),
"1.0 + 3.0 x^2"); "1 + 3 x^2");
checkPolynomial(new PolynomialFunction(new double[] { 0.0 }), checkPolynomial(new PolynomialFunction(new double[] { 0 }),
"0"); "0");
} }
@Test
public void testAddition() { public void testAddition() {
PolynomialFunction p1 = new PolynomialFunction(new double[] { -2, 1 });
PolynomialFunction p1 = new PolynomialFunction(new double[] { -2.0, 1.0 }); PolynomialFunction p2 = new PolynomialFunction(new double[] { 2, -1, 0 });
PolynomialFunction p2 = new PolynomialFunction(new double[] { 2.0, -1.0, 0.0 });
checkNullPolynomial(p1.add(p2)); checkNullPolynomial(p1.add(p2));
p2 = p1.add(p1); p2 = p1.add(p1);
checkPolynomial(p2, "-4.0 + 2.0 x"); checkPolynomial(p2, "-4 + 2 x");
p1 = new PolynomialFunction(new double[] { 1.0, -4.0, 2.0 }); p1 = new PolynomialFunction(new double[] { 1, -4, 2 });
p2 = new PolynomialFunction(new double[] { -1.0, 3.0, -2.0 }); p2 = new PolynomialFunction(new double[] { -1, 3, -2 });
p1 = p1.add(p2); p1 = p1.add(p2);
assertEquals(1, p1.degree()); Assert.assertEquals(1, p1.degree());
checkPolynomial(p1, "-x"); checkPolynomial(p1, "-x");
} }
@Test
public void testSubtraction() { public void testSubtraction() {
PolynomialFunction p1 = new PolynomialFunction(new double[] { -2, 1 });
PolynomialFunction p1 = new PolynomialFunction(new double[] { -2.0, 1.0 });
checkNullPolynomial(p1.subtract(p1)); checkNullPolynomial(p1.subtract(p1));
PolynomialFunction p2 = new PolynomialFunction(new double[] { -2.0, 6.0 }); PolynomialFunction p2 = new PolynomialFunction(new double[] { -2, 6 });
p2 = p2.subtract(p1); p2 = p2.subtract(p1);
checkPolynomial(p2, "5.0 x"); checkPolynomial(p2, "5 x");
p1 = new PolynomialFunction(new double[] { 1.0, -4.0, 2.0 }); p1 = new PolynomialFunction(new double[] { 1, -4, 2 });
p2 = new PolynomialFunction(new double[] { -1.0, 3.0, 2.0 }); p2 = new PolynomialFunction(new double[] { -1, 3, 2 });
p1 = p1.subtract(p2); p1 = p1.subtract(p2);
assertEquals(1, p1.degree()); Assert.assertEquals(1, p1.degree());
checkPolynomial(p1, "2.0 - 7.0 x"); checkPolynomial(p1, "2 - 7 x");
} }
@Test
public void testMultiplication() { public void testMultiplication() {
PolynomialFunction p1 = new PolynomialFunction(new double[] { -3, 2 });
PolynomialFunction p2 = new PolynomialFunction(new double[] { 3, 2, 1 });
checkPolynomial(p1.multiply(p2), "-9 + x^2 + 2 x^3");
PolynomialFunction p1 = new PolynomialFunction(new double[] { -3.0, 2.0 }); p1 = new PolynomialFunction(new double[] { 0, 1 });
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; p2 = p1;
for (int i = 2; i < 10; ++i) { for (int i = 2; i < 10; ++i) {
p2 = p2.multiply(p1); p2 = p2.multiply(p1);
checkPolynomial(p2, "x^" + i); checkPolynomial(p2, "x^" + i);
} }
} }
@Test
public void testSerial() { public void testSerial() {
PolynomialFunction p2 = new PolynomialFunction(new double[] { 3.0, 2.0, 1.0 }); PolynomialFunction p2 = new PolynomialFunction(new double[] { 3, 2, 1 });
assertEquals(p2, TestUtils.serializeAndRecover(p2)); Assert.assertEquals(p2, TestUtils.serializeAndRecover(p2));
} }
/** /**
@ -237,35 +231,35 @@ public final class PolynomialFunctionTest extends TestCase {
* <tt>f(x) = x^3 - 2x^2 + 6x + 3, g(x) = 3x^2 - 4x + 6</tt> * <tt>f(x) = x^3 - 2x^2 + 6x + 3, g(x) = 3x^2 - 4x + 6</tt>
* and <tt>h(x) = 6x - 4</tt> * and <tt>h(x) = 6x - 4</tt>
*/ */
@Test
public void testMath341() { public void testMath341() {
double[] f_coeff = { 3.0, 6.0, -2.0, 1.0 }; double[] f_coeff = { 3, 6, -2, 1 };
double[] g_coeff = { 6.0, -4.0, 3.0 }; double[] g_coeff = { 6, -4, 3 };
double[] h_coeff = { -4.0, 6.0 }; double[] h_coeff = { -4, 6 };
PolynomialFunction f = new PolynomialFunction( f_coeff ); PolynomialFunction f = new PolynomialFunction(f_coeff);
PolynomialFunction g = new PolynomialFunction( g_coeff ); PolynomialFunction g = new PolynomialFunction(g_coeff);
PolynomialFunction h = new PolynomialFunction( h_coeff ); PolynomialFunction h = new PolynomialFunction(h_coeff);
// compare f' = g // compare f' = g
assertEquals( f.derivative().value(0.0), g.value(0.0), tolerance ); Assert.assertEquals(f.derivative().value(0), g.value(0), tolerance);
assertEquals( f.derivative().value(1.0), g.value(1.0), tolerance ); Assert.assertEquals(f.derivative().value(1), g.value(1), tolerance);
assertEquals( f.derivative().value(100.0), g.value(100.0), tolerance ); Assert.assertEquals(f.derivative().value(100), g.value(100), tolerance);
assertEquals( f.derivative().value(4.1), g.value(4.1), tolerance ); Assert.assertEquals(f.derivative().value(4.1), g.value(4.1), tolerance);
assertEquals( f.derivative().value(-3.25), g.value(-3.25), tolerance ); Assert.assertEquals(f.derivative().value(-3.25), g.value(-3.25), tolerance);
// compare g' = h // compare g' = h
assertEquals( g.derivative().value(FastMath.PI), h.value(FastMath.PI), tolerance ); Assert.assertEquals(g.derivative().value(FastMath.PI), h.value(FastMath.PI), tolerance);
assertEquals( g.derivative().value(FastMath.E), h.value(FastMath.E), tolerance ); Assert.assertEquals(g.derivative().value(FastMath.E), h.value(FastMath.E), tolerance);
} }
public void checkPolynomial(PolynomialFunction p, String reference) { public void checkPolynomial(PolynomialFunction p, String reference) {
assertEquals(reference, p.toString()); Assert.assertEquals(reference, p.toString());
} }
private void checkNullPolynomial(PolynomialFunction p) { private void checkNullPolynomial(PolynomialFunction p) {
for (double coefficient : p.getCoefficients()) { for (double coefficient : p.getCoefficients()) {
assertEquals(0.0, coefficient, 1.0e-15); Assert.assertEquals(0, coefficient, 1e-15);
} }
} }
} }

View File

@ -18,38 +18,41 @@ package org.apache.commons.math.analysis.polynomials;
import org.apache.commons.math.util.FastMath; import org.apache.commons.math.util.FastMath;
import junit.framework.TestCase; import org.junit.Test;
import org.junit.Assert;
/** /**
* Tests the PolynomialsUtils class. * Tests the PolynomialsUtils class.
* *
* @version $Revision$ $Date$ * @version $Revision$ $Date$
*/ */
public class PolynomialsUtilsTest extends TestCase { public class PolynomialsUtilsTest {
@Test
public void testFirstChebyshevPolynomials() { public void testFirstChebyshevPolynomials() {
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(3), "-3 x + 4 x^3");
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(3), "-3.0 x + 4.0 x^3"); checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(2), "-1 + 2 x^2");
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(2), "-1.0 + 2.0 x^2");
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(1), "x"); checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(1), "x");
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(0), "1.0"); checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(0), "1");
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(7), "-7.0 x + 56.0 x^3 - 112.0 x^5 + 64.0 x^7"); checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(7), "-7 x + 56 x^3 - 112 x^5 + 64 x^7");
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(6), "-1.0 + 18.0 x^2 - 48.0 x^4 + 32.0 x^6"); checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(6), "-1 + 18 x^2 - 48 x^4 + 32 x^6");
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(5), "5.0 x - 20.0 x^3 + 16.0 x^5"); checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(5), "5 x - 20 x^3 + 16 x^5");
checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(4), "1.0 - 8.0 x^2 + 8.0 x^4"); checkPolynomial(PolynomialsUtils.createChebyshevPolynomial(4), "1 - 8 x^2 + 8 x^4");
} }
@Test
public void testChebyshevBounds() { public void testChebyshevBounds() {
for (int k = 0; k < 12; ++k) { for (int k = 0; k < 12; ++k) {
PolynomialFunction Tk = PolynomialsUtils.createChebyshevPolynomial(k); PolynomialFunction Tk = PolynomialsUtils.createChebyshevPolynomial(k);
for (double x = -1.0; x <= 1.0; x += 0.02) { for (double x = -1; x <= 1; x += 0.02) {
assertTrue(k + " " + Tk.value(x), FastMath.abs(Tk.value(x)) < (1.0 + 1.0e-12)); Assert.assertTrue(k + " " + Tk.value(x), FastMath.abs(Tk.value(x)) < (1 + 1e-12));
} }
} }
} }
@Test
public void testChebyshevDifferentials() { public void testChebyshevDifferentials() {
for (int k = 0; k < 12; ++k) { for (int k = 0; k < 12; ++k) {
@ -70,17 +73,17 @@ public class PolynomialsUtilsTest extends TestCase {
} }
} }
@Test
public void testFirstHermitePolynomials() { public void testFirstHermitePolynomials() {
checkPolynomial(PolynomialsUtils.createHermitePolynomial(3), "-12 x + 8 x^3");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(2), "-2 + 4 x^2");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(1), "2 x");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(0), "1");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(3), "-12.0 x + 8.0 x^3"); checkPolynomial(PolynomialsUtils.createHermitePolynomial(7), "-1680 x + 3360 x^3 - 1344 x^5 + 128 x^7");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(2), "-2.0 + 4.0 x^2"); checkPolynomial(PolynomialsUtils.createHermitePolynomial(6), "-120 + 720 x^2 - 480 x^4 + 64 x^6");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(1), "2.0 x"); checkPolynomial(PolynomialsUtils.createHermitePolynomial(5), "120 x - 160 x^3 + 32 x^5");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(0), "1.0"); checkPolynomial(PolynomialsUtils.createHermitePolynomial(4), "12 - 48 x^2 + 16 x^4");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(7), "-1680.0 x + 3360.0 x^3 - 1344.0 x^5 + 128.0 x^7");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(6), "-120.0 + 720.0 x^2 - 480.0 x^4 + 64.0 x^6");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(5), "120.0 x - 160.0 x^3 + 32.0 x^5");
checkPolynomial(PolynomialsUtils.createHermitePolynomial(4), "12.0 - 48.0 x^2 + 16.0 x^4");
} }
@ -104,23 +107,23 @@ public class PolynomialsUtilsTest extends TestCase {
} }
} }
@Test
public void testFirstLaguerrePolynomials() { public void testFirstLaguerrePolynomials() {
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(3), 6l, "6 - 18 x + 9 x^2 - x^3");
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(3), 6l, "6.0 - 18.0 x + 9.0 x^2 - x^3"); checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(2), 2l, "2 - 4 x + x^2");
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(2), 2l, "2.0 - 4.0 x + x^2"); checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(1), 1l, "1 - x");
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(1), 1l, "1.0 - x"); checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(0), 1l, "1");
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(0), 1l, "1.0");
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(7), 5040l, checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(7), 5040l,
"5040.0 - 35280.0 x + 52920.0 x^2 - 29400.0 x^3" "5040 - 35280 x + 52920 x^2 - 29400 x^3"
+ " + 7350.0 x^4 - 882.0 x^5 + 49.0 x^6 - x^7"); + " + 7350 x^4 - 882 x^5 + 49 x^6 - x^7");
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(6), 720l, checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(6), 720l,
"720.0 - 4320.0 x + 5400.0 x^2 - 2400.0 x^3 + 450.0 x^4" "720 - 4320 x + 5400 x^2 - 2400 x^3 + 450 x^4"
+ " - 36.0 x^5 + x^6"); + " - 36 x^5 + x^6");
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(5), 120l, checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(5), 120l,
"120.0 - 600.0 x + 600.0 x^2 - 200.0 x^3 + 25.0 x^4 - x^5"); "120 - 600 x + 600 x^2 - 200 x^3 + 25 x^4 - x^5");
checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(4), 24l, checkPolynomial(PolynomialsUtils.createLaguerrePolynomial(4), 24l,
"24.0 - 96.0 x + 72.0 x^2 - 16.0 x^3 + x^4"); "24 - 96 x + 72 x^2 - 16 x^3 + x^4");
} }
@ -144,20 +147,21 @@ public class PolynomialsUtilsTest extends TestCase {
} }
} }
@Test
public void testFirstLegendrePolynomials() { public void testFirstLegendrePolynomials() {
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(3), 2l, "-3 x + 5 x^3");
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(3), 2l, "-3.0 x + 5.0 x^3"); checkPolynomial(PolynomialsUtils.createLegendrePolynomial(2), 2l, "-1 + 3 x^2");
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(2), 2l, "-1.0 + 3.0 x^2");
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(1), 1l, "x"); checkPolynomial(PolynomialsUtils.createLegendrePolynomial(1), 1l, "x");
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(0), 1l, "1.0"); checkPolynomial(PolynomialsUtils.createLegendrePolynomial(0), 1l, "1");
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(7), 16l, "-35.0 x + 315.0 x^3 - 693.0 x^5 + 429.0 x^7"); checkPolynomial(PolynomialsUtils.createLegendrePolynomial(7), 16l, "-35 x + 315 x^3 - 693 x^5 + 429 x^7");
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(6), 16l, "-5.0 + 105.0 x^2 - 315.0 x^4 + 231.0 x^6"); checkPolynomial(PolynomialsUtils.createLegendrePolynomial(6), 16l, "-5 + 105 x^2 - 315 x^4 + 231 x^6");
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(5), 8l, "15.0 x - 70.0 x^3 + 63.0 x^5"); checkPolynomial(PolynomialsUtils.createLegendrePolynomial(5), 8l, "15 x - 70 x^3 + 63 x^5");
checkPolynomial(PolynomialsUtils.createLegendrePolynomial(4), 8l, "3.0 - 30.0 x^2 + 35.0 x^4"); checkPolynomial(PolynomialsUtils.createLegendrePolynomial(4), 8l, "3 - 30 x^2 + 35 x^4");
} }
@Test
public void testLegendreDifferentials() { public void testLegendreDifferentials() {
for (int k = 0; k < 12; ++k) { for (int k = 0; k < 12; ++k) {
@ -178,41 +182,41 @@ public class PolynomialsUtilsTest extends TestCase {
} }
} }
@Test
public void testHighDegreeLegendre() { public void testHighDegreeLegendre() {
PolynomialsUtils.createLegendrePolynomial(40); PolynomialsUtils.createLegendrePolynomial(40);
double[] l40 = PolynomialsUtils.createLegendrePolynomial(40).getCoefficients(); double[] l40 = PolynomialsUtils.createLegendrePolynomial(40).getCoefficients();
double denominator = 274877906944.0; double denominator = 274877906944d;
double[] numerators = new double[] { double[] numerators = new double[] {
+34461632205.0, -28258538408100.0, +3847870979902950.0, -207785032914759300.0, +34461632205d, -28258538408100d, +3847870979902950d, -207785032914759300d,
+5929294332103310025.0, -103301483474866556880.0, +1197358103913226000200.0, -9763073770369381232400.0, +5929294332103310025d, -103301483474866556880d, +1197358103913226000200d, -9763073770369381232400d,
+58171647881784229843050.0, -260061484647976556945400.0, +888315281771246239250340.0, -2345767627188139419665400.0, +58171647881784229843050d, -260061484647976556945400d, +888315281771246239250340d, -2345767627188139419665400d,
+4819022625419112503443050.0, -7710436200670580005508880.0, +9566652323054238154983240.0, -9104813935044723209570256.0, +4819022625419112503443050d, -7710436200670580005508880d, +9566652323054238154983240d, -9104813935044723209570256d,
+6516550296251767619752905.0, -3391858621221953912598660.0, +1211378079007840683070950.0, -265365894974690562152100.0, +6516550296251767619752905d, -3391858621221953912598660d, +1211378079007840683070950d, -265365894974690562152100d,
+26876802183334044115405.0 +26876802183334044115405d
}; };
for (int i = 0; i < l40.length; ++i) { for (int i = 0; i < l40.length; ++i) {
if (i % 2 == 0) { if (i % 2 == 0) {
double ci = numerators[i / 2] / denominator; double ci = numerators[i / 2] / denominator;
assertEquals(ci, l40[i], FastMath.abs(ci) * 1.0e-15); Assert.assertEquals(ci, l40[i], FastMath.abs(ci) * 1e-15);
} else { } else {
assertEquals(0.0, l40[i], 0.0); Assert.assertEquals(0, l40[i], 0);
} }
} }
} }
private void checkPolynomial(PolynomialFunction p, long denominator, String reference) { private void checkPolynomial(PolynomialFunction p, long denominator, String reference) {
PolynomialFunction q = new PolynomialFunction(new double[] { denominator}); PolynomialFunction q = new PolynomialFunction(new double[] { denominator});
assertEquals(reference, p.multiply(q).toString()); Assert.assertEquals(reference, p.multiply(q).toString());
} }
private void checkPolynomial(PolynomialFunction p, String reference) { private void checkPolynomial(PolynomialFunction p, String reference) {
assertEquals(reference, p.toString()); Assert.assertEquals(reference, p.toString());
} }
private void checkNullPolynomial(PolynomialFunction p) { private void checkNullPolynomial(PolynomialFunction p) {
for (double coefficient : p.getCoefficients()) { for (double coefficient : p.getCoefficients()) {
assertEquals(0.0, coefficient, 1.0e-13); Assert.assertEquals(0, coefficient, 1e-13);
} }
} }
} }