sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1529656 - in /sis/branches/JDK7/core/sis-referencing/src: main/java/org/apache/sis/referencing/operation/matrix/ test/java/org/apache/sis/referencing/operation/matrix/
Date Sun, 06 Oct 2013 18:32:09 GMT
Author: desruisseaux
Date: Sun Oct  6 18:32:08 2013
New Revision: 1529656

URL: http://svn.apache.org/r1529656
Log:
Initial port of Geotk code for inversion of some special cases of non-square matrix.
Still need more work for better handling of DoubleDouble.error values.

Modified:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/SolverTest.java

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java?rev=1529656&r1=1529655&r2=1529656&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrix.java
[UTF-8] Sun Oct  6 18:32:08 2013
@@ -105,11 +105,75 @@ final class NonSquareMatrix extends Gene
 
     /**
      * {@inheritDoc}
+     *
+     * <p>This method performs a special check for non-square matrix in an attempt
to invert them anyway.
+     * This is possible only if some columns or rows contain contain only 0 elements.</p>
      */
     @Override
     public MatrixSIS inverse() throws NoninvertibleMatrixException {
-        // TODO: This is where we will need a special treatment different than what JAMA
do (because different needs).
-        throw new UnsupportedOperationException();
+        final int numRow = this.numRow; // Protection against accidental changes.
+        final int numCol = this.numCol;
+        if (numRow < numCol) {
+            /*
+             * Target points have fewer ordinates than source point. If a column contains
only zero values,
+             * then this means that the ordinate at the corresponding column is simply deleted.
We can omit
+             * that column. We check the last columns before the first columns on the assumption
that last
+             * dimensions are more likely to be independant dimensions like time.
+             */
+            int oi = numCol - numRow;
+            final int[] omitted = new int[oi];
+skipColumn: for (int i=numCol; --i>=0;) {
+                for (int j=numRow; --j>=0;) {
+                    if (getElement(j, i) != 0) {
+                        continue skipColumn;
+                    }
+                }
+                // Found a column which contains only 0 elements.
+                omitted[--oi] = i;
+                if (oi == 0) {
+                    break; // Found enough columns to skip.
+                }
+            }
+            if (oi == 0) {
+                /*
+                 * Create a square matrix omitting some or all columns containing only 0
elements, and invert
+                 * that matrix. Finally, create a new matrix with new rows added for the
omitted ordinates.
+                 */
+                MatrixSIS squareMatrix = new GeneralMatrix(numRow, numRow, false, 2);
+                for (int k=0,i=0; i<numCol; i++) {
+                    if (oi != omitted.length && i == omitted[oi]) {
+                        oi++;
+                    } else {
+                        for (int j=numRow; --j>=0;) {
+                            squareMatrix.setElement(j, k, getElement(j, i));
+                        }
+                        k++;
+                    }
+                }
+                squareMatrix = squareMatrix.inverse();
+                /*
+                 * From this point, the meaning of 'numCol' and 'numRow' are interchanged.
+                 */
+                final MatrixSIS inverse = new NonSquareMatrix(numCol, numRow, false, 2);
+                oi = 0;
+                for (int k=0,j=0; j<numCol; j++) {
+                    if (oi != omitted.length && j == omitted[oi]) {
+                        if (j < numRow) {
+                            inverse.setElement(j, j, 0);
+                        }
+                        inverse.setElement(j, numRow-1, Double.NaN);
+                        oi++;
+                    } else {
+                        for (int i=numRow; --i>=0;) {
+                            inverse.setElement(j, i, squareMatrix.getElement(k, i));
+                        }
+                        k++;
+                    }
+                }
+                return inverse;
+            }
+        }
+        return super.inverse();
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java?rev=1529656&r1=1529655&r2=1529656&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatrixTestCase.java
[UTF-8] Sun Oct  6 18:32:08 2013
@@ -181,6 +181,19 @@ public abstract strictfp class MatrixTes
     }
 
     /**
+     * Asserts that the given matrix is equals to the given expected values, up to the given
tolerance threshold.
+     * This method compares the elements values in two slightly redundant ways.
+     */
+    static void assertMatrixEquals(final double[] expected, final int numRow, final int numCol,
+            final MatrixSIS actual, final double tolerance)
+    {
+        assertEquals("numRow", numRow, actual.getNumRow());
+        assertEquals("numCol", numCol, actual.getNumCol());
+        assertArrayEquals(expected, actual.getElements(), tolerance); // First because more
informative in case of failure.
+        assertTrue(Matrices.create(numRow, numCol, expected).equals(actual, tolerance));
+    }
+
+    /**
      * Creates an array of the given length filled with random values. All random values
are between 0 inclusive
      * and 100 exclusive. This method never write negative values. Consequently, any strictly
negative value set
      * by the test method is guaranteed to be different than all original values in the returned
array.

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java?rev=1529656&r1=1529655&r2=1529656&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/NonSquareMatrixTest.java
[UTF-8] Sun Oct  6 18:32:08 2013
@@ -21,6 +21,7 @@ import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestUtilities;
 import org.junit.AfterClass;
 
+import static java.lang.Double.NaN;
 import static org.junit.Assert.*;
 
 
@@ -73,11 +74,24 @@ public final strictfp class NonSquareMat
     }
 
     /**
-     * TODO: inverse transform not yet implemented for non-square matrix.
+     * Tests {@link #inverse()} with a non-square matrix.
      */
     @Override
