Provided access to methods for finding complex roots of a polynomial in
"LaguerreSolver" class.
Added utility for converting an array of doubles to an array of "Complex"
objects.


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1361793 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2012-07-15 20:50:13 +00:00
parent 8b71139a74
commit 3ba28fe49d
5 changed files with 112 additions and 45 deletions

View File

@ -52,6 +52,13 @@ If the output is not quite correct, check for invisible trailing spaces!
<body>
<release version="3.1" date="TBD" description="
">
<action dev="erans" type="add" issue="MATH-768">
Re-instated methods to find all complex roots of a polynomial (class
"LaguerreSolver" in package "o.a.c.m.analysis.solvers").
</action>
<action dev="erans" type="add" issue="MATH-810">
Added accessors to the "Pair" class (package "o.a.c.m.util").
</action>
<action dev="tn" type="add" issue="MATH-822" due-to="Jared Becksfort">
Added new constructors in EigenDecomposition and deprecated two constructors
with unused parameters.

View File

@ -17,6 +17,8 @@
package org.apache.commons.math3.analysis.solvers;
import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.complex.ComplexUtils;
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math3.exception.NoBracketingException;
import org.apache.commons.math3.exception.NullArgumentException;
import org.apache.commons.math3.exception.NoDataException;
@ -144,11 +146,8 @@ public class LaguerreSolver extends AbstractPolynomialSolver {
*/
public double laguerre(double lo, double hi,
double fLo, double fHi) {
double coefficients[] = getCoefficients();
Complex c[] = new Complex[coefficients.length];
for (int i = 0; i < coefficients.length; i++) {
c[i] = new Complex(coefficients[i], 0);
}
final Complex c[] = ComplexUtils.convertToComplex(getCoefficients());
Complex initial = new Complex(0.5 * (lo + hi), 0);
Complex z = complexSolver.solve(c, initial);
if (complexSolver.isRoot(lo, hi, z)) {
@ -167,6 +166,58 @@ public class LaguerreSolver extends AbstractPolynomialSolver {
}
}
/**
* Find all complex roots for the polynomial with the given
* coefficients, starting from the given initial value.
* <br/>
* Note: This method is not part of the API of {@link BaseUnivariateSolver}.
*
* @param coefficients Polynomial coefficients.
* @param initial Start value.
* @return the point at which the function value is zero.
* @throws org.apache.commons.math3.exception.TooManyEvaluationsException
* if the maximum number of evaluations is exceeded.
* @throws NullArgumentException if the {@code coefficients} is
* {@code null}.
* @throws NoDataException if the {@code coefficients} array is empty.
*/
public Complex[] solveAllComplex(double[] coefficients,
double initial) {
setup(Integer.MAX_VALUE,
new PolynomialFunction(coefficients),
Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY,
initial);
return complexSolver.solveAll(ComplexUtils.convertToComplex(coefficients),
new Complex(initial, 0d));
}
/**
* Find a complex root for the polynomial with the given coefficients,
* starting from the given initial value.
* <br/>
* Note: This method is not part of the API of {@link BaseUnivariateSolver}.
*
* @param coefficients Polynomial coefficients.
* @param initial Start value.
* @return the point at which the function value is zero.
* @throws org.apache.commons.math3.exception.TooManyEvaluationsException
* if the maximum number of evaluations is exceeded.
* @throws NullArgumentException if the {@code coefficients} is
* {@code null}.
* @throws NoDataException if the {@code coefficients} array is empty.
*/
public Complex solveComplex(double[] coefficients,
double initial) {
setup(Integer.MAX_VALUE,
new PolynomialFunction(coefficients),
Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY,
initial);
return complexSolver.solve(ComplexUtils.convertToComplex(coefficients),
new Complex(initial, 0d));
}
/**
* Class for searching all (complex) roots.
*/

View File

@ -32,9 +32,7 @@ public class ComplexUtils {
/**
* Default constructor.
*/
private ComplexUtils() {
super();
}
private ComplexUtils() {}
/**
* Creates a complex number from the given polar representation.
@ -58,7 +56,7 @@ public class ComplexUtils {
* @param r the modulus of the complex number to create
* @param theta the argument of the complex number to create
* @return <code>r&middot;e<sup>i&middot;theta</sup></code>
* @throws MathIllegalArgumentException if r is negative
* @throws MathIllegalArgumentException if {@code r} is negative.
* @since 1.1
*/
public static Complex polar2Complex(double r, double theta) {
@ -69,4 +67,21 @@ public class ComplexUtils {
return new Complex(r * FastMath.cos(theta), r * FastMath.sin(theta));
}
/**
* Convert an array of primitive doubles to an array of {@code Complex} objects.
*
* @param real Array of numbers to be converted to their {@code Complex}
* equivalent.
* @return an array of {@code Complex} objects.
*
* @since 3.1
*/
public static Complex[] convertToComplex(double[] real) {
final Complex c[] = new Complex[real.length];
for (int i = 0; i < real.length; i++) {
c[i] = new Complex(real[i], 0);
}
return c;
}
}

View File

@ -19,7 +19,9 @@ package org.apache.commons.math3.analysis.solvers;
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math3.exception.NumberIsTooLargeException;
import org.apache.commons.math3.exception.NoBracketingException;
import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.util.FastMath;
import org.apache.commons.math3.TestUtils;
import org.junit.Assert;
import org.junit.Test;
@ -110,43 +112,26 @@ public final class LaguerreSolverTest {
}
/**
* Test of solver for the quintic function using solveAll().
* XXX commented out because "solveAll" is not part of the API.
* Test of solver for the quintic function using
* {@link LaguerreSolver#solveAllComplex(double[],double) solveAllComplex}.
*/
// public void testQuinticFunction2() {
// double initial = 0.0, tolerance;
// Complex expected, result[];
@Test
public void testQuinticFunction2() {
// p(x) = x^5 + 4x^3 + x^2 + 4 = (x+1)(x^2-x+1)(x^2+4)
final double[] coefficients = { 4.0, 0.0, 1.0, 4.0, 0.0, 1.0 };
final LaguerreSolver solver = new LaguerreSolver();
final Complex[] result = solver.solveAllComplex(coefficients, 0);
// // p(x) = x^5 + 4x^3 + x^2 + 4 = (x+1)(x^2-x+1)(x^2+4)
// double coefficients[] = { 4.0, 0.0, 1.0, 4.0, 0.0, 1.0 };
// LaguerreSolver solver = new LaguerreSolver();
// result = solver.solveAll(coefficients, initial);
// expected = new Complex(0.0, -2.0);
// tolerance = FastMath.max(solver.getAbsoluteAccuracy(),
// FastMath.abs(expected.abs() * solver.getRelativeAccuracy()));
// TestUtils.assertContains(result, expected, tolerance);
// expected = new Complex(0.0, 2.0);
// tolerance = FastMath.max(solver.getAbsoluteAccuracy(),
// FastMath.abs(expected.abs() * solver.getRelativeAccuracy()));
// TestUtils.assertContains(result, expected, tolerance);
// expected = new Complex(0.5, 0.5 * FastMath.sqrt(3.0));
// tolerance = FastMath.max(solver.getAbsoluteAccuracy(),
// FastMath.abs(expected.abs() * solver.getRelativeAccuracy()));
// TestUtils.assertContains(result, expected, tolerance);
// expected = new Complex(-1.0, 0.0);
// tolerance = FastMath.max(solver.getAbsoluteAccuracy(),
// FastMath.abs(expected.abs() * solver.getRelativeAccuracy()));
// TestUtils.assertContains(result, expected, tolerance);
// expected = new Complex(0.5, -0.5 * FastMath.sqrt(3.0));
// tolerance = FastMath.max(solver.getAbsoluteAccuracy(),
// FastMath.abs(expected.abs() * solver.getRelativeAccuracy()));
// TestUtils.assertContains(result, expected, tolerance);
// }
for (Complex expected : new Complex[] { new Complex(0, -2),
new Complex(0, 2),
new Complex(0.5, 0.5 * FastMath.sqrt(3)),
new Complex(-1, 0),
new Complex(0.5, -0.5 * FastMath.sqrt(3.0)) }) {
final double tolerance = FastMath.max(solver.getAbsoluteAccuracy(),
FastMath.abs(expected.abs() * solver.getRelativeAccuracy()));
TestUtils.assertContains(result, expected, tolerance);
}
}
/**
* Test of parameters for the solver.

View File

@ -20,7 +20,7 @@ package org.apache.commons.math3.complex;
import org.apache.commons.math3.TestUtils;
import org.apache.commons.math3.util.FastMath;
import org.junit.Test;
import org.junit.Assert;
/**
* @version $Id$
@ -100,4 +100,13 @@ public class ComplexUtilsTest {
TestUtils.assertSame(negInfNegInf, ComplexUtils.polar2Complex(inf, 5*pi/4));
}
@Test
public void testConvertToComplex() {
final double[] real = new double[] { negInf, -123.45, 0, 1, 234.56, pi, inf };
final Complex[] complex = ComplexUtils.convertToComplex(real);
for (int i = 0; i < real.length; i++) {
Assert.assertEquals(real[i], complex[i].getReal(), 0d);
}
}
}