sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1529105 - in /sis/branches/JDK7/core: sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/ sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/ sis-utility/src/main/java/org/apache/sis/internal/u...
Date Fri, 04 Oct 2013 09:15:15 GMT
Author: desruisseaux
Date: Fri Oct  4 09:15:14 2013
New Revision: 1529105

URL: http://svn.apache.org/r1529105
Log:
Safety against some rounding errors.

Modified:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java?rev=1529105&r1=1529104&r2=1529105&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] Fri Oct  4 09:15:14 2013
@@ -295,6 +295,12 @@ class GeneralMatrix extends MatrixSIS {
 
     /**
      * {@inheritDoc}
+     *
+     * <p>This method does not check the error terms, because those terms are not visible
to the user
+     * (they can not appear in the value returned by {@link #getElement(int, int)}, and are
not shown
+     * by {@link #toString()}) - returning {@code false} while the matrix clearly looks like
affine
+     * would be confusing for the user. Furthermore, the errors can be non-zero only in the
very last
+     * element and that value always smaller than 2.3E-16.</p>
      */
     @Override
     public final boolean isAffine() {
@@ -309,11 +315,7 @@ class GeneralMatrix extends MatrixSIS {
                         return false;
                     }
                 }
-                /*
-                 * At this point, the 'double' values are those of an affine transform.
-                 * If this matrix uses extended precision, ensures that their errors are
zero.
-                 */
-                return errorsAreZero(base + numRow*numCol);
+                return true;
             }
         }
         return false;
@@ -321,6 +323,16 @@ class GeneralMatrix extends MatrixSIS {
 
     /**
      * {@inheritDoc}
+     *
+     * <p>This method does not check the error terms, because those terms are not visible
to the user
+     * (they can not appear in the value returned by {@link #getElement(int, int)}, and are
not shown
+     * by {@link #toString()}) - returning {@code false} while the matrix clearly looks like
identity
+     * would be confusing for the user. Furthermore, the errors can be non-zero only on the
diagonal,
+     * and those values always smaller than 2.3E-16.</p>
+     *
+     * <p>An other argument is that the extended precision is for reducing rounding
errors during
+     * matrix arithmetics. But since the user provided the original data as {@code double}
values,
+     * the extra precision usually have no "real" meaning.</p>
      */
     @Override
     public final boolean isIdentity() {
@@ -340,25 +352,6 @@ class GeneralMatrix extends MatrixSIS {
                 if (element != 0) return false;
             }
         }
-        /*
-         * At this point, the 'double' values are those of an identity transform.
-         * If this matrix uses extended precision, ensures that all errors are zero.
-         */
-        return errorsAreZero(length);
-    }
-
-    /**
-     * Returns {@code true} if this matrix has no error elements, or if all error elements
starting
-     * at the given index are zero.
-     *
-     * @param i Index of the first error elements to check (may be greater than the array
length).
-     */
-    private boolean errorsAreZero(int i) {
-        while (i < elements.length) {
-            if (elements[i++] != 0) {
-                return false;
-            }
-        }
         return true;
     }
 

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java?rev=1529105&r1=1529104&r2=1529105&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
[UTF-8] Fri Oct  4 09:15:14 2013
@@ -115,12 +115,10 @@ public final strictfp class Matrix4Test 
          * We have a slight residu in the longitude translation term because of the
          * prime meridian shift - we will set this residu to zero for this test.
          *
-         * Note that the 'isIdentity(0)' test fail if the double-double arithmetic is
+         * Note that the 'isIdentity()' test fail if the double-double arithmetic is
          * disabled, because some scale factors will be 0.9999999999999999 instead of 1.
          */
         final MatrixSIS result = step3.multiply(step2).multiply(step1);
-        assertEquals("translateX", 0, result.getElement(0,3), 1E-32);
-        result.setElement(0,3, 0);
-        assertTrue("isIdentity(0)", Matrices.isIdentity(result, 0));
+        assertTrue("isIdentity()", result.isIdentity());
     }
 }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java?rev=1529105&r1=1529104&r2=1529105&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
[UTF-8] Fri Oct  4 09:15:14 2013
@@ -421,6 +421,20 @@ public final class DoubleDouble extends 
         value += otherValue;
         error += v - (value + (v -= value)) + (otherValue + v);
         error += otherError;
+        if (value == 0 && error != 0) {
+            /*
+             * The two values almost cancelled, only their error terms are different.
+             * The number of significand bits (mantissa) in the IEEE 'double' representation
is 52,
+             * not counting the hidden bit. So estimate the accuracy of the double-double
number as
+             * the accuracy of the 'double' value (which is 1 ULP) scaled as if we had 50
additional
+             * significand bits (we ignore 2 bits as a safety margin). If the error is not
greater
+             * than that value, then assume that it is not significant.
+             */
+            if (Math.abs(error) <= Math.scalb(Math.ulp(otherValue), -50)) {
+                error = 0;
+                return;
+            }
+        }
         normalize();
     }
 
@@ -622,11 +636,11 @@ public final class DoubleDouble extends 
      * {@section Implementation}
      * If <var>a</var> and <var>b</var> are {@code DoubleDouble}
instances, then we estimate:
      *
-     *   <blockquote>(a / b) = (a.value / b.value) + remaining / b</blockquote>
+     *   <blockquote>(a / b) = (a.value / b.value) + remainder / b</blockquote>
      *
      * where:
      *
-     *   <blockquote>remaining = a - b * (a.value / b.value)</blockquote>
+     *   <blockquote>remainder = a - b * (a.value / b.value)</blockquote>
      *
      * @param numeratorValue The other value to divide by this {@code DoubleDouble}.
      * @param numeratorError The error of the other value to divide by this {@code DoubleDouble}.
@@ -644,14 +658,14 @@ public final class DoubleDouble extends 
         final double quotient = numeratorValue / denominatorValue;
         multiply(quotient, 0);
         /*
-         * Compute 'remaining' as 'a - above_product'.
+         * Compute 'remainder' as 'a - above_product'.
          */
         final double productError = error;
         setToSum(numeratorValue, -value);
         error -= productError;  // Complete the above subtraction
         error += numeratorError;
         /*
-         * Adds the 'remaining / b' term, using 'remaining / b.value' as an approximation
+         * Adds the 'remainder / b' term, using 'remainder / b.value' as an approximation
          * (otherwise we would have to invoke this method recursively). The approximation
          * is assumed okay since the second term is small compared to the first one.
          */



Mime
View raw message