-    @org.junit.Ignore
     public void testInverse() throws NoninvertibleMatrixException {
+        final MatrixSIS matrix = Matrices.create(3, 5, new double[] {
+            2, 0, 0, 0, 8,
+            0, 0, 4, 0, 5,
+            0, 0, 0, 0, 1
+        });
+        final double[] expected = {
+            0.5, 0,    -4,
+            0,   0,     NaN,
+            0,   0.25, -1.25,
+            0,   0,     NaN,
+            0,   0,     1
+        };
+        final MatrixSIS inverse = matrix.inverse();
+        assertMatrixEquals(expected, 5, 3, inverse, SolverTest.TOLERANCE);
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/SolverTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/SolverTest.java?rev=1529656&r1=1529655&r2=1529656&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/SolverTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/SolverTest.java
[UTF-8] Sun Oct  6 18:32:08 2013
@@ -25,7 +25,7 @@ import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
 import static java.lang.Double.NaN;
-import static org.junit.Assert.*;
+import static org.apache.sis.referencing.operation.matrix.MatrixTestCase.assertMatrixEquals;
 
 
 /**
@@ -62,19 +62,6 @@ public final strictfp class SolverTest e
     protected static final double TOLERANCE = 100 * MatrixTestCase.TOLERANCE;
 
     /**
-     * Asserts that the given matrix is equals to the given expected values, up to the {@link
#TOLERANCE}
-     * threshold. This method compares the elements values in two slightly redundant ways.
-     */
-    private static void assertMatrixEquals(final double[] expected,
-            final int numRow, final int numCol, final MatrixSIS actual)
-    {
-        assertEquals("numRow", numRow, actual.getNumRow());
-        assertEquals("numCol", numCol, actual.getNumCol());
-        assertArrayEquals(expected, actual.getElements(), TOLERANCE); // First because more
informative in case of failure.
-        assertTrue(Matrices.create(numRow, numCol, expected).equals(actual, TOLERANCE));
-    }
-
-    /**
      * The matrix to test.
      */
     private MatrixSIS matrix;
@@ -127,7 +114,7 @@ public final strictfp class SolverTest e
                 continue;
             }
             final MatrixSIS U = Solver.solve(matrix, matrixArg);
-            MatrixTestCase.assertMatrixEquals(jama, U, TOLERANCE);
+            assertMatrixEquals(jama, U, TOLERANCE);
         }
     }
 
@@ -157,7 +144,7 @@ public final strictfp class SolverTest e
             0,     0,  0,      0,    1
         };
         MatrixSIS inverse = Solver.inverse(matrix);
-        assertMatrixEquals(expected, 5, 5, inverse);
+        assertMatrixEquals(expected, 5, 5, inverse, TOLERANCE);
         /*
          * Set a scale factor to NaN. The translation term for the corresponding
          * dimension become unknown, so it most become NaN in the inverse matrix.
@@ -177,7 +164,7 @@ public final strictfp class SolverTest e
             0,     0,  0,      0,    1
         };
         inverse = Solver.inverse(matrix);
-        assertMatrixEquals(expected, 5, 5, inverse);
+        assertMatrixEquals(expected, 5, 5, inverse, TOLERANCE);
         /*
          * Set a scale factor to NaN with translation equals to 0.
          * The zero value should be preserved, since 0 × any == 0
@@ -198,7 +185,7 @@ public final strictfp class SolverTest e
             0,     0,  0,      0,    1
         };
         inverse = Solver.inverse(matrix);
-        assertMatrixEquals(expected, 5, 5, inverse);
+        assertMatrixEquals(expected, 5, 5, inverse, TOLERANCE);
         /*
          * Set a translation term to NaN. The translation should be NaN in
          * the inverse matrix too, but the scale factor can still be compute.
@@ -218,6 +205,6 @@ public final strictfp class SolverTest e
             0,     0,  0,      0,    1
         };
         inverse = Solver.inverse(matrix);
-        assertMatrixEquals(expected, 5, 5, inverse);
+        assertMatrixEquals(expected, 5, 5, inverse, TOLERANCE);
     }
 }



Mime
View raw message