You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2019/02/06 20:12:18 UTC

[sis] 02/03: Make explicit when a DoubleDouble arithmetic operation tries to guess an error term.

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 08088981ef4cf83e91aa341f170ce866f2b13783
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Wed Feb 6 12:46:45 2019 +0100

    Make explicit when a DoubleDouble arithmetic operation tries to guess an error term.
---
 .../sis/referencing/cs/CoordinateSystems.java      |   6 +-
 .../sis/referencing/datum/BursaWolfParameters.java |  24 ++--
 .../sis/referencing/datum/DefaultEllipsoid.java    |   8 +-
 .../sis/referencing/datum/TimeDependentBWP.java    |   6 +-
 .../sis/referencing/operation/matrix/Matrices.java |   8 +-
 .../referencing/operation/matrix/MatrixSIS.java    |  18 +--
 .../operation/projection/AlbersEqualArea.java      |   4 +-
 .../operation/projection/CylindricalEqualArea.java |   6 +-
 .../operation/projection/Initializer.java          |  12 +-
 .../projection/LambertConicConformal.java          |   6 +-
 .../referencing/operation/projection/Mercator.java |   2 +-
 .../operation/projection/TransverseMercator.java   |   4 +-
 .../transform/EllipsoidToCentricTransform.java     |   2 +-
 .../org/apache/sis/internal/util/DoubleDouble.java | 122 ++++++++++++++++-----
 .../src/main/java/org/apache/sis/math/Line.java    |  12 +-
 .../src/main/java/org/apache/sis/math/Plane.java   |  22 ++--
 .../sis/storage/geotiff/GridGeometryBuilder.java   |   4 +-
 17 files changed, 168 insertions(+), 98 deletions(-)

diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
index b8a00a3..005e9c5 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
@@ -328,11 +328,11 @@ public final class CoordinateSystems extends Static {
                 }
                 final DoubleDouble element = DoubleDouble.castOrCopy(matrix.getNumber(j,i));
                 final DoubleDouble r = new DoubleDouble(element);
-                r.multiply(scale);
+                r.multiplyGuessError(scale);
                 matrix.setNumber(j, i, r);
                 r.setFrom(element);
-                r.multiply(offset);
-                r.add(matrix.getNumber(j, sourceDim));
+                r.multiplyGuessError(offset);
+                r.addGuessError(matrix.getNumber(j, sourceDim));
                 matrix.setNumber(j, sourceDim, r);
             }
         }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
index 1b26fee..42b8719 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
@@ -491,8 +491,8 @@ public class BursaWolfParameters extends FormattableObject implements Cloneable,
          */
         final DoubleDouble RS = DoubleDouble.createSecondsToRadians();
         final DoubleDouble S = param(6, period);
-        S.divide(PPM, 0);
-        S.add(1, 0);                                                // S = 1 + dS / PPM;
+        S.divide(PPM);
+        S.add(1);                                                   // S = 1 + dS / PPM;
         RS.multiply(S);                                             // RS = toRadians(1″) * S;
         final DoubleDouble  X = param(3, period); X.multiply(RS);
         final DoubleDouble  Y = param(4, period); Y.multiply(RS);
@@ -550,17 +550,17 @@ public class BursaWolfParameters extends FormattableObject implements Cloneable,
          * (this will be verified later).
          */
         final DoubleDouble S = DoubleDouble.castOrCopy(getNumber(matrix, 0,0));
-        S.add(getNumber(matrix, 1,1));
-        S.add(getNumber(matrix, 2,2));
-        S.divide(3, 0);
+        S.addGuessError(getNumber(matrix, 1,1));
+        S.addGuessError(getNumber(matrix, 2,2));
+        S.divide(3);
         /*
          * Computes: RS = S * toRadians(1″)
          *           dS = (S-1) * PPM
          */
         final DoubleDouble RS = DoubleDouble.createSecondsToRadians();
         RS.multiply(S);
