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:17 UTC
[sis] 01/03: Change in DoubleDouble construction policy: make
explicit when an error term is guessed from the 'double' value.
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 a62ef5a7b83dff5aa883a774b2eacc7785f3e30e
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Wed Feb 6 11:17:26 2019 +0100
Change in DoubleDouble construction policy: make explicit when an error term is guessed from the 'double' value.
---
.../referencing/provider/Equirectangular.java | 6 +--
.../sis/referencing/datum/BursaWolfParameters.java | 2 +-
.../sis/referencing/datum/DefaultEllipsoid.java | 10 ++---
.../sis/referencing/datum/TimeDependentBWP.java | 5 +--
.../sis/referencing/operation/matrix/Matrices.java | 2 +-
.../operation/projection/AlbersEqualArea.java | 4 +-
.../operation/projection/CylindricalEqualArea.java | 5 +--
.../operation/projection/Initializer.java | 19 ++++-----
.../projection/LambertConicConformal.java | 7 ++--
.../referencing/operation/projection/Mercator.java | 7 ++--
.../operation/projection/PolarStereographic.java | 10 ++---
.../operation/projection/TransverseMercator.java | 2 +-
.../operation/transform/ContextualParameters.java | 2 +-
.../transform/EllipsoidToCentricTransform.java | 2 +-
.../org/apache/sis/internal/util/DoubleDouble.java | 48 +++++++++++++---------
.../apache/sis/internal/util/DoubleDoubleTest.java | 26 +++++++++---
16 files changed, 89 insertions(+), 68 deletions(-)
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
index 2b17228..d7e8c31 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Equirectangular.java
@@ -299,10 +299,10 @@ public final class Equirectangular extends AbstractProvider {
final double sinφ1 = sin(φ1);
a = b / (1 - (1 - rs*rs) * (sinφ1*sinφ1));
}
- final DoubleDouble k = new DoubleDouble(a);
+ final DoubleDouble k = DoubleDouble.createAndGuessError(a);
final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
- denormalize.convertAfter(0, k, new DoubleDouble(fe));
- denormalize.convertAfter(1, k, new DoubleDouble(fn));
+ denormalize.convertAfter(0, k, DoubleDouble.createAndGuessError(fe));
+ denormalize.convertAfter(1, k, DoubleDouble.createAndGuessError(fn));
/*
* Creates the ConcatenatedTransform, letting the factory returns the cached instance
* if the caller already invoked this method previously (which usually do not happen).
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 0a1f1c8..1b26fee 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
@@ -430,7 +430,7 @@ public class BursaWolfParameters extends FormattableObject implements Cloneable,
case 6: p = dS; break;
default: throw new AssertionError(index);
}
- return new DoubleDouble(p);
+ return DoubleDouble.createAndGuessError(p);
}
/**
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 8686944..2fceb0e 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
@@ -465,13 +465,13 @@ public class DefaultEllipsoid extends AbstractIdentifiedObject implements Ellips
private static DoubleDouble flattening(final Ellipsoid e) {
final DoubleDouble f;
if (e.isIvfDefinitive()) {
- f = new DoubleDouble(e.getInverseFlattening()); // Presumed accurate in base 10 (not 2) by definition.
+ f = DoubleDouble.createAndGuessError(e.getInverseFlattening()); // Presumed accurate in base 10 (not 2) by definition.
f.inverseDivide(1, 0);
} else {
- f = new DoubleDouble(e.getSemiMajorAxis()); // Presumed accurate in base 10 (not 2) by definition.
+ 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.subtract(e.getSemiMinorAxis()); // Presumed accurate in base 10 (not 2) by definition.
f.divide(value, error);
}
return f;
@@ -636,8 +636,8 @@ public class DefaultEllipsoid extends AbstractIdentifiedObject implements Ellips
public double semiMajorAxisDifference(final Ellipsoid other) {
double semiMajor = other.getSemiMajorAxis();
semiMajor = other.getAxisUnit().getConverterTo(getAxisUnit()).convert(semiMajor); // Often a no-op.
- final DoubleDouble a = new DoubleDouble(semiMajor); // Presumed accurate in base 10 if no unit conversion.
- a.subtract(getSemiMajorAxis()); // Presumed accurate in base 10 (not 2) by definition.
+ 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.
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 92e20e0..07a7bde 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
@@ -23,7 +23,6 @@ import org.opengis.referencing.datum.PrimeMeridian;
import org.apache.sis.internal.util.DoubleDouble;
import static org.apache.sis.util.ArgumentChecks.*;
-import static org.apache.sis.internal.util.DoubleDouble.verbatim;
import static org.apache.sis.internal.referencing.Formulas.JULIAN_YEAR_LENGTH;
@@ -160,8 +159,8 @@ public class TimeDependentBWP extends BursaWolfParameters {
final DoubleDouble period(final Date time) {
if (time != null) {
final long millis = time.getTime() - timeReference;
- if (millis != 0) { // Returns null for 0 as an optimization.
- final DoubleDouble period = verbatim(millis);
+ if (millis != 0) { // Returns null for 0 as an optimization.
+ final DoubleDouble period = new DoubleDouble(millis);
period.divide(1000 * JULIAN_YEAR_LENGTH, 0);
return period;
}
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 a66c03d..8cb69bc 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
@@ -280,7 +280,7 @@ public final class Matrices extends Static {
* See the comment in transform(Envelope, Envelope) for an explanation about why
* we use the lower/upper corners instead than getMinimum()/getMaximum() methods.
*/
- final DoubleDouble scale = new DoubleDouble(same ? +1 : -1, 0);
+ final DoubleDouble scale = new DoubleDouble(same ? +1d : -1d);
scale.multiply(dstEnvelope.getSpan(dstIndex));
scale.divide (srcEnvelope.getSpan(srcIndex));
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 40962a4..c59b0c2 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
@@ -141,7 +141,7 @@ public class AlbersEqualArea extends EqualAreaProjection {
* we do not really have that accuracy because of the limited precision of 'nm'. The intent is rather to
* increase the chances term cancellations happen during concatenation of coordinate operations.
*/
- final DoubleDouble rn = DoubleDouble.verbatim(1);
+ final DoubleDouble rn = new DoubleDouble(1d);
rn.subtract(initializer.eccentricitySquared);
rn.divide(nm, 0);
/*
@@ -149,7 +149,7 @@ public class AlbersEqualArea extends EqualAreaProjection {
* by the denormalization matrix. Omitted (1-ℯ²) term in nm cancels with omitted (1-ℯ²) term in qm(…).
* See above note about double-double arithmetic usage.
*/
- final DoubleDouble ρ0 = DoubleDouble.verbatim(C - nm*qm(sinφ0));
+ final DoubleDouble ρ0 = new DoubleDouble(C - nm*qm(sinφ0));
ρ0.sqrt();
ρ0.multiply(rn);
/*
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 24880b7..506eb82 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
@@ -34,7 +34,6 @@ import org.apache.sis.referencing.operation.transform.ContextualParameters;
import org.apache.sis.util.Workaround;
import static java.lang.Math.*;
-import static org.apache.sis.internal.util.DoubleDouble.verbatim;
import static org.apache.sis.internal.referencing.provider.LambertCylindricalEqualArea.*;
@@ -150,7 +149,7 @@ public class CylindricalEqualArea extends EqualAreaProjection {
* but we nevertheless support it.
*/
final double φ1 = toRadians(initializer.getAndStore(STANDARD_PARALLEL));
- final DoubleDouble k0 = verbatim(initializer.scaleAtφ(sin(φ1), cos(φ1)));
+ final DoubleDouble k0 = new DoubleDouble(initializer.scaleAtφ(sin(φ1), cos(φ1)));
k0.multiply(initializer.getAndStore(Mercator1SP.SCALE_FACTOR));
/*
* In most Apache SIS map projection implementations, the scale factor is handled by the super-class by
@@ -163,7 +162,7 @@ public class CylindricalEqualArea extends EqualAreaProjection {
* Furthermore we also multiply y by (1-ℯ²)/2 for avoiding the need to recompute this constant during
* the projection of every point.
*/
- final DoubleDouble ik = new DoubleDouble(1, 0);
+ 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.divide(k0);
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 f2808de..b4adf94 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
@@ -31,7 +31,6 @@ import org.apache.sis.referencing.operation.projection.NormalizedProjection.Para
import static java.lang.Math.*;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
-import static org.apache.sis.internal.util.DoubleDouble.verbatim;
/**
@@ -145,7 +144,7 @@ final class Initializer {
- getAndStore(roles.get(ParameterRole.FALSE_SOUTHING));
eccentricitySquared = new DoubleDouble();
- DoubleDouble k = new DoubleDouble(a); // The value by which to multiply all results of normalized projection.
+ DoubleDouble k = DoubleDouble.createAndGuessError(a); // The value by which to multiply all results of normalized projection.
if (a != b) {
if (variant == AUTHALIC_RADIUS) {
k.value = Formulas.getAuthalicRadius(a, b);
@@ -177,14 +176,14 @@ final class Initializer {
* constructor applies corrections for making those values more accurate in base 10 rather than 2.
*/
if (isIvfDefinitive) {
- final DoubleDouble f = new DoubleDouble(parameters.parameter(Constants.INVERSE_FLATTENING).doubleValue());
+ final DoubleDouble f = DoubleDouble.createAndGuessError(parameters.parameter(Constants.INVERSE_FLATTENING).doubleValue());
f.inverseDivide(1,0);
eccentricitySquared.setFrom(f);
eccentricitySquared.multiply(2,0);
f.square();
eccentricitySquared.subtract(f);
} else {
- final DoubleDouble rs = new DoubleDouble(b);
+ final DoubleDouble rs = DoubleDouble.createAndGuessError(b);
rs.divide(k); // rs = b/a
rs.square();
eccentricitySquared.value = 1;
@@ -228,8 +227,8 @@ final class Initializer {
*/
context.normalizeGeographicInputs(λ0);
final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
- denormalize.convertAfter(0, k, new DoubleDouble(fe));
- denormalize.convertAfter(1, k, new DoubleDouble(fn));
+ denormalize.convertAfter(0, k, DoubleDouble.createAndGuessError(fe));
+ denormalize.convertAfter(1, k, DoubleDouble.createAndGuessError(fn));
}
/**
@@ -283,7 +282,7 @@ final class Initializer {
* We retrieve this value from the eccentricity with {@code b/a = sqrt(1-ℯ²)}.
*/
final DoubleDouble axisLengthRatio() {
- final DoubleDouble b = new DoubleDouble(1,0);
+ final DoubleDouble b = new DoubleDouble(1d);
b.subtract(eccentricitySquared);
b.sqrt();
return b;
@@ -316,9 +315,9 @@ final class Initializer {
*/
final DoubleDouble rν2(final double sinφ) {
if (DoubleDouble.DISABLED) {
- return verbatim(1 - eccentricitySquared.doubleValue() * (sinφ*sinφ));
+ return new DoubleDouble(1 - eccentricitySquared.doubleValue() * (sinφ*sinφ));
}
- final DoubleDouble t = verbatim(sinφ);
+ final DoubleDouble t = new DoubleDouble(sinφ);
t.square();
t.multiply(eccentricitySquared);
/*
@@ -345,7 +344,7 @@ final class Initializer {
* @return radius of the conformal sphere at latitude φ.
*/
final double radiusOfConformalSphere(final double sinφ) {
- final DoubleDouble Rc = verbatim(1);
+ final DoubleDouble Rc = new DoubleDouble(1d);
Rc.subtract(eccentricitySquared); // 1 - ℯ²
Rc.sqrt(); // √(1 - ℯ²)
Rc.divide(rν2(sinφ)); // √(1 - ℯ²) / (1 - ℯ²sin²φ)
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 6061b08..666a7a8 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
@@ -41,7 +41,6 @@ import org.apache.sis.util.Workaround;
import static java.lang.Math.*;
import static java.lang.Double.*;
import static org.apache.sis.math.MathFunctions.isPositive;
-import static org.apache.sis.internal.util.DoubleDouble.verbatim;
/**
@@ -289,7 +288,7 @@ public class LambertConicConformal extends ConformalProjection {
* Opportunistically use double-double arithmetic since the matrix coefficients will
* be stored in that format anyway. This makes a change in the 2 or 3 last digits.
*/
- final DoubleDouble F = verbatim(n);
+ final DoubleDouble F = new DoubleDouble(n);
F.multiply(pow(t1, n), 0);
F.inverseDivide(m1);
if (!isNorth) {
@@ -325,11 +324,11 @@ public class LambertConicConformal extends ConformalProjection {
* - Multiply by the scale factor (done by the super-class constructor).
* - Add false easting and false northing (done by the super-class constructor).
*/
- DoubleDouble sλ = verbatim(n);
+ DoubleDouble sλ = new DoubleDouble(n);
DoubleDouble sφ = null;
if (isNorth) {
// Reverse the sign of either longitude or latitude values before map projection.
- sφ = verbatim(-1);
+ sφ = new DoubleDouble(-1d);
} else {
sλ.negate();
}
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 fa52fea..e799998 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
@@ -40,7 +40,6 @@ import org.apache.sis.util.Workaround;
import static java.lang.Math.*;
import static java.lang.Double.*;
import static org.apache.sis.math.MathFunctions.isPositive;
-import static org.apache.sis.internal.util.DoubleDouble.verbatim;
/**
@@ -233,7 +232,7 @@ public class Mercator extends ConformalProjection {
* if they really want, since we sometime see such CRS definitions.
*/
final double φ1 = toRadians(initializer.getAndStore(Mercator2SP.STANDARD_PARALLEL));
- final Number k0 = verbatim(initializer.scaleAtφ(sin(φ1), cos(φ1)));
+ final Number k0 = new DoubleDouble(initializer.scaleAtφ(sin(φ1), cos(φ1)));
/*
* In principle we should rotate the central meridian (λ0) in the normalization transform, as below:
*
@@ -260,7 +259,7 @@ public class Mercator extends ConformalProjection {
denormalize.convertBefore(0, null, offset);
}
if (φ0 != 0) {
- denormalize.convertBefore(1, null, verbatim(-log(expOfNorthing(φ0, eccentricity * sin(φ0)))));
+ denormalize.convertBefore(1, null, new DoubleDouble(-log(expOfNorthing(φ0, eccentricity * sin(φ0)))));
}
if (variant == MILLER) {
normalize .convertBefore(1, 0.80, null);
@@ -290,7 +289,7 @@ public class Mercator extends ConformalProjection {
* those remaning lines of code.
*/
if (φ0 == 0 && isPositive(φ1 != 0 ? φ1 : φ0)) {
- final Number reverseSign = verbatim(-1);
+ final Number reverseSign = new DoubleDouble(-1d);
normalize .convertBefore(1, reverseSign, null);
denormalize.convertBefore(1, reverseSign, null); // Must be before false easting/northing.
}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java
index f746120..f722e40 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/PolarStereographic.java
@@ -31,13 +31,13 @@ import org.apache.sis.internal.referencing.provider.PolarStereographicB;
import org.apache.sis.internal.referencing.provider.PolarStereographicC;
import org.apache.sis.internal.referencing.Formulas;
import org.apache.sis.internal.referencing.Resources;
+import org.apache.sis.internal.util.DoubleDouble;
import org.apache.sis.parameter.Parameters;
import org.apache.sis.util.Workaround;
import org.apache.sis.measure.Latitude;
import org.apache.sis.math.MathFunctions;
import static java.lang.Math.*;
-import static org.apache.sis.internal.util.DoubleDouble.verbatim;
/**
@@ -207,7 +207,7 @@ public class PolarStereographic extends ConformalProjection {
*
* In the spherical case, should give ρ == 2.
*/
- ρ = verbatim(2 / sqrt(pow(1+eccentricity, 1+eccentricity) * pow(1-eccentricity, 1-eccentricity)));
+ ρ = new DoubleDouble(2 / sqrt(pow(1+eccentricity, 1+eccentricity) * pow(1-eccentricity, 1-eccentricity)));
ρF = null;
} else {
/*
@@ -229,8 +229,8 @@ public class PolarStereographic extends ConformalProjection {
*/
final double sinφ1 = sin(φ1);
final double mF = initializer.scaleAtφ(sinφ1, cos(φ1));
- ρ = verbatim(mF / expOfNorthing(φ1, eccentricity*sinφ1));
- ρF = (variant == C) ? verbatim(-mF) : null;
+ ρ = new DoubleDouble(mF / expOfNorthing(φ1, eccentricity*sinφ1));
+ ρF = (variant == C) ? new DoubleDouble(-mF) : null;
}
/*
* At this point, all parameters have been processed. Now process to their
@@ -240,7 +240,7 @@ public class PolarStereographic extends ConformalProjection {
denormalize.convertBefore(0, ρ, null);
denormalize.convertBefore(1, ρ, ρF);
if (isNorth) {
- final Number reverseSign = verbatim(-1);
+ final Number reverseSign = new DoubleDouble(-1d);
final MatrixSIS normalize = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
normalize .convertAfter (1, reverseSign, null);
denormalize.convertBefore(1, reverseSign, null);
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 11bcc38..e6b9d45 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
@@ -215,7 +215,7 @@ public class TransverseMercator extends ConformalProjection {
* in the 3 last digits. Note that we still have sometime a 1 ULP difference compared to the
* 'n' value at serialization time.
*/
- final DoubleDouble t = new DoubleDouble(1, 0);
+ final DoubleDouble t = new DoubleDouble(1d);
t.subtract(eccentricitySquared, 0);
t.sqrt();
t.ratio_1m_1p();
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
index 2d85d47..f7a62cd 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
@@ -448,7 +448,7 @@ public class ContextualParameters extends Parameters implements Serializable {
final DoubleDouble toRadians = DoubleDouble.createDegreesToRadians();
DoubleDouble offset = null;
if (λ0 != 0) {
- offset = new DoubleDouble(-λ0);
+ offset = DoubleDouble.createAndGuessError(-λ0);
offset.multiply(toRadians);
}
final MatrixSIS normalize = (MatrixSIS) this.normalize; // Must be the same instance, not a copy.
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 dcd626e..26a55c2 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
@@ -289,7 +289,7 @@ public class EllipsoidToCentricTransform extends AbstractMathTransform implement
* - A "denormalization" transform for scaling (X,Y,Z) to the semi-major axis length.
*/
context.normalizeGeographicInputs(0);
- final DoubleDouble a = new DoubleDouble(semiMajor);
+ final DoubleDouble a = DoubleDouble.createAndGuessError(semiMajor);
final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
for (int i=0; i<3; i++) {
denormalize.convertAfter(i, a, null);
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 abb6477..48e293b 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
@@ -47,7 +47,7 @@ import org.apache.sis.math.DecimalFunctions;
* }
*
* <div class="section">Impact of availability of FMA instructions</div>
- * If <cite>fused multiply-add</cite> (FMA) instruction are available in a future Java version
+ * When allowed to use <cite>fused multiply-add</cite> (FMA) instruction added in JDK9
* (see <a href="https://issues.apache.org/jira/browse/SIS-136">SIS-136</a> on Apache SIS JIRA),
* then the following methods should be revisited:
*
@@ -56,7 +56,7 @@ import org.apache.sis.math.DecimalFunctions;
* </ul>
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
*
* @see <a href="http://en.wikipedia.org/wiki/Double-double_%28arithmetic%29#Double-double_arithmetic">Wikipedia: Double-double arithmetic</a>
*
@@ -244,17 +244,27 @@ public final class DoubleDouble extends Number {
}
/**
- * Creates a new value initialized to the given value and an error term inferred by
- * {@link #errorForWellKnownValue(double)}.
+ * Creates a new instance initialized to the given long integer.
*
- * <b>Tip:</b> if the other value is known to be an integer or a power of 2, then invoking
- * <code>{@linkplain #DoubleDouble(double, double) DoubleDouble}(otherValue, 0)</code> is more efficient.
+ * @param value the long integer value to wrap.
+ */
+ public DoubleDouble(final long value) {
+ this.value = value;
+ this.error = (value - (long) this.value);
+ }
+
+ /**
+ * Creates a new instance initialized to the given value verbatim, without inferring an error term for double-double arithmetic.
+ * We use this constructor when the value has been computed using transcendental functions (cosine, logarithm, <i>etc.</i>)
+ * in which case there is no way we can infer a meaningful error term. It should also be used when the value is known to have
+ * an exact representation as a {@code double} primitive type.
*
- * @param value the initial value.
+ * @param value the value to wrap in a {@code DoubleDouble} instance.
+ *
+ * @see #createAndGuessError(double)
*/
public DoubleDouble(final double value) {
this.value = value;
- this.error = errorForWellKnownValue(value);
}
/**
@@ -285,17 +295,17 @@ public final class DoubleDouble extends Number {
}
/**
- * Uses the given value verbatim, without inferring an error term for double-double arithmetic.
- * We use this method when the value has been computed using transcendental functions (cosine,
- * logarithm, <i>etc.</i>) in which case there is no way we can infer a meaningful error term.
+ * Creates a new value initialized to the given value and an error term inferred by
+ * {@link #errorForWellKnownValue(double)}.
*
- * <p>We use this method both for readability and for making easier to search where such thing occur.</p>
+ * <b>Tip:</b> if the other value is known to be an integer or a power of 2, then invoking
+ * <code>{@linkplain #DoubleDouble(double) DoubleDouble}(value)</code> is more efficient.
*
- * @param value the value to wrap in a {@code DoubleDouble} instance.
- * @return a {@code DoubleDouble} containing exactly the given value, without error term.
+ * @param value the initial value.
+ * @return an instance initialized to the given value and a default error term.
*/
- public static DoubleDouble verbatim(final double value) {
- return new DoubleDouble(value, 0);
+ public static DoubleDouble createAndGuessError(final double value) {
+ return new DoubleDouble(value, errorForWellKnownValue(value));
}
/**
@@ -331,7 +341,7 @@ public final class DoubleDouble extends Number {
/** @return {@link #value} + {@link #error}. */
@Override public double doubleValue() {return value + error;}
@Override public float floatValue() {return (float) doubleValue();}
- @Override public long longValue() {return Math.round(doubleValue());}
+ @Override public long longValue() {return Math.round(value) + (long) error;}
@Override public int intValue() {return Math.toIntExact(longValue());}
/**
@@ -425,7 +435,7 @@ public final class DoubleDouble extends Number {
* @param a the first number to add.
* @param b the second number to add, which must be smaller than {@code a}.
*/
- public void setToQuickSum(final double a, final double b) {
+ final void setToQuickSum(final double a, final double b) {
value = a + b;
error = b - (value - a);
if (DISABLED) error = 0;
@@ -997,7 +1007,7 @@ public final class DoubleDouble extends Number {
* This pattern occurs in map projections.
*/
public void ratio_1m_1p() {
- final DoubleDouble numerator = new DoubleDouble(1, 0);
+ final DoubleDouble numerator = new DoubleDouble(1d);
numerator.subtract(this);
add(1, 0);
inverseDivide(numerator);
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 8d10ced..54a2365 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
@@ -37,7 +37,7 @@ import static java.lang.StrictMath.*;
* Those tests need {@link DoubleDouble#DISABLED} to be set to {@code false}.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.4
+ * @version 1.0
* @since 0.4
* @module
*/
@@ -255,7 +255,7 @@ public final strictfp class DoubleDoubleTest extends TestCase {
@Test
@DependsOnMethod("testDivide")
public void testRatio_1m_1p() {
- final DoubleDouble t = new DoubleDouble(0.25, 0);
+ final DoubleDouble t = new DoubleDouble(0.25);
t.ratio_1m_1p();
assertEquals((1 - 0.25) / (1 + 0.25), t.doubleValue(), STRICT);
}
@@ -273,7 +273,7 @@ public final strictfp class DoubleDoubleTest extends TestCase {
@DependsOnMethod({"testMultiply", "testDivide"})
public void testSqrt() {
final BigDecimal SQRT2 = new BigDecimal("1.414213562373095048801688724209698");
- final DoubleDouble dd = new DoubleDouble(2, 0);
+ final DoubleDouble dd = new DoubleDouble(2d);
dd.sqrt();
assertNormalizedAndEquals(sqrt(2), dd);
assertEquals(0, SQRT2.subtract(toBigDecimal(dd)).doubleValue(), 1E-32);
@@ -305,8 +305,8 @@ public final strictfp class DoubleDoubleTest extends TestCase {
@Test
@DependsOnMethod({"testMultiply", "testAdd"})
public void testSeries() {
- final DoubleDouble t = new DoubleDouble(2);
- t.series(1, 1./3, 1./9, 1./7, 1./13); // Random coefficient.
+ final DoubleDouble t = new DoubleDouble(2d);
+ t.series(1, 1./3, 1./9, 1./7, 1./13); // Random coefficients.
assertEquals(1 + 2./3 + 4./9 + 8./7 + 16./13, t.doubleValue(), STRICT);
}
@@ -437,4 +437,20 @@ public final strictfp class DoubleDoubleTest extends TestCase {
assertEquals(DoubleDouble.errorForWellKnownValue(dd.value), dd.error, STRICT);
}
}
+
+ /**
+ * Tests initialization with a long value.
+ */
+ @Test
+ public void testLong() {
+ long value = Long.MAX_VALUE - 10;
+ DoubleDouble t = new DoubleDouble(value);
+ assertEquals(-10, t.error, STRICT);
+ assertEquals(value, t.longValue());
+
+ value = Long.MIN_VALUE + 10;
+ t = new DoubleDouble(value);
+ assertEquals(10, t.error, STRICT);
+ assertEquals(value, t.longValue());
+ }
}