sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 02/03: Reduce the occurrence of NaN in transform matrix.
Date Fri, 14 Dec 2018 13:29:14 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 054ae86f4784ec72a9a89b712533ed5daf14dff1
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Fri Dec 14 11:43:47 2018 +0100

    Reduce the occurrence of NaN in transform matrix.
---
 .../operation/matrix/GeneralMatrix.java            | 16 +++++++---
 .../referencing/operation/matrix/Matrix4Test.java  | 36 ++++++++++++++++++++--
 .../operation/matrix/NonSquareMatrixTest.java      | 17 +++++-----
 3 files changed, 52 insertions(+), 17 deletions(-)

diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
index adb0af6..be16952 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
@@ -615,13 +615,19 @@ class GeneralMatrix extends MatrixSIS implements ExtendedPrecisionMatrix
{
                 int iA = j * nc;                            // Index of values in a single
row of A.
                 final int nextRow = iA + nc;
                 while (iA < nextRow) {
-                    dot.setFrom (eltA, iA, errA);
-                    dot.multiply(eltB, iB, errB);
-                    sum.add(dot);
+                    dot.setFrom(eltA, iA, errA);
+                    if (!dot.isZero()) {                    // For avoiding multiplication
with NaN values.
+                        final double vB = eltB[iB];
+                        final double eB = eltB[iB + errB];
+                        if (vB != 0 || eB != 0) {           // For avoiding multiplication
with NaN values.
+                            dot.multiply(vB, eB);
+                            sum.add(dot);
+                            final double value = Math.abs(dot.value);
+                            if (value > max) max = value;
+                        }
+                    }
                     iB += numCol;                           // Move to next row of B.
                     iA++;                                   // Move to next column of A.
-                    final double value = Math.abs(dot.value);
-                    if (value > max) max = value;
                 }
                 if (Math.abs(sum.value) < Math.ulp(max) * ZERO_THRESHOLD) {
                     sum.clear();                            // Sum is not significant according
double arithmetic.
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
index 0880923..2df60e9 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
@@ -19,7 +19,8 @@ package org.apache.sis.referencing.operation.matrix;
 import org.apache.sis.test.DependsOn;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static java.lang.Double.NaN;
+import static org.opengis.test.Assert.*;
 import static org.apache.sis.referencing.operation.matrix.Matrix4.SIZE;
 
 
@@ -28,7 +29,7 @@ import static org.apache.sis.referencing.operation.matrix.Matrix4.SIZE;
  * This class inherits all tests defined in {@link MatrixTestCase}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.4
+ * @version 1.0
  * @since   0.4
  * @module
  */
@@ -80,6 +81,37 @@ public final strictfp class Matrix4Test extends MatrixTestCase {
     }
 
     /**
+     * Tests multiplication of a matrix that contains NaN numbers.
+     * We want to avoid having NaNs of a full row or full column.
+     */
+    @Test
+    public void testMultiplyWithNaN() {
+        final Matrix4 m1 = new Matrix4(
+                0.5,  0,    0,   -179.5,
+                0,    0.25, 0,    -89.5,
+                0,    0,  NaN,  20989.0,
+                0,    0,    0,      1);
+
+        final Matrix4 m2 = new Matrix4(
+                4,  0,  0,      0,
+                0,  6,  0,      0,
+                0,  0,  1,  18262.5,
+                0,  0,  0,      1);
+
+        assertMatrixEquals("Multiplication with NaN", new Matrix4(
+                2.0,  0,      0,   -718.0,
+                0,    1.5,    0,   -537.0,
+                0,    0,    NaN,  39251.5,
+                0,    0,      0,      1), m2.multiply(m1), STRICT);
+
+        assertMatrixEquals("Multiplication with NaN", new Matrix4(
+                2.0,  0,      0,  -179.5,
+                0,    1.5,    0,   -89.5,
+                0,    0,    NaN,     NaN,
+                0,    0,      0,     1), m1.multiply(m2), STRICT);
+    }
+
+    /**
      * Tests the accuracy of a chain of matrix operations.
      *
      * @throws NoninvertibleMatrixException should never happen.
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
index fab3d5c..48c3172 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
@@ -82,7 +82,7 @@ public final strictfp class NonSquareMatrixTest extends MatrixTestCase {
     @Test
     @Override
     public void testInverse() throws NoninvertibleMatrixException {
-        testDimensionReduction(null, 1, 0);
+        testDimensionReduction(null, 1);
         testDimensionIncrease (null, 1);
     }
 
@@ -137,7 +137,7 @@ public final strictfp class NonSquareMatrixTest extends MatrixTestCase
{
         testDimensionReduction(new Matrix3(
                 2, 0, 0,
                 0, 2, 0,
-                0, 0, 1), 2, NaN);
+                0, 0, 1), 2);
         testDimensionIncrease(new GeneralMatrix(5, 5, new double[] {
                 2, 0, 0, 0, 0,
                 0, 2, 0, 0, 0,
@@ -150,14 +150,11 @@ public final strictfp class NonSquareMatrixTest extends MatrixTestCase
{
      * Tests {@link NonSquareMatrix#inverse()} or {@link NonSquareMatrix#solve(Matrix)} with
a conversion
      * matrix having more source dimensions (columns) than target dimensions (rows).
      *
-     * @param  Y    the matrix to give to {@code solve(Y)}, {@code null} for testing {@code
inverse()}.
-     * @param  sf   the scale factor by which to multiply all expected scale elements.
-     * @param  uks  value of unknown scales (O for {@code inverse()}, or NaN for {@code solve(Y)}).
+     * @param  Y   the matrix to give to {@code solve(Y)}, {@code null} for testing {@code
inverse()}.
+     * @param  sf  the scale factor by which to multiply all expected scale elements.
      * @throws NoninvertibleMatrixException if the matrix can not be inverted.
      */
-    private static void testDimensionReduction(final MatrixSIS Y, final double sf, final
double uks)
-            throws NoninvertibleMatrixException
-    {
+    private static void testDimensionReduction(final MatrixSIS Y, final double sf) throws
NoninvertibleMatrixException {
         final MatrixSIS matrix = Matrices.create(3, 5, new double[] {
             2, 0, 0, 0, 8,
             0, 0, 4, 0, 5,
@@ -165,9 +162,9 @@ public final strictfp class NonSquareMatrixTest extends MatrixTestCase
{
         });
         final double[] expected = {
             0.5*sf,  0,           -4,
-            uks,     uks,        NaN,
+            0,       0,          NaN,
             0,       0.25*sf,  -1.25,
-            uks,     uks,        NaN,
+            0,       0,          NaN,
             0,       0,            1
         };
         final MatrixSIS inverse = (Y != null) ? matrix.solve(Y) : matrix.inverse();


Mime
View raw message