-        S.add(-1, 0);
-        S.multiply(PPM, 0);
+        S.add(-1);
+        S.multiply(PPM);
         dS = S.doubleValue();
         /*
          * Rotation terms. Each rotation terms appear twice, with one value being the negative of the other value.
@@ -573,17 +573,17 @@ public class BursaWolfParameters extends FormattableObject implements Cloneable,
             }
             for (int i = j+1; i < SIZE-1; i++) {
                 S.setFrom(RS);
-                S.inverseDivide(getNumber(matrix, j,i));        // Negative rotation term.
+                S.inverseDivideGuessError(getNumber(matrix, j,i));          // Negative rotation term.
                 double value = S.value;
                 double error = S.error;
                 S.setFrom(RS);
-                S.inverseDivide(getNumber(matrix, i,j));        // Positive rotation term.
-                if (!(abs(value + S.value) <= tolerance)) {     // We expect r1 ≈ -r2
+                S.inverseDivideGuessError(getNumber(matrix, i,j));          // Positive rotation term.
+                if (!(abs(value + S.value) <= tolerance)) {                 // We expect r1 ≈ -r2
                     throw new IllegalArgumentException(Resources.format(Resources.Keys.NotASkewSymmetricMatrix));
                 }
                 S.subtract(value, error);
-                S.multiply(0.5, 0);
-                value = S.doubleValue();                        // Average of the two rotation terms.
+                S.multiply(0.5);
+                value = S.doubleValue();                                    // Average of the two rotation terms.
                 switch (j*SIZE + i) {
                     case 1: rZ =  value; break;
                     case 2: rY = -value; break;
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
index 2fceb0e..bcc59de 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
@@ -444,7 +444,7 @@ public class DefaultEllipsoid extends AbstractIdentifiedObject implements Ellips
     private DoubleDouble eccentricitySquared() {
         final DoubleDouble f = flattening(this);
         final DoubleDouble eccentricitySquared = new DoubleDouble(f);
-        eccentricitySquared.multiply(2, 0);
+        eccentricitySquared.multiply(2);
         f.square();
         eccentricitySquared.subtract(f);
         return eccentricitySquared;
@@ -466,12 +466,12 @@ public class DefaultEllipsoid extends AbstractIdentifiedObject implements Ellips
         final DoubleDouble f;
         if (e.isIvfDefinitive()) {
             f = DoubleDouble.createAndGuessError(e.getInverseFlattening());   // Presumed accurate in base 10 (not 2) by definition.
-            f.inverseDivide(1, 0);
+            f.inverseDivide(1);
         } else {
             f = DoubleDouble.createAndGuessError(e.getSemiMajorAxis());       // Presumed accurate in base 10 (not 2) by definition.
             final double value = f.value;
             final double error = f.error;
-            f.subtract(e.getSemiMinorAxis());                                 // Presumed accurate in base 10 (not 2) by definition.
+            f.subtractGuessError(e.getSemiMinorAxis());                       // Presumed accurate in base 10 (not 2) by definition.
             f.divide(value, error);
         }
         return f;
@@ -637,7 +637,7 @@ public class DefaultEllipsoid extends AbstractIdentifiedObject implements Ellips
         double semiMajor = other.getSemiMajorAxis();
         semiMajor = other.getAxisUnit().getConverterTo(getAxisUnit()).convert(semiMajor);            // Often a no-op.
         final DoubleDouble a = DoubleDouble.createAndGuessError(semiMajor);     // Presumed accurate in base 10 if no unit conversion.
-        a.subtract(getSemiMajorAxis());                                         // Presumed accurate in base 10 (not 2) by definition.
+        a.subtractGuessError(getSemiMajorAxis());                               // Presumed accurate in base 10 (not 2) by definition.
         return a.doubleValue();
     }
 
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
index 07a7bde..ad418c3 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
@@ -161,7 +161,7 @@ public class TimeDependentBWP extends BursaWolfParameters {
             final long millis = time.getTime() - timeReference;
             if (millis != 0) {                                          // Returns null for 0 as an optimization.
                 final DoubleDouble period = new DoubleDouble(millis);
-                period.divide(1000 * JULIAN_YEAR_LENGTH, 0);
+                period.divide(1000 * JULIAN_YEAR_LENGTH);
                 return period;
             }
         }
@@ -189,10 +189,10 @@ public class TimeDependentBWP extends BursaWolfParameters {
                 case 3: d = drX; break;
                 case 4: d = drY; break;
                 case 5: d = drZ; break;
-                case 6: d = ddS; period.multiply(1000, 0); break;
+                case 6: d = ddS; period.multiply(1000); break;
                 default: throw new AssertionError(index);
             }
-            period.multiply(d);
+            period.multiplyGuessError(d);
             p.add(period);
             period.value = value;
             period.error = error;
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
index 8cb69bc..eb8707a 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
@@ -281,13 +281,13 @@ public final class Matrices extends Static {
                          * we use the lower/upper corners instead than getMinimum()/getMaximum() methods.
                          */
                         final DoubleDouble scale = new DoubleDouble(same ? +1d : -1d);
-                        scale.multiply(dstEnvelope.getSpan(dstIndex));
-                        scale.divide  (srcEnvelope.getSpan(srcIndex));
+                        scale.multiplyGuessError(dstEnvelope.getSpan(dstIndex));
+                        scale.divideGuessError  (srcEnvelope.getSpan(srcIndex));
 
                         final DoubleDouble translate = new DoubleDouble(scale);
