You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2015/05/05 15:30:35 UTC

[math] Looking at double to long cast vs. dedicated implementation.

Repository: commons-math
Updated Branches:
  refs/heads/h10-builds 14f24f2cd -> 202f9fb42


Looking at double to long cast vs. dedicated implementation.

Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/202f9fb4
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/202f9fb4
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/202f9fb4

Branch: refs/heads/h10-builds
Commit: 202f9fb42b31620928caec317a0cc2036366e85a
Parents: 14f24f2
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue May 5 15:30:09 2015 +0200
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue May 5 15:30:09 2015 +0200

----------------------------------------------------------------------
 .../apache/commons/math4/util/FastMathTest.java | 70 ++++++++++++++++++++
 1 file changed, 70 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/202f9fb4/src/test/java/org/apache/commons/math4/util/FastMathTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math4/util/FastMathTest.java b/src/test/java/org/apache/commons/math4/util/FastMathTest.java
index e981dda..65ca9db 100644
--- a/src/test/java/org/apache/commons/math4/util/FastMathTest.java
+++ b/src/test/java/org/apache/commons/math4/util/FastMathTest.java
@@ -16,10 +16,12 @@
  */
 package org.apache.commons.math4.util;
 
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.math.BigInteger;
+import java.util.Arrays;
 
 import org.apache.commons.math4.TestUtils;
 import org.apache.commons.math4.dfp.Dfp;
@@ -49,6 +51,74 @@ public class FastMathTest {
         generator = new MersenneTwister(6176597458463500194l);
     }
 
+    private static long toLong(final double x) {
+        final long bits         = Double.doubleToRawLongBits(x);
+        final int rawExp        = (int) ((bits & 0x7ff0000000000000L) >> 52);
+        if (rawExp < 1023) {
+            // numbers between -1.0 and +1 excluded (some normal numbers, all sub-normal numbers and signed 0)
+            return 0;
+        } else {
+            final long sign         = bits & 0x8000000000000000L;
+            final long rawMantissa  = bits & 0x000fffffffffffffL;
+            if (rawExp == 2047) {
+
+                // special values
+                if (rawMantissa == 0) {
+                    // infinity
+                    return (sign == 0) ? Long.MAX_VALUE : Long.MIN_VALUE;
+                } else {
+                    // NaN
+                    return 0;
+                }
+
+            } else {
+
+                // normal number
+                final long fullMantissa = rawMantissa | 0x10000000000000L;
+
+                if (rawExp < 1075) {
+                    // normal numbers with negative shift (i.e. with a fractional part to be removed)
+                    final long l = fullMantissa >> (1075 - rawExp);
+                    return (sign == 0) ? l : -l;
+                } else if (rawExp < 1086) {
+                    // normal number with positive shift small enough to fit in a long
+                    final long l = fullMantissa << (rawExp - 1075);
+                    return (sign == 0) ? l : -l;
+                } else {
+                    // normal number exceeding long range
+                    return (sign == 0) ? Long.MAX_VALUE : Long.MIN_VALUE;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testDoubleToLongConversion() throws IOException {
+        double max = Long.MAX_VALUE;
+        double min = Long.MIN_VALUE;
+        for (double x : Arrays.asList(-3.5, -3.0, -2.5, -2.0, -1.5,
+                                      StrictMath.nextAfter(-1.0, -2.0), -1.0, StrictMath.nextAfter(-1.0, +2.0),
+                                      -0.5, -0.0, +0.0, 0.5,
+                                      StrictMath.nextAfter(+1.0, -2.0), +1.0, StrictMath.nextAfter(+1.0, +2.0),
+                                      1.5, 2.0, 2.5, 3.0, 3.5,
+                                      Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
+                                      Double.NaN,
+                                      Precision.SAFE_MIN, Precision.EPSILON,
+                                      -Precision.SAFE_MIN, -Precision.EPSILON,
+                                      StrictMath.nextAfter(Precision.SAFE_MIN, Double.NEGATIVE_INFINITY),
+                                      StrictMath.nextAfter(Precision.SAFE_MIN, Double.POSITIVE_INFINITY),
+                                      Precision.SAFE_MIN / 1024,
+                                      Double.MIN_VALUE, Double.MAX_VALUE,
+                                      min,
+                                      StrictMath.nextAfter(min, Double.NEGATIVE_INFINITY),
+                                      StrictMath.nextAfter(min, Double.POSITIVE_INFINITY),
+                                      max,
+                                      StrictMath.nextAfter(max, Double.NEGATIVE_INFINITY),
+                                      StrictMath.nextAfter(max, Double.POSITIVE_INFINITY))) {
+            Assert.assertEquals("x = " + x, (long) x, toLong(x));
+        }
+    }
+
     @Test
     public void testMinMaxDouble() {
         double[][] pairs = {