sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1607117 - in /sis/branches/JDK7: ./ core/sis-utility/src/main/java/org/apache/sis/internal/converter/NumberConverter.java core/sis-utility/src/test/java/org/apache/sis/internal/converter/NumberConverterTest.java
Date Tue, 01 Jul 2014 15:39:38 GMT
Author: desruisseaux
Date: Tue Jul  1 15:39:38 2014
New Revision: 1607117

URL: http://svn.apache.org/r1607117
Log:
Merge from the JDK8 branch.

Modified:
    sis/branches/JDK7/   (props changed)
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/NumberConverter.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/converter/NumberConverterTest.java

Propchange: sis/branches/JDK7/
------------------------------------------------------------------------------
  Merged /sis/branches/JDK8:r1606757-1607116

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/NumberConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/NumberConverter.java?rev=1607117&r1=1607116&r2=1607117&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/NumberConverter.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/converter/NumberConverter.java
[UTF-8] Tue Jul  1 15:39:38 2014
@@ -109,12 +109,27 @@ final class NumberConverter<S extends Nu
      */
     @Override
     public T apply(final S source) {
-        final T target = Numbers.cast(source, targetClass);
-        if (target.longValue() != source.longValue() ||
-                Double.doubleToLongBits(target.doubleValue()) !=
-                Double.doubleToLongBits(source.doubleValue()))
-        {
-            throw new UnconvertibleObjectException(formatErrorMessage(source));
+        final double sourceValue = source.doubleValue();
+        T target = Numbers.cast(source, targetClass);
+        final double targetValue = target.doubleValue();
+        if (Double.doubleToLongBits(targetValue) != Double.doubleToLongBits(sourceValue))
{
+            /*
+             * Casted value is not equal to the source value. Maybe we just lost the fraction
digits
+             * in a (double → long) cast, in which case the difference should be smaller
than 1.
+             */
+            final double delta = Math.abs(targetValue - sourceValue);
+            if (!(delta < 0.5)) { // Use '!' for catching NaN.
+                if (delta < 1) {
+                    target = Numbers.cast(Math.round(sourceValue), targetClass);
+                } else {
+                    /*
+                     * The delta may be greater than 1 in a (BigInteger/BigDecimal → long)
cast if the
+                     * BigInteger/BigDecimal has more significant digits than what the double
type can
+                     * hold.
+                     */
+                    throw new UnconvertibleObjectException(formatErrorMessage(source));
+                }
+            }
         }
         return target;
     }

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/converter/NumberConverterTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/converter/NumberConverterTest.java?rev=1607117&r1=1607116&r2=1607117&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/converter/NumberConverterTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/converter/NumberConverterTest.java
[UTF-8] Tue Jul  1 15:39:38 2014
@@ -33,7 +33,7 @@ import static org.apache.sis.test.Assert
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3 (derived from geotk-2.4)
- * @version 0.3
+ * @version 0.5
  * @module
  */
 @DependsOn(SystemRegistryTest.class)
@@ -54,6 +54,19 @@ public final strictfp class NumberConver
     }
 
     /**
+     * Asserts that conversion of the given {@code source} value produces the given {@code
target} value.
+     * The conversion is not expected to be invertible. This method is used for testing rounding
behavior.
+     */
+    private static <S extends Number, T extends Number> void runConversion(
+            final ObjectConverter<S,T> c, final S source, final T target, final S inverse)
+            throws UnconvertibleObjectException
+    {
+        assertFalse(source.equals(inverse));
+        assertEquals("Forward conversion.", target,  c.apply(source));
+        assertEquals("Inverse conversion.", inverse, c.inverse().apply(target));
+    }
+
+    /**
      * Asserts that conversion of the given {@code source} value produces
      * the given {@code target} value, and tests the inverse conversion.
      */
@@ -115,7 +128,9 @@ public final strictfp class NumberConver
     @Test
     public void testInteger() {
         final ObjectConverter<Float, Integer> c = create(Float.class, Integer.class);
-        runInvertibleConversion(c, Float.valueOf(-8), Integer.valueOf(-8));
+        runInvertibleConversion(c, Float.valueOf(-8),    Integer.valueOf(-8));
+        runConversion          (c, Float.valueOf(2.25f), Integer.valueOf(2), Float.valueOf(2f));
+        runConversion          (c, Float.valueOf(2.75f), Integer.valueOf(3), Float.valueOf(3f));
         // Can not easily tests the values around Integer.MIN/MAX_VALUE because of rounding
errors in float.
         assertSame("Deserialization shall resolves to the singleton instance.", c, assertSerializedEquals(c));
     }
@@ -137,6 +152,7 @@ public final strictfp class NumberConver
     public void testFloat() {
         final ObjectConverter<Double, Float> c = create(Double.class, Float.class);
         runInvertibleConversion(c, Double.valueOf(2.5), Float.valueOf(2.5f));
+        runConversion          (c, Double.valueOf(0.1), Float.valueOf(0.1f), Double.valueOf(0.1f));
         tryUnconvertibleValue  (c, Double.valueOf(1E+40));
         assertSame("Deserialization shall resolves to the singleton instance.", c, assertSerializedEquals(c));
     }
@@ -172,6 +188,23 @@ public final strictfp class NumberConver
     }
 
     /**
+     * Tests conversion of a value having more digits than what the {@code double} type can
hold.
+     */
+    @Test
+    public void testLargeValue() {
+        final long longValue = 1000000000000000010L;
+        final double doubleValue = longValue;
+        assertTrue(Math.ulp(doubleValue) > 10); // Need to have more digits than 'double'
capacity.
+        runConversion(create(BigDecimal.class, Double.class),
+                BigDecimal.valueOf(longValue), Double.valueOf(doubleValue), BigDecimal.valueOf(doubleValue));
+
+        final ObjectConverter<BigDecimal, Long> c = create(BigDecimal.class, Long.class);
+        final BigDecimal value = BigDecimal.valueOf(longValue);
+        runInvertibleConversion(c, value, Long.valueOf(longValue));
+        tryUnconvertibleValue(c, value.multiply(BigDecimal.valueOf(10)));
+    }
+
+    /**
      * Tests conversions to comparable objects. Should returns the object unchanged
      * since all {@link Number} subclasses are comparable.
      */



Mime
View raw message