sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 02/03: Minor performance improvement.
Date Thu, 07 Feb 2019 15:56:43 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 a5a0c04fc9efb6dc0641300c199b5c386a492b96
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Feb 7 15:03:45 2019 +0100

    Minor performance improvement.
---
 .../sis/referencing/datum/DatumShiftGrid.java      |  2 +-
 .../operation/builder/ResidualGrid.java            | 15 ++++++-------
 .../org/apache/sis/internal/util/DoubleDouble.java | 12 +++++++++++
 .../src/main/java/org/apache/sis/math/Line.java    |  4 ++--
 .../apache/sis/internal/util/DoubleDoubleTest.java | 25 +++++++++++++++++-----
 5 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DatumShiftGrid.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DatumShiftGrid.java
index f78e43e..4702749 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DatumShiftGrid.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DatumShiftGrid.java
@@ -581,7 +581,7 @@ public abstract class DatumShiftGrid<C extends Quantity<C>, T
extends Quantity<T
         final int ny = gridSize[1];
         for (int gridY=0; gridY<ny; gridY++) {
             for (int gridX=0; gridX<nx; gridX++) {
-                sum.add(getCellValue(dim, gridX, gridY));
+                sum.addKahan(getCellValue(dim, gridX, gridY));
             }
         }
         return sum.doubleValue() / (nx * ny);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ResidualGrid.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ResidualGrid.java
index b6de64a..4e27f04 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ResidualGrid.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/builder/ResidualGrid.java
@@ -194,14 +194,13 @@ final class ResidualGrid extends DatumShiftGridFile<Dimensionless,Dimensionless>
      */
     private final class Data extends FormattableObject implements Matrix, Function<int[],Number>
{
         /** Coefficients from the denormalization matrix for the row corresponding to this
dimension. */
-        private final double[] affine;
+        private final double c0, c1, c2;
 
         /** Creates a new matrix for the specified dimension. */
         Data(final int dim, final Matrix denormalization) {
-            affine = new double[denormalization.getNumCol()];
-            for (int i=0; i<affine.length; i++) {
-                affine[i] = denormalization.getElement(dim, i);
-            }
+            c0 = denormalization.getElement(dim, 0);
+            c1 = denormalization.getElement(dim, 1);
+            c2 = denormalization.getElement(dim, 2);
         }
 
         @SuppressWarnings("CloneInNonCloneableClass")
@@ -214,9 +213,9 @@ final class ResidualGrid extends DatumShiftGridFile<Dimensionless,Dimensionless>
 
         /** Computes the matrix element in the given row and column. */
         @Override public double  getElement(final int y, final int x) {
-            return affine[0] * (x + getCellValue(0, x, y)) +                // TODO: use
Math.fma with JDK9.
-                   affine[1] * (y + getCellValue(1, x, y)) +
-                   affine[2];
+            return c0 * (x + getCellValue(0, x, y)) +                // TODO: use Math.fma
with JDK9.
+                   c1 * (y + getCellValue(1, x, y)) +
+                   c2;
         }
 