-                        translate.multiply((same ? srcCorner : srcOppositeCorner).getOrdinate(srcIndex));
+                        translate.multiplyGuessError((same ? srcCorner : srcOppositeCorner).getOrdinate(srcIndex));
                         translate.negate();
-                        translate.add(dstCorner.getOrdinate(dstIndex));
+                        translate.addGuessError(dstCorner.getOrdinate(dstIndex));
 
                         matrix.setNumber(dstIndex, srcIndex,       scale);
                         matrix.setNumber(dstIndex, srcAxes.length, translate);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
index eeae9f5..29a21ef 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
@@ -487,15 +487,15 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
         final DoubleDouble t = new DoubleDouble();
         for (int j = getNumRow(); --j >= 0;) {
             if (offset != null) {
-                get(j, srcDim,  s);     // Scale factor
-                get(j, lastCol, t);     // Translation factor
-                s.multiply(offset);
+                get(j, srcDim,  s);             // Scale factor
+                get(j, lastCol, t);             // Translation factor
+                s.multiplyGuessError(offset);
                 t.add(s);
                 set(j, lastCol, t);
             }
             if (scale != null) {
-                get(j, srcDim, s);      // Scale factor
-                s.multiply(scale);
+                get(j, srcDim, s);              // Scale factor
+                s.multiplyGuessError(scale);
                 set(j, srcDim, s);
             }
         }
@@ -523,13 +523,13 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
         if (scale != null) {
             for (int i=lastCol; i>=0; i--) {
                 get(tgtDim, i, s);
-                s.multiply(scale);
+                s.multiplyGuessError(scale);
                 set(tgtDim, i, s);
             }
         }
         if (offset != null) {
             get(tgtDim, lastCol, s);
-            s.add(offset);
+            s.addGuessError(offset);
             set(tgtDim, lastCol, s);
         }
     }
