Fixed infinite loop when NaN occurs in singular value decomposition.

JIRA: MATH-947

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1456931 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2013-03-15 12:34:35 +00:00
parent 53039d5d04
commit c75c9e4092
3 changed files with 25 additions and 2 deletions

View File

@ -55,10 +55,13 @@ This is a minor release: It combines bug fixes and new features.
Changes to existing features were made in a backwards-compatible
way such as to allow drop-in replacement of the v3.1[.1] JAR file.
">
<action dev="luc" type="fix" issue="MATH-947" >
Fixed infinite loop when NaN occurs in singular value decomposition.
</action>
<action dev="luc" type="add" issue="MATH-460" due-to="Andrew Waterman">
Added the Lévy distribution.
</action>
<action dev="luc" type="update" >
<action dev="luc" type="update" >
Normal distribution now uses a direct implementation of the
inverse error function to compute inverse cumulative probability
instead of relying on a numerical solver. This is much faster,

View File

@ -285,10 +285,18 @@ public class SingularValueDecomposition {
final double threshold
= TINY + EPS * (FastMath.abs(singularValues[k]) +
FastMath.abs(singularValues[k + 1]));
if (FastMath.abs(e[k]) <= threshold) {
// the following condition is written this way in order
// to break out of the loop when NaN occurs, writing it
// as "if (FastMath.abs(e[k]) <= threshold)" would loop
// indefinitely in case of NaNs because comparison on NaNs
// always return false, regardless of what is checked
// see issue MATH-947
if (!(FastMath.abs(e[k]) > threshold)) {
e[k] = 0;
break;
}
}
if (k == p - 2) {

View File

@ -316,4 +316,16 @@ public class SingularValueDecompositionTest {
return u.multiply(d).multiply(v);
}
@Test
public void testIssue947() {
double[][] nans = new double[][] {
{ Double.NaN, Double.NaN },
{ Double.NaN, Double.NaN }
};
RealMatrix m = new Array2DRowRealMatrix(nans, false);
SingularValueDecomposition svd = new SingularValueDecomposition(m);
Assert.assertTrue(Double.isNaN(svd.getSingularValues()[0]));
Assert.assertTrue(Double.isNaN(svd.getSingularValues()[1]));
}
}