Fix for possible zero divide on an indefinite matrix
Fix for: MATH-297 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@826550 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ddc5554353
commit
becc8d9704
|
@ -1699,19 +1699,21 @@ public class EigenDecompositionImpl implements EigenDecomposition {
|
|||
// perform an initial non-shifted LDLt decomposition
|
||||
final double[] d = new double[m];
|
||||
final double[] l = new double[m - 1];
|
||||
double di = main[0];
|
||||
// avoid zero divide on indefinite matrix
|
||||
final double mu = realEigenvalues[m-1] <= 0 && realEigenvalues[0] > 0 ? 0.5-realEigenvalues[m-1] : 0;
|
||||
double di = main[0]+mu;
|
||||
d[0] = di;
|
||||
for (int i = 1; i < m; ++i) {
|
||||
final double eiM1 = secondary[i - 1];
|
||||
final double ratio = eiM1 / di;
|
||||
di = main[i] - eiM1 * ratio;
|
||||
di = main[i] - eiM1 * ratio + mu;
|
||||
l[i - 1] = ratio;
|
||||
d[i] = di;
|
||||
}
|
||||
|
||||
// compute eigenvectors
|
||||
for (int i = 0; i < m; ++i) {
|
||||
eigenvectors[i] = findEigenvector(realEigenvalues[i], d, l);
|
||||
eigenvectors[i] = findEigenvector(realEigenvalues[i]+mu, d, l);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -243,6 +243,24 @@ public class EigenDecompositionImplTest extends TestCase {
|
|||
checkEigenVector((new double[] {-1, -1, 2}), ed, 1E-12);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies operation on indefinite matrix
|
||||
*/
|
||||
public void testZeroDivide() {
|
||||
RealMatrix indefinite = MatrixUtils.createRealMatrix(new double [][] {
|
||||
{ 0.0, 1.0, -1.0 },
|
||||
{ 1.0, 1.0, 0.0 },
|
||||
{ -1.0,0.0, 1.0 }
|
||||
});
|
||||
EigenDecomposition ed = new EigenDecompositionImpl(indefinite, MathUtils.SAFE_MIN);
|
||||
checkEigenValues((new double[] {2, 1, -1}), ed, 1E-12);
|
||||
double isqrt3 = 1/Math.sqrt(3.0);
|
||||
checkEigenVector((new double[] {isqrt3,isqrt3,-isqrt3}), ed, 1E-12);
|
||||
double isqrt2 = 1/Math.sqrt(2.0);
|
||||
checkEigenVector((new double[] {0.0,-isqrt2,-isqrt2}), ed, 1E-12);
|
||||
double isqrt6 = 1/Math.sqrt(6.0);
|
||||
checkEigenVector((new double[] {2*isqrt6,-isqrt6,isqrt6}), ed, 1E-12);
|
||||
}
|
||||
/**
|
||||
* Verifies that the given EigenDecomposition has eigenvalues equivalent to
|
||||
* the targetValues, ignoring the order of the values and allowing
|
||||
|
@ -257,6 +275,7 @@ public class EigenDecompositionImplTest extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true iff there is an entry within tolerance of value in
|
||||
* searchArray.
|
||||
|
|
Loading…
Reference in New Issue