Repository: commons-math Updated Branches: refs/heads/master 093e3bb2e -> c440f668a
MATH-1210 Improved error reporting. Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/c440f668 Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/c440f668 Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/c440f668 Branch: refs/heads/master Commit: c440f668aca99266b5379235f6d99d378630c938 Parents: 093e3bb Author: Gilles <[email protected]> Authored: Wed Mar 18 16:57:16 2015 +0100 Committer: Gilles <[email protected]> Committed: Wed Mar 18 16:57:16 2015 +0100 ---------------------------------------------------------------------- src/changes/changes.xml | 4 ++ .../commons/math4/linear/QRDecomposition.java | 48 +++++++++++++++----- 2 files changed, 40 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-math/blob/c440f668/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f3cf214..485458b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,6 +54,10 @@ If the output is not quite correct, check for invisible trailing spaces! </release> <release version="4.0" date="XXXX-XX-XX" description=""> + <action dev="erans" type="update" issue="MATH-1210"> + "QRDecomposition": include information about the condition that + triggers a "SingularMatrixException". + </action> <action dev="tn" type="fix" issue="MATH-1209" due-to="Jonathan Ogilvie"> Fixed link to algorithm description in "PoissonDistribution#sample()". </action> http://git-wip-us.apache.org/repos/asf/commons-math/blob/c440f668/src/main/java/org/apache/commons/math4/linear/QRDecomposition.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math4/linear/QRDecomposition.java b/src/main/java/org/apache/commons/math4/linear/QRDecomposition.java index 02ac7e9..d96bb45 100644 --- a/src/main/java/org/apache/commons/math4/linear/QRDecomposition.java +++ b/src/main/java/org/apache/commons/math4/linear/QRDecomposition.java @@ -21,6 +21,7 @@ import java.util.Arrays; import org.apache.commons.math4.exception.DimensionMismatchException; import org.apache.commons.math4.util.FastMath; +import org.apache.commons.math4.exception.util.LocalizedFormats; /** @@ -335,12 +336,7 @@ public class QRDecomposition { /** {@inheritDoc} */ public boolean isNonSingular() { - for (double diag : rDiag) { - if (FastMath.abs(diag) <= threshold) { - return false; - } - } - return true; + return !checkSingular(rDiag, threshold, false); } /** {@inheritDoc} */ @@ -350,9 +346,7 @@ public class QRDecomposition { if (b.getDimension() != m) { throw new DimensionMismatchException(b.getDimension(), m); } - if (!isNonSingular()) { - throw new SingularMatrixException(); - } + checkSingular(rDiag, threshold, true); final double[] x = new double[n]; final double[] y = b.toArray(); @@ -393,9 +387,7 @@ public class QRDecomposition { if (b.getRowDimension() != m) { throw new DimensionMismatchException(b.getRowDimension(), m); } - if (!isNonSingular()) { - throw new SingularMatrixException(); - } + checkSingular(rDiag, threshold, true); final int columns = b.getColumnDimension(); final int blockSize = BlockRealMatrix.BLOCK_SIZE; @@ -472,5 +464,37 @@ public class QRDecomposition { public RealMatrix getInverse() { return solve(MatrixUtils.createRealIdentityMatrix(qrt[0].length)); } + + /** + * Check singularity. + * + * @param diag Diagonal elements of the R matrix. + * @param min Singularity threshold. + * @param raise Whether to raise a {@link SingularMatrixException} + * if any element of the diagonal fails the check. + * @return {@code true} if any element of the diagonal is smaller + * or equal to {@code min}. + * @throws SingularMatrixException if the matrix is singular and + * {@code raise} is {@code true}. + */ + private static boolean checkSingular(double[] diag, + double min, + boolean raise) { + final int len = diag.length; + for (int i = 0; i < len; i++) { + final double d = diag[i]; + if (FastMath.abs(d) <= min) { + if (raise) { + final SingularMatrixException e = new SingularMatrixException(); + e.getContext().addMessage(LocalizedFormats.NUMBER_TOO_SMALL, d, min); + e.getContext().addMessage(LocalizedFormats.INDEX, i); + throw e; + } else { + return true; + } + } + } + return false; + } } }
