MATH-768
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:
parent
8b71139a74
commit
3ba28fe49d
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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·e<sup>i·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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue