sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1737250 - in /sis/branches/JDK8/core/sis-utility/src: main/java/org/apache/sis/math/MathFunctions.java test/java/org/apache/sis/math/MathFunctionsTest.java
Date Thu, 31 Mar 2016 15:41:22 GMT
Author: desruisseaux
Date: Thu Mar 31 15:41:22 2016
New Revision: 1737250

URL: http://svn.apache.org/viewvc?rev=1737250&view=rev
Log:
Move the quadrupleToDouble method up for keeping it together with related functions.
Add javadoc. 

Modified:
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/MathFunctionsTest.java

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java?rev=1737250&r1=1737249&r2=1737250&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/math/MathFunctions.java
[UTF-8] Thu Mar 31 15:41:22 2016
@@ -56,8 +56,9 @@ import static org.apache.sis.internal.ut
  * {@link #nextPrimeNumber(int) nextPrimeNumber}.
  *
  * @author  Martin Desruisseaux (MPO, IRD, Geomatys)
+ * @author  Johann Sorel (Geomatys)
  * @since   0.3
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see DecimalFunctions
@@ -132,6 +133,7 @@ public final class MathFunctions extends
      *
      * @see #primeNumberAt(int)
      */
+    @SuppressWarnings("VolatileArrayField")     // Because we will not modify array content.
     private static volatile short[] primes = new short[] {2, 3};
 
     /**
@@ -543,8 +545,7 @@ public final class MathFunctions extends
 
     /**
      * Returns a {@linkplain Float#isNaN(float) NaN} number for the specified ordinal value.
-     * Valid NaN numbers in Java can have bit fields in the ranges listed below.
-     * This method allocates one of valid NaN bit fields to each ordinal value.
+     * Valid NaN numbers in Java can have bit fields in the ranges listed below:
      *
      * <ul>
      *   <li>[{@code 0x7F800001} … {@code 0x7FFFFFFF}], with
@@ -552,9 +553,12 @@ public final class MathFunctions extends
      *   <li>[{@code 0xFF800001} … {@code 0xFFFFFFFF}]</li>
      * </ul>
      *
-     * The relationship between bit fields and ordinal values is implementation dependent
and may
-     * change in any future version of the SIS library. The current implementation restricts
the
-     * range of allowed ordinal values to a smaller one than the range of all possible NaN
values.
+     * Some of those bits, named the <cite>payload</cite>, can be used for storing
custom information.
+     * This method maps some of the payload values to each ordinal value.
+     *
+     * <p>The relationship between payload values and ordinal values is implementation
dependent and
+     * may change in any future version of the SIS library. The current implementation restricts
the
+     * range of allowed ordinal values to a smaller one than the range of all possible values.</p>
      *
      * @param  ordinal The NaN ordinal value, from {@code -0x200000} to {@code 0x1FFFFF}
inclusive.
      * @return One of the legal {@linkplain Float#isNaN(float) NaN} values as a float.
@@ -596,6 +600,68 @@ public final class MathFunctions extends
     }
 
     /**
+     * Converts two long bits values containing a IEEE 754 quadruple precision floating point
number
+     * to a double precision floating point number. About 17 decimal digits of precision
may be lost
+     * due to the {@code double} type having only half the capacity of quadruple precision
type.
+     *
+     * <p>Some quadruple precision values can not be represented in double precision
and are mapped
+     * to {@code double} values as below:</p>
+     * <ul>
+     *   <li>Values having a magnitude less than {@link Double#MIN_VALUE} are mapped
to
+     *       positive or negative zero.</li>
+     *   <li>Values having a magnitude greater than {@link Double#MAX_VALUE} are mapped
to
+     *       {@link Double#POSITIVE_INFINITY} or {@link Double#NEGATIVE_INFINITY}.</li>
+     *   <li>All NaN values are currently collapsed to the single "canonical" {@link
Double#NaN} value
+     *       (this policy may be revisited in future SIS version).</li>
+     * </ul>
+     *
+     * @param l0 upper part of the quadruple precision floating point number.
+     * @param l1 lower part of the quadruple precision floating point number.
+     * @return double precision approximation.
+     *
+     * @see <a href="https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format">Quadruple-precision
floating-point format on Wikipedia</a>
+     *
+     * @since 0.7
+     */
+    public static double quadrupleToDouble(long l0, long l1) {
+        // Build double
+        long sig = (l0 & 0x8000000000000000L);
+        long exp = (l0 & 0x7FFF000000000000L) >> 48;
+        l0       = (l0 & 0x0000FFFFFFFFFFFFL);
+        if (exp == 0) {
+            /*
+             * Subnormal number.
+             * Since we convert them to double precision, subnormal numbers can not be represented
+             * as they are smaller than Double.MIN_VALUE. We map them to zero preserving
the sign.
+             */
+            return Double.longBitsToDouble(sig);
+        }
+        if (exp == 0x7FFF) {
+            /*
+             * NaN of infinite number.
+             * Mantissa with all bits at 0 is used for infinite.
+             * This is the only special number that we can preserve.
+             */
+            if (l0 == 0 && l1 == 0) {
+                return Double.longBitsToDouble(sig | 0x7FF0000000000000L);
+            }
+            /*
+             * Other NaN values might have a meaning (e.g. NaN(1) = forest, NaN(2) = lake,
etc.)
+             * See above toNanFloat(int) and toNaNOrdinal(float) methods. When truncating
the value we
+             * might change the meaning, which could cause several issues later. Therefor
we conservatively
+             * collapse all NaNs to the default NaN for now (this may be revisited in a future
SIS version).
+             */
+            return Double.NaN;
+        }
+        exp -= (16383 - 1023);      //change from 15 bias to 11 bias
+        // Check cases where mantissa excess what double can support
+        if (exp < 0)    return Double.NEGATIVE_INFINITY;
+        if (exp > 2046) return Double.POSITIVE_INFINITY;
+
+        return Double.longBitsToDouble(sig | (exp << 52) | (l0 << 4) | (l1 >>>
60));
+    }
+
+    /**
      * Returns the <var>i</var><sup>th</sup> prime number.
      * This method returns (2, 3, 5, 7, 11, …) for index (0, 1, 2, 3, 4, …).
      *
@@ -787,45 +853,4 @@ testNextNumber:         while (true) { /
         }
         return ArraysExt.resize(divisors, count);
     }
-
-    /**
-     * Convert two long bits values containing a quadruple precision floating point number
-     * to a java double precision floating point number.
-     *
-     * @param l0 upper part of the quadruple precision floating point number
-     * @param l1 lower part of the quadruple precision floating point number
-     * @return double precision approximation
-     */
-    public static double quadrupleToDouble(long l0, long l1){
-        //build double
-        long sig = (l0 & 0x8000000000000000L);
-        long exp = (l0 & 0x7FFF000000000000L) >> 48;
-        l0 = (l0 & 0x0000FFFFFFFFFFFFL);
-        if(exp==0){
-            //subnormal number
-            //note : since we convert them to double precision, subnormal number
-            //can not be represented, we map them to zero preserving the sign.
-            return Double.longBitsToDouble(sig);
-        }
-        if(exp==0x7FFF){
-            //NaN number
-            //note : mantissa with all bits at 0 is used for infinite, this is the only
-            //special NaN we can preserve.
-            if(l0==0 && l1==0){
-                return Double.longBitsToDouble(sig|0x7FF0000000000000L);
-            }
-            //Other NaN values might have a meaning, when truncating the value
-            //we might change this meaning, which could cause several issues later
-            //Therefor we map all other NaNs to the default NaN
-            return Double.NaN;
-        }
-        exp = exp - 16383 + 1023; //change from 15 bias to 11 bias
-        //check cases where mantissa excess what double can support
-        if(exp<0)    return Double.NEGATIVE_INFINITY;
-        if(exp>2046) return Double.POSITIVE_INFINITY;
-
-        return Double.longBitsToDouble(
-                sig | (exp << 52) | (l0 << 4) | (l1 >>> 60));
-    }
-
 }

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/MathFunctionsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/MathFunctionsTest.java?rev=1737250&r1=1737249&r2=1737250&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/MathFunctionsTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/math/MathFunctionsTest.java
[UTF-8] Thu Mar 31 15:41:22 2016
@@ -32,8 +32,9 @@ import static org.apache.sis.internal.ut
  * Tests the {@link MathFunctions} static methods.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @author  Johann Sorel (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  */
 @DependsOn({
@@ -256,6 +257,70 @@ public final strictfp class MathFunction
     }
 
     /**
+     * Tests the {@link MathFunctions#quadrupleToDouble(long, long)} method. Values used
in this test are taken from
+     * <a href="https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format">Quadruple-precision
+     * floating-point format</a> on Wikipedia.
+     */
+    @Test
+    public void testQuadrupleToDouble(){
+        long l0, l1;
+
+        // 1.0
+        l0 = 0x3FFF000000000000L;
+        l1 = 0x0000000000000000L;
+        assertEquals(doubleToLongBits(1.0),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+
+        // -2.0
+        l0 = 0xC000000000000000L;
+        l1 = 0x0000000000000000L;
+        assertEquals(doubleToLongBits(-2.0),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+
+        // 3.1415926535897932384626433832795028
+        l0 = 0x4000921FB54442D1L;
+        l1 = 0x8469898CC51701B8L;
+        assertEquals(doubleToLongBits(3.1415926535897932384626433832795028),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+
+        // ~1/3
+        l0 = 0x3FFD555555555555L;
+        l1 = 0x5555555555555555L;
+        assertEquals(doubleToLongBits(1.0/3.0),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+
+        // positive zero
+        l0 = 0x0000000000000000L;
+        l1 = 0x0000000000000000L;
+        assertEquals(doubleToLongBits(+0.0),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+
+        // negative zero
+        l0 = 0x8000000000000000L;
+        l1 = 0x0000000000000000L;
+        assertEquals(doubleToLongBits(-0.0),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+
+        // positive infinite
+        l0 = 0x7FFF000000000000L;
+        l1 = 0x0000000000000000L;
+        assertEquals(doubleToLongBits(Double.POSITIVE_INFINITY),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+
+        // negative infinite
+        l0 = 0xFFFF000000000000L;
+        l1 = 0x0000000000000000L;
+        assertEquals(doubleToLongBits(Double.NEGATIVE_INFINITY),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+
+        // a random NaN
+        l0 = 0x7FFF000100040000L;
+        l1 = 0x0001005000080000L;
+        assertEquals(doubleToLongBits(Double.NaN),
+                     doubleToLongBits(quadrupleToDouble(l0, l1)));
+    }
+
+    /**
      * Tests the {@link MathFunctions#primeNumberAt(int)} method.
      */
     @Test
@@ -340,68 +405,4 @@ public final strictfp class MathFunction
             1, 5
         }, commonDivisors(2000, 15));
     }
-
-    /**
-     * Tests the {@link MathFunctions#quadrupleToDouble(int[])} method.
-     */
-    @Test
-    public void testQuadrupleToDouble(){
-
-        long l0,l1;
-
-        // 1.0
-        l0 = 0x3FFF000000000000L;
-        l1 = 0x0000000000000000L;
-        assertEquals(doubleToLongBits(1.0),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-        // -2.0
-        l0 = 0xC000000000000000L;
-        l1 = 0x0000000000000000L;
-        assertEquals(doubleToLongBits(-2.0),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-        // 3.1415926535897932384626433832795028
-        l0 = 0x4000921FB54442D1L;
-        l1 = 0x8469898CC51701B8L;
-        assertEquals(doubleToLongBits(3.1415926535897932384626433832795028),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-        // ~1/3
-        l0 = 0x3FFD555555555555L;
-        l1 = 0x5555555555555555L;
-        assertEquals(doubleToLongBits(1.0/3.0),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-        //positive zero
-        l0 = 0x0000000000000000L;
-        l1 = 0x0000000000000000L;
-        assertEquals(doubleToLongBits(+0.0),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-        //negative zero
-        l0 = 0x8000000000000000L;
-        l1 = 0x0000000000000000L;
-        assertEquals(doubleToLongBits(-0.0),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-        //positive infinite
-        l0 = 0x7FFF000000000000L;
-        l1 = 0x0000000000000000L;
-        assertEquals(doubleToLongBits(Double.POSITIVE_INFINITY),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-        //negative infinite
-        l0 = 0xFFFF000000000000L;
-        l1 = 0x0000000000000000L;
-        assertEquals(doubleToLongBits(Double.NEGATIVE_INFINITY),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-        //a random NaN
-        l0 = 0x7FFF000100040000L;
-        l1 = 0x0001005000080000L;
-        assertEquals(doubleToLongBits(Double.NaN),
-                     doubleToLongBits(quadrupleToDouble(l0, l1)));
-
-    }
 }



Mime
View raw message