         /**
diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
index f404852..12b6efc 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
@@ -570,6 +570,18 @@ public final class DoubleDouble extends Number {
     }
 
     /**
+     * Adds the given {@code double} value using
+     * <a href="https://en.wikipedia.org/wiki/Kahan_summation_algorithm">Kahan summation
algorithm</a>.
+     * This can be used when {@code otherValue} is known to be smaller than {@link #value}.
+     *
+     * @param  y  the other value to add to this {@code DoubleDouble}.
+     */
+    public void addKahan(double y) {
+        y += error;
+        error = y + (value - (value += y));
+    }
+
+    /**
      * Adds a {@code double} value to this {@code DoubleDouble} without error term.
      * This is a convenience method for:
      *
diff --git a/core/sis-utility/src/main/java/org/apache/sis/math/Line.java b/core/sis-utility/src/main/java/org/apache/sis/math/Line.java
index 3a57bee..3493df9 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/math/Line.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/math/Line.java
@@ -303,8 +303,8 @@ public class Line implements Cloneable, Serializable {
             if (!isNaN(y = p.getOrdinate(1)) &&     // Test first the dimension which
is most likely to contain NaN.
                 !isNaN(x = p.getOrdinate(0)))
             {
-                mean_x.add(x);
-                mean_y.add(y);
+                mean_x.addKahan(x);
+                mean_y.addKahan(y);
                 n++;
             }
         }
diff --git a/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
b/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
index 54a2365..0401fc8 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
@@ -104,7 +104,7 @@ public final strictfp class DoubleDoubleTest extends TestCase {
     }
 
     /**
-     * Asserts that the result of some operation is equals to the expected value,
+     * Asserts that the result of some operation is equal to the expected value,
      * up to a tolerance value determined by the extended arithmetic precision.
      *
      * @param expected  the expected value, computed using {@code BigInteger} arithmetic.
@@ -115,7 +115,7 @@ public final strictfp class DoubleDoubleTest extends TestCase {
         final BigDecimal value = toBigDecimal(actual);
         final double delta = abs(expected.subtract(value).doubleValue());
         final double threshold = max(ulp(actual.error), ulp(actual.value) * ef);
-        if (!(delta <= threshold)) { // Use ! for catching NaN values.
+        if (!(delta <= threshold)) {                                                //
Use ! for catching NaN values.
             fail("Arithmetic error:\n" +
                  "  Expected:   " + expected  + '\n' +
                  "  Actual:     " + value     + '\n' +
@@ -199,6 +199,21 @@ public final strictfp class DoubleDoubleTest extends TestCase {
     }
 
     /**
+     * Tests {@link DoubleDouble#addKahan(double)}.
+     */
+    @Test
+    public void testAddKahan() {
+        final DoubleDouble dd = new DoubleDouble(1, 0);
+        BigDecimal expected = BigDecimal.ONE;
+        for (int i=0; i<NUMBER_OF_REPETITIONS; i++) {
+            final double b = random.nextDouble();
+            dd.addKahan(b);
+            expected = expected.add(new BigDecimal(b));
+            assertExtendedEquals(expected, dd, ADD_TOLERANCE_FACTOR * NUMBER_OF_REPETITIONS);
+        }
+    }
+
+    /**
      * Tests {@link DoubleDouble#add(DoubleDouble)}.
      */
     @Test
@@ -210,7 +225,7 @@ public final strictfp class DoubleDoubleTest extends TestCase {
             nextRandom(dd);
             nextRandom(op);
             final BigDecimal expected = toBigDecimal(dd).add(toBigDecimal(op));
-            dd.add(op); // Must be after 'expected' computation.
+            dd.add(op);     // Must be after 'expected' computation.
             assertExtendedEquals(expected, dd, ADD_TOLERANCE_FACTOR);
         }
     }
@@ -227,7 +242,7 @@ public final strictfp class DoubleDoubleTest extends TestCase {
             nextRandom(dd);
             nextRandom(op);
             final BigDecimal expected = toBigDecimal(dd).multiply(toBigDecimal(op), MathContext.DECIMAL128);
-            dd.multiply(op); // Must be after 'expected' computation.
+            dd.multiply(op);    // Must be after 'expected' computation.
             assertExtendedEquals(expected, dd, PRODUCT_TOLERANCE_FACTOR);
         }
     }
@@ -244,7 +259,7 @@ public final strictfp class DoubleDoubleTest extends TestCase {
             nextRandom(dd);
             nextRandom(op);
             final BigDecimal expected = toBigDecimal(dd).divide(toBigDecimal(op), MathContext.DECIMAL128);
-            dd.divide(op); // Must be after 'expected' computation.
+            dd.divide(op);      // Must be after 'expected' computation.
             assertExtendedEquals(expected, dd, PRODUCT_TOLERANCE_FACTOR);
         }
     }


Mime
View raw message