@@ -587,7 +587,7 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
         for (int j=0; j<target.length; j++) {
             for (int i=0; i<numCol; i++) {
                 get(j, i, ele);
-                ele.multiply(vector[i]);
+                ele.multiplyGuessError(vector[i]);
                 sum.add(ele);
             }
             target[j] = sum.doubleValue();
@@ -636,7 +636,7 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
             s.clear();
             for (int i=0; i<numCol; i++) {
                 get(j, i, t);
-                t.multiply(vector[i]);
+                t.multiplyGuessError(vector[i]);
                 s.add(t);
             }
             set(j, numCol-1, s);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/AlbersEqualArea.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/AlbersEqualArea.java
index c59b0c2..c2a137a 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/AlbersEqualArea.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/AlbersEqualArea.java
@@ -143,7 +143,7 @@ public class AlbersEqualArea extends EqualAreaProjection {
          */
         final DoubleDouble rn = new DoubleDouble(1d);
         rn.subtract(initializer.eccentricitySquared);
-        rn.divide(nm, 0);
+        rn.divide(nm);
         /*
          * Compute  ρ₀ = √(C - n⋅q(sinφ₀))/n  with multiplication by a omitted because already taken in account
          * by the denormalization matrix. Omitted (1-ℯ²) term in nm cancels with omitted (1-ℯ²) term in qm(…).
@@ -159,7 +159,7 @@ public class AlbersEqualArea extends EqualAreaProjection {
         final MatrixSIS normalize   = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
         final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
         denormalize.convertBefore(0, rn, null); rn.negate();
-        denormalize.convertBefore(1, rn, ρ0);   rn.inverseDivide(-1, 0);
+        denormalize.convertBefore(1, rn, ρ0);   rn.inverseDivide(-1);
         normalize.convertAfter(0, rn, null);
         super.computeCoefficients();
     }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/CylindricalEqualArea.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/CylindricalEqualArea.java
index 506eb82..6cc9fb6 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/CylindricalEqualArea.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/CylindricalEqualArea.java
@@ -140,7 +140,7 @@ public class CylindricalEqualArea extends EqualAreaProjection {
         final double λ0 = initializer.getAndStore(LONGITUDE_OF_ORIGIN);
         if (λ0 != 0) {
             final DoubleDouble offset = DoubleDouble.createDegreesToRadians();
-            offset.multiply(-λ0);
+            offset.multiplyGuessError(-λ0);
             denormalize.convertBefore(0, null, offset);
         }
         /*
@@ -150,7 +150,7 @@ public class CylindricalEqualArea extends EqualAreaProjection {
          */
         final double φ1 = toRadians(initializer.getAndStore(STANDARD_PARALLEL));
         final DoubleDouble k0 = new DoubleDouble(initializer.scaleAtφ(sin(φ1), cos(φ1)));
-        k0.multiply(initializer.getAndStore(Mercator1SP.SCALE_FACTOR));
+        k0.multiplyGuessError(initializer.getAndStore(Mercator1SP.SCALE_FACTOR));
         /*
          * In most Apache SIS map projection implementations, the scale factor is handled by the super-class by
          * specifying a ParameterRole.SCALE_FACTOR. However in the case of this CylindricalEqualArea we rather
@@ -164,7 +164,7 @@ public class CylindricalEqualArea extends EqualAreaProjection {
          */
         final DoubleDouble ik = new DoubleDouble(1d);
         ik.subtract(initializer.eccentricitySquared);
-        ik.multiply(0.5, 0);                 // This line need to be cancelled when using spherical formulas.
+        ik.multiply(0.5);                   // This line need to be cancelled when using spherical formulas.
         ik.divide(k0);
         denormalize.convertAfter(0, k0, null);
         denormalize.convertAfter(1, ik, null);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
index b4adf94..c551e42 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
@@ -177,9 +177,9 @@ final class Initializer {
                  */
                 if (isIvfDefinitive) {
                     final DoubleDouble f = DoubleDouble.createAndGuessError(parameters.parameter(Constants.INVERSE_FLATTENING).doubleValue());
-                    f.inverseDivide(1,0);
+                    f.inverseDivide(1);
                     eccentricitySquared.setFrom(f);
-                    eccentricitySquared.multiply(2,0);
+                    eccentricitySquared.multiply(2);
                     f.square();
                     eccentricitySquared.subtract(f);
                 } else {
@@ -208,7 +208,7 @@ final class Initializer {
                      *     k = b / (1 - eccentricitySquared * (sinφ*sinφ));
                      */
                     k = rν2(sin(toRadians(parameters.doubleValue(radius))));
-                    k.inverseDivide(b, 0);
+                    k.inverseDivide(b);
                 }
             }
         }
@@ -219,7 +219,7 @@ final class Initializer {
          */
         final ParameterDescriptor<? extends Number> scaleFactor = roles.get(ParameterRole.SCALE_FACTOR);
         if (scaleFactor != null) {
-            k.multiply(getAndStore(scaleFactor));
+            k.multiplyGuessError(getAndStore(scaleFactor));
         }
         /*
          * Set meridian rotation, scale factor, false easting and false northing parameter values
@@ -325,7 +325,7 @@ final class Initializer {
          * this is where double-double arithmetic has more value.
          */
         t.negate();
-        t.add(1,0);
+        t.add(1);
         return t;
     }
 
@@ -366,7 +366,7 @@ final class Initializer {
     final double scaleAtφ(final double sinφ, final double cosφ) {
         final DoubleDouble s = rν2(sinφ);
         s.sqrt();
-        s.inverseDivide(cosφ, 0);
+        s.inverseDivide(cosφ);
         return s.doubleValue();
     }
 }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
index 666a7a8..08898ac 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
@@ -289,8 +289,8 @@ public class LambertConicConformal extends ConformalProjection {
          * be stored in that format anyway. This makes a change in the 2 or 3 last digits.
          */
         final DoubleDouble F = new DoubleDouble(n);
-        F.multiply(pow(t1, n), 0);
-        F.inverseDivide(m1);
+        F.multiply(pow(t1, n));
+        F.inverseDivideGuessError(m1);
         if (!isNorth) {
             F.negate();
         }
@@ -305,7 +305,7 @@ public class LambertConicConformal extends ConformalProjection {
         DoubleDouble rF = null;
         if (φ0 != copySign(PI/2, -n)) {    // For reducing the rounding error documented in expOfNorthing(+π/2).
             rF = new DoubleDouble(F);
-            rF.multiply(pow(expOfNorthing(φ0, eccentricity*sin(φ0)), n), 0);
+            rF.multiply(pow(expOfNorthing(φ0, eccentricity*sin(φ0)), n));
         }
         /*
          * At this point, all parameters have been processed. Now store
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
index e799998..c1b672f 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Mercator.java
@@ -255,7 +255,7 @@ public class Mercator extends ConformalProjection {
              * there is no such goal for other parameters computed from sine or consine functions.
              */
             final DoubleDouble offset = DoubleDouble.createDegreesToRadians();
-            offset.multiply(-λ0);
+            offset.multiplyGuessError(-λ0);
             denormalize.convertBefore(0, null, offset);
         }
         if (φ0 != 0) {
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
index e6b9d45..866f993 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/TransverseMercator.java
@@ -151,7 +151,7 @@ public class TransverseMercator extends ConformalProjection {
             B = new DoubleDouble(t);        // B  =  n
             B.square();
             B.series(1, 0.25, 1./64);       // B  =  (1 + n²/4 + n⁴/64)
-            t.add(1, 0);
+            t.add(1);
             B.divide(t);                    // B  =  (1 + n²/4 + n⁴/64) / (1 + n)
         }
         /*
@@ -216,7 +216,7 @@ public class TransverseMercator extends ConformalProjection {
          * 'n' value at serialization time.
          */
         final DoubleDouble t = new DoubleDouble(1d);
-        t.subtract(eccentricitySquared, 0);
+        t.subtract(eccentricitySquared);
         t.sqrt();
         t.ratio_1m_1p();
         computeCoefficients(t.doubleValue());
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java
index 26a55c2..845f02a 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java
@@ -295,7 +295,7 @@ public class EllipsoidToCentricTransform extends AbstractMathTransform implement
             denormalize.convertAfter(i, a, null);
         }
         if (withHeight) {
-            a.inverseDivide(1, 0);
+            a.inverseDivide(1);
             final MatrixSIS normalize = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
             normalize.convertBefore(2, a, null);    // Divide ellipsoidal height by a.
         }
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 48e293b..f404852 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
@@ -212,7 +212,7 @@ public final class DoubleDouble extends Number {
     public DoubleDouble(Number otherValue) {
         if (otherValue instanceof Fraction) {
             value = ((Fraction) otherValue).denominator;
-            inverseDivide(((Fraction) otherValue).numerator, 0);
+            inverseDivide(((Fraction) otherValue).numerator);
         } else {
             if (otherValue instanceof BigInteger) {
                 otherValue = new BigDecimal((BigInteger) otherValue, MathContext.DECIMAL128);
@@ -542,13 +542,13 @@ public final class DoubleDouble extends Number {
      *
      * @param  other  the other value to add to this {@code DoubleDouble}.
      */
-    public void add(final Number other) {
+    public void addGuessError(final Number other) {
         if (other instanceof DoubleDouble) {
             add((DoubleDouble) other);
         } else if (shouldConvert(other)) {
             add(new DoubleDouble(other));
         } else {
-            add(other.doubleValue());
+            addGuessError(other.doubleValue());
         }
     }
 
@@ -561,15 +561,29 @@ public final class DoubleDouble extends Number {
      * }
      *
      * <b>Tip:</b> if the other value is known to be an integer or a power of 2, then invoking
-     * <code>{@linkplain #add(double, double) add}(otherValue, 0)</code> is more efficient.
+     * <code>{@linkplain #add(double) add}(otherValue)</code> is more efficient.
      *
      * @param  otherValue  the other value to add to this {@code DoubleDouble}.
      */
-    public void add(final double otherValue) {
+    public void addGuessError(final double otherValue) {
         add(otherValue, errorForWellKnownValue(otherValue));
     }
 
     /**
+     * Adds a {@code double} value to this {@code DoubleDouble} without error term.
+     * This is a convenience method for:
+     *
+     * {@preformat java
+     *    add(otherValue, 0);
+     * }
+     *
+     * @param  otherValue  the other value to add to this {@code DoubleDouble}.
+     */
+    public void add(final double otherValue) {
+        add(otherValue, 0);
+    }
+
+    /**
      * Adds an other double-double value to this {@code DoubleDouble}.
      * The result is stored in this instance.
      *
@@ -656,13 +670,13 @@ public final class DoubleDouble extends Number {
      *
      * @param  other  the other value to subtract from this {@code DoubleDouble}.
      */
-    public void subtract(final Number other) {
+    public void subtractGuessError(final Number other) {
         if (other instanceof DoubleDouble) {
             subtract((DoubleDouble) other);
         } else if (shouldConvert(other)) {
             subtract(new DoubleDouble(other));
         } else {
-            subtract(other.doubleValue());
+            subtractGuessError(other.doubleValue());
         }
     }
 
@@ -675,15 +689,29 @@ public final class DoubleDouble extends Number {
      * }
      *
      * <b>Tip:</b> if the other value is known to be an integer or a power of 2, then invoking
-     * <code>{@linkplain #subtract(double, double) subtract}(otherValue, 0)</code> is more efficient.
+     * <code>{@linkplain #subtract(double) subtract}(otherValue)</code> is more efficient.
      *
      * @param  otherValue  the other value to subtract from this {@code DoubleDouble}.
      */
-    public void subtract(final double otherValue) {
+    public void subtractGuessError(final double otherValue) {
         subtract(otherValue, errorForWellKnownValue(otherValue));
     }
 
     /**
+     * Subtracts a {@code double} from this {@code DoubleDouble} without error term.
+     * This is a convenience method for:
+     *
+     * {@preformat java
+     *    subtract(otherValue, 0);
+     * }
+     *
+     * @param  otherValue  the other value to subtract from this {@code DoubleDouble}.
+     */
+    public void subtract(final double otherValue) {
+        subtract(otherValue, 0);
+    }
+
+    /**
      * Subtracts an other double-double value from this {@code DoubleDouble}.
      * The result is stored in this instance.
      *
@@ -730,13 +758,13 @@ public final class DoubleDouble extends Number {
      *
      * @param  other  the other value to multiply by this {@code DoubleDouble}.
      */
-    public void multiply(final Number other) {
+    public void multiplyGuessError(final Number other) {
         if (other instanceof DoubleDouble) {
             multiply((DoubleDouble) other);
         } else if (shouldConvert(other)) {
             multiply(new DoubleDouble(other));
         } else {
-            multiply(other.doubleValue());
+            multiplyGuessError(other.doubleValue());
         }
     }
 
@@ -749,15 +777,29 @@ public final class DoubleDouble extends Number {
      * }
      *
      * <b>Tip:</b> if the other value is known to be an integer or a power of 2, then invoking
-     * <code>{@linkplain #multiply(double, double) multiply}(otherValue, 0)</code> is more efficient.
+     * <code>{@linkplain #multiply(double) multiply}(otherValue)</code> is more efficient.
      *
      * @param  otherValue  the other value to multiply by this {@code DoubleDouble}.
      */
-    public void multiply(final double otherValue) {
+    public void multiplyGuessError(final double otherValue) {
         multiply(otherValue, errorForWellKnownValue(otherValue));
     }
 
     /**
+     * Multiplies this {@code DoubleDouble} by a {@code double} without error term.
+     * This is a convenience method for:
+     *
+     * {@preformat java
+     *    multiply(otherValue, 0);
+     * }
+     *
+     * @param  otherValue  the other value to multiply by this {@code DoubleDouble}.
+     */
+    public void multiply(final double otherValue) {
+        multiply(otherValue, 0);
+    }
+
+    /**
      * Multiplies this {@code DoubleDouble} by an other double-double value.
      * The result is stored in this instance.
      *
@@ -833,13 +875,13 @@ public final class DoubleDouble extends Number {
      *
      * @param  other  the other value by which to divide this {@code DoubleDouble}.
      */
-    public void divide(final Number other) {
+    public void divideGuessError(final Number other) {
         if (other instanceof DoubleDouble) {
             divide((DoubleDouble) other);
         } else if (shouldConvert(other)) {
             divide(new DoubleDouble(other));
         } else {
-            divide(other.doubleValue());
+            divideGuessError(other.doubleValue());
         }
     }
 
@@ -852,15 +894,29 @@ public final class DoubleDouble extends Number {
      * }
      *
      * <b>Tip:</b> if the other value is known to be an integer or a power of 2, then invoking
-     * <code>{@linkplain #divide(double, double) divide}(otherValue, 0)</code> is more efficient.
+     * <code>{@linkplain #divide(double) divide}(otherValue)</code> is more efficient.
      *
      * @param  otherValue  the other value by which to divide this {@code DoubleDouble}.
      */
-    public void divide(final double otherValue) {
+    public void divideGuessError(final double otherValue) {
         divide(otherValue, errorForWellKnownValue(otherValue));
     }
 
     /**
+     * Divides this {@code DoubleDouble} by a {@code double} without error term.
+     * This is a convenience method for:
+     *
+     * {@preformat java
+     *    divide(otherValue, 0);
+     * }
+     *
+     * @param  otherValue  the other value by which to divide this {@code DoubleDouble}.
+     */
+    public void divide(final double otherValue) {
+        divide(otherValue, 0);
+    }
+
+    /**
      * Divides this {@code DoubleDouble} by an other double-double value.
      * The result is stored in this instance.
      *
@@ -916,13 +972,13 @@ public final class DoubleDouble extends Number {
      *
      * @param  other  the other value to divide by this {@code DoubleDouble}.
      */
-    public void inverseDivide(final Number other) {
+    public void inverseDivideGuessError(final Number other) {
         if (other instanceof DoubleDouble) {
             inverseDivide((DoubleDouble) other);
         } else if (shouldConvert(other)) {
             inverseDivide(new DoubleDouble(other));
         } else {
-            inverseDivide(other.doubleValue());
+            inverseDivideGuessError(other.doubleValue());
         }
     }
 
@@ -935,15 +991,29 @@ public final class DoubleDouble extends Number {
      * }
      *
      * <b>Tip:</b> if the other value is known to be an integer or a power of 2, then invoking
-     * <code>{@linkplain #inverseDivide(double, double) inverseDivide}(otherValue, 0)</code> is more efficient.
+     * <code>{@linkplain #inverseDivide(double) inverseDivide}(otherValue)</code> is more efficient.
      *
      * @param  numeratorValue  the other value to divide by this {@code DoubleDouble}.
      */
-    public void inverseDivide(final double numeratorValue) {
+    public void inverseDivideGuessError(final double numeratorValue) {
         inverseDivide(numeratorValue, errorForWellKnownValue(numeratorValue));
     }
 
     /**
+     * Divides the given {@code double} value by this {@code DoubleDouble} without error term.
+     * This is a convenience method for:
+     *
+     * {@preformat java
+     *    inverseDivide(numeratorValue, 0);
+     * }
+     *
+     * @param  numeratorValue  the other value to divide by this {@code DoubleDouble}.
+     */
+    public void inverseDivide(final double numeratorValue) {
+        inverseDivide(numeratorValue, 0);
+    }
+
+    /**
      * Divides the given double-double value by this {@code DoubleDouble}.
      * The result is stored in this instance.
      *
@@ -970,7 +1040,7 @@ public final class DoubleDouble extends Number {
          * The 'b * (a.value / b.value)' part in the method javadoc.
          */
         final double quotient = numeratorValue / denominatorValue;
-        multiply(quotient, 0);
+        multiply(quotient);
         /*
          * Compute 'remainder' as 'a - above_product'.
          */
@@ -1009,7 +1079,7 @@ public final class DoubleDouble extends Number {
     public void ratio_1m_1p() {
         final DoubleDouble numerator = new DoubleDouble(1d);
         numerator.subtract(this);
-        add(1, 0);
+        add(1);
         inverseDivide(numerator);
     }
 
@@ -1049,7 +1119,7 @@ public final class DoubleDouble extends Number {
             double r = Math.sqrt(thisValue);
             setToProduct(r, r);
             subtract(thisValue, thisError);
-            divide(-2*r, 0);                    // Multiplication by 2 does not cause any precision lost.
+            divide(-2*r);                           // Multiplication by 2 does not cause any precision lost.
             setToQuickSum(r, value);
         }
     }
@@ -1070,12 +1140,12 @@ public final class DoubleDouble extends Number {
             final DoubleDouble xn = new DoubleDouble(x);
             final DoubleDouble t = new DoubleDouble(xn);
             for (int i=1; i<last; i++) {
-                t.multiply(coefficients[i], 0);
+                t.multiply(coefficients[i]);
                 add(t);
                 xn.multiply(x);
                 t.setFrom(xn);
             }
-            t.multiply(coefficients[last], 0);
+            t.multiply(coefficients[last]);
             add(t);
         }
     }
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 ac65ae9..3a57bee 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
@@ -308,8 +308,8 @@ public class Line implements Cloneable, Serializable {
                 n++;
             }
         }
-        mean_x.divide(n, 0);
-        mean_y.divide(n, 0);
+        mean_x.divide(n);
+        mean_y.divide(n);
         /*
          * We have to solve two equations with two unknowns:
          *
@@ -330,7 +330,7 @@ public class Line implements Cloneable, Serializable {
         final DoubleDouble mean_xy = new DoubleDouble();
         for (final DirectPosition p : points) {
             final double y;
-            if (!isNaN(y       = p.getOrdinate(1)) &&  // Test first the dimension which is most likely to contain NaN.
+            if (!isNaN(y       = p.getOrdinate(1)) &&       // Test first the dimension which is most likely to contain NaN.
                 !isNaN(a.value = p.getOrdinate(0)))
             {
                 a.error = 0;
@@ -346,9 +346,9 @@ public class Line implements Cloneable, Serializable {
                 mean_y2.add(a);         // mean_y² += y²
             }
         }
-        mean_x2.divide(n, 0);
-        mean_y2.divide(n, 0);
-        mean_xy.divide(n, 0);
+        mean_x2.divide(n);
+        mean_y2.divide(n);
+        mean_xy.divide(n);
         /*
          * Assuming that 'mean(x) == 0', then the correlation
          * coefficient can be approximate by:
diff --git a/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java b/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java
index cbc1bc1..1dd05ae 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/math/Plane.java
@@ -442,11 +442,11 @@ public class Plane implements Cloneable, Serializable {
                     n++;
                 }
             }
-            sum_x .value = n/2d;  sum_x .multiply(nx-1,   0);                     // Division by 2 is exact.
-            sum_y .value = n/2d;  sum_y .multiply(ny-1,   0);
-            sum_xx.value = n;     sum_xx.multiply(nx-0.5, 0); sum_xx.multiply(nx-1, 0); sum_xx.divide(3, 0);
-            sum_yy.value = n;     sum_yy.multiply(ny-0.5, 0); sum_yy.multiply(ny-1, 0); sum_yy.divide(3, 0);
-            sum_xy.value = n/4d;  sum_xy.multiply(ny-1,   0); sum_xy.multiply(nx-1, 0);
+            sum_x .value = n/2d;  sum_x .multiply(nx-1);                     // Division by 2 is exact.
+            sum_y .value = n/2d;  sum_y .multiply(ny-1);
+            sum_xx.value = n;     sum_xx.multiply(nx-0.5);  sum_xx.multiply(nx-1);  sum_xx.divide(3);
+            sum_yy.value = n;     sum_yy.multiply(ny-0.5);  sum_yy.multiply(ny-1);  sum_yy.divide(3);
+            sum_xy.value = n/4d;  sum_xy.multiply(ny-1);    sum_xy.multiply(nx-1);
             this.n = n;
         }
 
@@ -458,11 +458,11 @@ public class Plane implements Cloneable, Serializable {
              *    ( sum_zx - sum_z⋅sum_x )  =  sx⋅(sum_xx - sum_x⋅sum_x) + sy⋅(sum_xy - sum_x⋅sum_y)
              *    ( sum_zy - sum_z⋅sum_y )  =  sx⋅(sum_xy - sum_x⋅sum_y) + sy⋅(sum_yy - sum_y⋅sum_y)
              */
-            zx.setFrom(sum_x); zx.divide(-n, 0); zx.multiply(sum_z); zx.add(sum_zx);    // zx = sum_zx - sum_z⋅sum_x/n
-            zy.setFrom(sum_y); zy.divide(-n, 0); zy.multiply(sum_z); zy.add(sum_zy);    // zy = sum_zy - sum_z⋅sum_y/n
-            xx.setFrom(sum_x); xx.divide(-n, 0); xx.multiply(sum_x); xx.add(sum_xx);    // xx = sum_xx - sum_x⋅sum_x/n
-            xy.setFrom(sum_y); xy.divide(-n, 0); xy.multiply(sum_x); xy.add(sum_xy);    // xy = sum_xy - sum_x⋅sum_y/n
-            yy.setFrom(sum_y); yy.divide(-n, 0); yy.multiply(sum_y); yy.add(sum_yy);    // yy = sum_yy - sum_y⋅sum_y/n
+            zx.setFrom(sum_x); zx.divide(-n); zx.multiply(sum_z); zx.add(sum_zx);    // zx = sum_zx - sum_z⋅sum_x/n
+            zy.setFrom(sum_y); zy.divide(-n); zy.multiply(sum_z); zy.add(sum_zy);    // zy = sum_zy - sum_z⋅sum_y/n
+            xx.setFrom(sum_x); xx.divide(-n); xx.multiply(sum_x); xx.add(sum_xx);    // xx = sum_xx - sum_x⋅sum_x/n
+            xy.setFrom(sum_y); xy.divide(-n); xy.multiply(sum_x); xy.add(sum_xy);    // xy = sum_xy - sum_x⋅sum_y/n
+            yy.setFrom(sum_y); yy.divide(-n); yy.multiply(sum_y); yy.add(sum_yy);    // yy = sum_yy - sum_y⋅sum_y/n
             /*
              * den = (xy⋅xy - xx⋅yy)
              */
@@ -483,7 +483,7 @@ public class Plane implements Cloneable, Serializable {
             tmp.add(z0);
             z0.setFrom(sum_z);
             z0.subtract(tmp);
-            z0.divide(n, 0);
+            z0.divide(n);
         }
 
         /**
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometryBuilder.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometryBuilder.java
index 24cff6a..06fd23d 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometryBuilder.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GridGeometryBuilder.java
@@ -258,8 +258,8 @@ final class GridGeometryBuilder {
                 for (int j=0; j<numDim; j++) {
                     t.value = -modelTiePoints.doubleValue(nearest + j);
                     t.error = DoubleDouble.errorForWellKnownValue(t.value);
-                    t.multiply(affine.getNumber(j, j));
-                    t.add(modelTiePoints.doubleValue(nearest + j + Localization.RECORD_LENGTH / 2));
+                    t.multiplyGuessError(affine.getNumber(j, j));
+                    t.addGuessError(modelTiePoints.doubleValue(nearest + j + Localization.RECORD_LENGTH / 2));
                     affine.setNumber(j, trCol, t);
                 }
                 return true;