Author: desruisseaux
Date: Tue Oct 1 15:40:01 2013
New Revision: 1528121
URL: http://svn.apache.org/r1528121
Log:
Adds a few constants for double-double arithmetic, especially for values
related to PI and conversions between degrees and radians.
Modified:
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DoubleDouble.java
sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
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=1528121&r1=1528120&r2=1528121&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] Tue Oct 1 15:40:01 2013
@@ -101,14 +101,33 @@ public final class DoubleDouble extends
* For any value at index <var>i</var>, the associated error is {@code
ERRORS[i]}.
*/
private static final double[] VALUES = {
- 0.000001,
- 0.00001,
- 0.0001,
- 0.001,
- 0.01,
- 0.1,
- 0.3048, // Feet to metres
- 0.9 // Degrees to gradians
+ // Some of the following constants have more fraction digits than
necessary. We declare the extra
+ // digits for documentation purpose, and in order to have identical
content than DoubleDoubleTest
+ // so that a plain copy-and-paste can be performed between those two
classes.
+ 0.000001,
+ 0.00001,
+ 0.0001,
+ 0.00027777777777777777777777777777777778, // Second to degrees
+ 0.001,
+ 0.002777777777777777777777777777777778, // 1/360°
+ 0.01,
+ 0.01666666666666666666666666666666667, // Minute to degrees
+ 0.017453292519943295769236907684886127134428333, // Degrees to radians
+ 0.1,
+ 0.201168, // Link to metres
+ 0.3048, // Feet to metres
+ 0.785398163397448309615660845819876, // π/4
+ 0.9, // Degrees to gradians
+ 0.9144, // Yard to metres
+ 1.111111111111111111111111111111111, // Gradian to degrees
+ 1.570796326794896619231321691639751, // π/2
+ 1.8288, // Fathom to metres
+ 2.356194490192344928846982537459627, // π * 3/4
+ 2.54, // Inch to centimetres
+ 3.14159265358979323846264338327950, // π
+ 6.28318530717958647692528676655901, // 2π
+ 20.1168, // Chain to metres
+ 57.2957795130823208767981548141052 // Radians to degrees
};
/**
@@ -124,14 +143,30 @@ public final class DoubleDouble extends
* </ul>
*/
private static final double[] ERRORS = {
- /* 0.000001 */ 4.525188817411374E-23,
- /* 0.00001 */ -8.180305391403131E-22,
- /* 0.0001 */ -4.79217360238593E-21,
- /* 0.001 */ -2.0816681711721686E-20,
- /* 0.01 */ -2.0816681711721684E-19,
- /* 0.1 */ -5.551115123125783E-18,
- /* 0.3048 */ -1.5365486660812166E-17,
- /* 0.9 */ -2.2204460492503132E-17
+ /* 0.000001 */ 4.525188817411374E-23,
+ /* 0.00001 */ -8.180305391403131E-22,
+ /* 0.0001 */ -4.79217360238593E-21,
+ /* 0.000266… */ 2.4093381610788987E-22,
+ /* 0.001 */ -2.0816681711721686E-20,
+ /* 0.002666… */ -1.0601087908747154E-19,
+ /* 0.01 */ -2.0816681711721684E-19,
+ /* 0.016666… */ 2.312964634635743E-19,
+ /* 0.017453… */ 2.9486522708701687E-19,
+ /* 0.1 */ -5.551115123125783E-18,
+ /* 0.201168 */ -1.3471890270011499E-17,
+ /* 0.3048 */ -1.5365486660812166E-17,
+ /* 0.785398… */ 3.061616997868383E-17,
+ /* 0.9 */ -2.2204460492503132E-17,
+ /* 0.9144 */ 9.414691248821328E-18,
+ /* 1.111111… */ -4.9343245538895844E-17,
+ /* 1.570796… */ 6.123233995736766E-17,
+ /* 1.8288 */ 1.8829382497642655E-17,
+ /* 2.356194… */ 9.184850993605148E-17,
+ /* 2.54 */ -3.552713678800501E-17,
+ /* 3.141592… */ 1.2246467991473532E-16,
+ /* 6.283185… */ 2.4492935982947064E-16,
+ /* 20.1168 */ -1.3471890270011499E-15,
+ /* 57.295779… */ -1.9878495670576283E-15
};
/**
Modified:
sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java?rev=1528121&r1=1528120&r2=1528121&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
[UTF-8] (original)
+++
sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DoubleDoubleTest.java
[UTF-8] Tue Oct 1 15:40:01 2013
@@ -42,9 +42,9 @@ import static java.lang.StrictMath.*;
@DependsOn(org.apache.sis.math.MathFunctionsTest.class)
public final strictfp class DoubleDoubleTest extends TestCase {
/**
- * Number of iterations in each test method.
+ * Number of time to repeat arithmetic tests.
*/
- private static final int NUM_ITERATIONS = 1000;
+ private static final int NUMBER_OF_REPETITIONS = 1000;
/**
* The tolerance factor (as a multiplicand) for the addition and
subtraction operations.
@@ -59,6 +59,11 @@ public final strictfp class DoubleDouble
private static final double PRODUCT_TOLERANCE_FACTOR = 10000;
/**
+ * Tolerance threshold for strict comparisons of floating point values.
+ */
+ private static final double STRICT = 0;
+
+ /**
* The random number generator to use for the test.
*/
private final Random random = TestUtilities.createRandomNumberGenerator();
@@ -96,7 +101,7 @@ public final strictfp class DoubleDouble
*/
private static void assertNormalizedAndEquals(final double expected, final
DoubleDouble actual) {
assertTrue("DoubleDouble is not normalized.", abs(actual.error) <=
ulp(actual.value));
- assertEquals("Unexpected arithmetic result.", expected, actual.value,
0.0);
+ assertEquals("Unexpected arithmetic result.", expected, actual.value,
STRICT);
}
/**
@@ -128,7 +133,7 @@ public final strictfp class DoubleDouble
@DependsOnMethod("testSetToQuickSum")
public void testNormalize() {
final DoubleDouble dd = new DoubleDouble();
- for (int i=0; i<NUM_ITERATIONS; i++) {
+ for (int i=0; i<NUMBER_OF_REPETITIONS; i++) {
double a = nextRandom();
double b = nextRandom();
if (abs(a) < abs(b)) {
@@ -150,7 +155,7 @@ public final strictfp class DoubleDouble
@Test
public void testSetToQuickSum() {
final DoubleDouble dd = new DoubleDouble();
- for (int i=0; i<NUM_ITERATIONS; i++) {
+ for (int i=0; i<NUMBER_OF_REPETITIONS; i++) {
double a = nextRandom();
double b = nextRandom();
if (abs(a) < abs(b)) {
@@ -170,7 +175,7 @@ public final strictfp class DoubleDouble
@Test
public void testSetToSum() {
final DoubleDouble dd = new DoubleDouble();
- for (int i=0; i<NUM_ITERATIONS; i++) {
+ for (int i=0; i<NUMBER_OF_REPETITIONS; i++) {
final double a = nextRandom();
final double b = nextRandom();
dd.setToSum(a, b);
@@ -185,7 +190,7 @@ public final strictfp class DoubleDouble
@Test
public void testSetToProduct() {
final DoubleDouble dd = new DoubleDouble();
- for (int i=0; i<NUM_ITERATIONS; i++) {
+ for (int i=0; i<NUMBER_OF_REPETITIONS; i++) {
final double a = nextRandom();
final double b = nextRandom();
dd.setToProduct(a, b);
@@ -202,7 +207,7 @@ public final strictfp class DoubleDouble
public void testAdd() {
final DoubleDouble dd = new DoubleDouble();
final DoubleDouble op = new DoubleDouble();
- for (int i=0; i<NUM_ITERATIONS; i++) {
+ for (int i=0; i<NUMBER_OF_REPETITIONS; i++) {
nextRandom(dd);
nextRandom(op);
final BigDecimal expected = toBigDecimal(dd).add(toBigDecimal(op));
@@ -219,7 +224,7 @@ public final strictfp class DoubleDouble
public void testMultiply() {
final DoubleDouble dd = new DoubleDouble();
final DoubleDouble op = new DoubleDouble();
- for (int i=0; i<NUM_ITERATIONS; i++) {
+ for (int i=0; i<NUMBER_OF_REPETITIONS; i++) {
nextRandom(dd);
nextRandom(op);
final BigDecimal expected =
toBigDecimal(dd).multiply(toBigDecimal(op), MathContext.DECIMAL128);
@@ -236,7 +241,7 @@ public final strictfp class DoubleDouble
public void testDivide() {
final DoubleDouble dd = new DoubleDouble();
final DoubleDouble op = new DoubleDouble();
- for (int i=0; i<NUM_ITERATIONS; i++) {
+ for (int i=0; i<NUMBER_OF_REPETITIONS; i++) {
nextRandom(dd);
nextRandom(op);
final BigDecimal expected =
toBigDecimal(dd).divide(toBigDecimal(op), MathContext.DECIMAL128);
@@ -249,14 +254,30 @@ public final strictfp class DoubleDouble
* List of all {@link DoubleDouble#VALUES} as string decimal
representation.
*/
private static final String[] PREDEFINED_VALUES = {
- "0.000001",
- "0.00001",
- "0.0001",
- "0.001",
- "0.01",
- "0.1",
- "0.3048",
- "0.9"
+ "0.000001",
+ "0.00001",
+ "0.0001",
+ "0.00027777777777777777777777777777777778",
+ "0.001",
+ "0.002777777777777777777777777777777778",
+ "0.01",
+ "0.01666666666666666666666666666666667",
+ "0.017453292519943295769236907684886127134428333",
+ "0.1",
+ "0.201168",
+ "0.3048",
+ "0.785398163397448309615660845819876",
+ "0.9",
+ "0.9144",
+ "1.111111111111111111111111111111111",
+ "1.570796326794896619231321691639751",
+ "1.8288",
+ "2.356194490192344928846982537459627",
+ "2.54",
+ "3.14159265358979323846264338327950",
+ "6.28318530717958647692528676655901",
+ "20.1168",
+ "57.2957795130823208767981548141052"
};
/**
@@ -290,9 +311,35 @@ public final strictfp class DoubleDouble
final BigDecimal accurate = new BigDecimal(text);
final BigDecimal approximation = new BigDecimal(value);
final double expected =
accurate.subtract(approximation).doubleValue();
- assertEquals(text, expected, DoubleDouble.errorForWellKnownValue(
value), 0);
- assertEquals(text, -expected,
DoubleDouble.errorForWellKnownValue(-value), 0);
+ assertEquals(text, expected, DoubleDouble.errorForWellKnownValue(
value), STRICT);
+ assertEquals(text, -expected,
DoubleDouble.errorForWellKnownValue(-value), STRICT);
assertFalse("There is no point to define an entry for values
having no error.", expected == 0);
}
}
+
+ /**
+ * Tests π values using the {@link Math#PI} constant.
+ * This test method serves two purposes:
+ *
+ * <ul>
+ * <li>Ensure that the results of small arithmetic operations on {@link
Math#PI} produce
+ * numbers that {@link DoubleDouble#errorForWellKnownValue(double)}
can find.</li>
+ * <li>Compare with the values computed by the {@code qd-2.3.14} package
(a C/C++ library),
+ * which is taken as the reference implementation.</li>
+ * </ul>
+ */
+ @Test
+ @DependsOnMethod("testErrorForWellKnownValue")
+ public void testPI() {
+ assertEquals(1.224646799147353207E-16,
DoubleDouble.errorForWellKnownValue(PI ), STRICT);
+ assertEquals(2.449293598294706414E-16,
DoubleDouble.errorForWellKnownValue(PI * 2), STRICT);
+ assertEquals(6.123233995736766036E-17,
DoubleDouble.errorForWellKnownValue(PI / 2), STRICT);
+ assertEquals(3.061616997868383018E-17,
DoubleDouble.errorForWellKnownValue(PI / 4), STRICT);
+ assertEquals(9.184850993605148436E-17,
DoubleDouble.errorForWellKnownValue(PI * (3./4)), STRICT);
+
+ assertTrue("toDegrees", DoubleDouble.errorForWellKnownValue(180 / PI)
!= 0);
+ assertTrue("toDegrees",
DoubleDouble.errorForWellKnownValue(toDegrees(1)) != 0);
+ assertTrue("toRadians", DoubleDouble.errorForWellKnownValue(PI / 180)
!= 0);
+ assertTrue("toRadians",
DoubleDouble.errorForWellKnownValue(toRadians(1)) != 0);
+ }
}