[Jython-checkins] jython: Use Java equivalents of frexp, ldexp and copysign directly.

jeff.allen jython-checkins at python.org
Tue Jan 6 20:23:01 CET 2015


https://hg.python.org/jython/rev/44cfecd93257
changeset:   7510:44cfecd93257
user:        Jeff Allen <ja.py at farowl.co.uk>
date:        Mon Jan 05 23:17:51 2015 +0000
summary:
  Use Java equivalents of frexp, ldexp and copysign directly.

files:
  src/org/python/modules/math.java |  92 ++++++-------------
  1 files changed, 32 insertions(+), 60 deletions(-)


diff --git a/src/org/python/modules/math.java b/src/org/python/modules/math.java
--- a/src/org/python/modules/math.java
+++ b/src/org/python/modules/math.java
@@ -20,7 +20,6 @@
 
     private static final double ZERO = 0.0;
     private static final double MINUS_ZERO = -0.0;
-    private static final double HALF = 0.5;
     private static final double ONE = 1.0;
     private static final double MINUS_ONE = -1.0;
     private static final double TWO = 2.0;
@@ -347,25 +346,36 @@
     }
 
     public static PyTuple frexp(double x) {
-        int exponent = 0;
+        int exponent;
+        double mantissa;
 
-        if (isnan(x) || isinf(x) || x == ZERO) {
-            exponent = 0;
-        } else {
-            short sign = 1;
+        switch (exponent = Math.getExponent(x)) {
 
-            if (x < ZERO) {
-                x = -x;
-                sign = -1;
-            }
+            default:
+                // x = m * 2**exponent and 1 <=abs(m) <2
+                exponent = exponent + 1;
+                // x = m * 2**exponent and 0.5 <=abs(m) <1
+                mantissa = Math.scalb(x, -exponent);
+                break;
 
-            for (; x < HALF; x *= TWO, exponent--) {}
+            case 1024:  // nan or inf
+                mantissa = x;
+                exponent = 0;
+                break;
 
-            for (; x >= ONE; x *= HALF, exponent++) {}
+            case -1023:
+                if (x == 0.) { // , 0.0 or -0.0
+                    mantissa = x;
+                    exponent = 0;
+                } else { // denormalised value
+                    // x = m * 2**exponent but 0 < abs(m) < 1
+                    exponent = Math.getExponent(x * 0x1p52) - 51;
+                    mantissa = Math.scalb(x, -exponent);
+                }
+                break;
+        }
 
-            x *= sign;
-        }
-        return new PyTuple(new PyFloat(x), new PyInteger(exponent));
+        return new PyTuple(new PyFloat(mantissa), new PyInteger(exponent));
     }
 
     public static PyObject trunc(PyObject number) {
@@ -373,23 +383,13 @@
     }
 
     public static double ldexp(double v, PyObject wObj) {
-        if (ZERO == v) {
-            return v; // can be negative zero
+        long w = getLong(wObj);
+        if (w < Integer.MIN_VALUE) {
+            w = Integer.MIN_VALUE;
+        } else if (w > Integer.MAX_VALUE) {
+            w = Integer.MAX_VALUE;
         }
-        if (isinf(v)) {
-            return v;
-        }
-        if (isnan(v)) {
-            return v;
-        }
-        long w = getLong(wObj);
-        if (w == Long.MIN_VALUE) {
-            if (v > ZERO) {
-                return ZERO;
-            }
-            return MINUS_ZERO;
-        }
-        return checkOverflow(v * Math.pow(TWO, w));
+        return exceptInf(Math.scalb(v, (int)w), v);
     }
 
     /**
@@ -433,13 +433,7 @@
     }
 
     public static double copysign(double v, double w) {
-        if (isnan(v)) {
-            return NAN;
-        }
-        if (signum(v) == signum(w)) {
-            return v;
-        }
-        return v *= MINUS_ONE;
+        return Math.copySign(v, w);
     }
 
     public static PyLong factorial(double v) {
@@ -517,21 +511,6 @@
     }
 
     /**
-     * work around special Math.signum() behaviour for positive and negative zero
-     */
-    private static double signum(double v) {
-        double signum = ONE;
-        if (v == ZERO) {
-            if ('-' == Double.toString(v).charAt(0)) {
-                signum = MINUS_ONE;
-            }
-        } else {
-            signum = Math.signum(v);
-        }
-        return signum;
-    }
-
-    /**
      * Returns a ValueError("math domain error"), ready to throw from the client code.
      *
      * @return ValueError("math domain error")
@@ -549,13 +528,6 @@
         return Py.OverflowError("math range error");
     }
 
-    private static double checkOverflow(double v) {
-        if (isinf(v)) {
-            throw Py.OverflowError("math range error");
-        }
-        return v;
-    }
-
     /**
      * Turn a <code>NaN</code> result into a thrown <code>ValueError</code>, a math domain error, if
      * the original argument was not itself <code>NaN</code>. Use as:

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list