Added add, subtract, negate, multiply and toString methods to PolynomialFunction

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@739834 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2009-02-01 20:56:12 +00:00
parent e8bb7ce937
commit adc64fb8cf
3 changed files with 244 additions and 12 deletions

View File

@ -32,25 +32,26 @@ import org.apache.commons.math.analysis.UnivariateRealFunction;
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 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
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 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
* @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 @@ public class PolynomialFunction implements DifferentiableUnivariateRealFunction,
}
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 class PolynomialFunction implements DifferentiableUnivariateRealFunction,
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();
}
}

View File

@ -39,6 +39,9 @@ The <action> type attribute can be add,update,fix,remove.
</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>

View File

@ -160,4 +160,80 @@ public final class PolynomialFunctionTest extends TestCase {
}
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);
}
}
}