[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