Skip to content

Commit 2113bac

Browse files
committed
o fix assert not nan == nan and nan != nan, and cmp on nans
o fix math.frexp(nan) causing an endless loop
1 parent bb0195f commit 2113bac

4 files changed

Lines changed: 86 additions & 21 deletions

File tree

Lib/test/test_float_jy.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,22 @@ def test_overflow(self):
6666
self.assertNotEqual(0.1, shuge_int)
6767

6868
def test_nan(self):
69-
self.assert_(type(float('NaN')), float)
70-
self.assert_(type(float('nan')), float)
71-
self.assertEqual(long(float('NaN')), 0)
69+
nan = float('nan')
70+
self.assert_(type(nan), float)
71+
if jython:
72+
# support Java syntax
73+
self.assert_(type(float('NaN')), float)
74+
75+
# CPython 2.4/2.5 allow this
76+
self.assertEqual(long(nan), 0)
77+
78+
self.assertNotEqual(nan, float('nan'))
79+
self.assertNotEqual(nan, nan)
80+
self.assertEqual(cmp(nan, float('nan')), 1)
81+
self.assertEqual(cmp(nan, nan), 0)
82+
for i in (-1, 1, -1.0, 1.0):
83+
self.assertEqual(cmp(nan, i), -1)
84+
self.assertEqual(cmp(i, nan), 1)
7285

7386
def test_infinity(self):
7487
self.assert_(type(float('Infinity')), float)

Lib/test/test_math_jy.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Misc math module tests
2+
3+
Made for Jython.
4+
"""
5+
import math
6+
import unittest
7+
from test import test_support
8+
9+
inf = float('inf')
10+
nan = float('nan')
11+
12+
class MathTestCase(unittest.TestCase):
13+
14+
def test_frexp(self):
15+
self.assertEqual(math.frexp(inf), (inf, 0))
16+
mantissa, exponent = math.frexp(nan)
17+
self.assertNotEqual(mantissa, mantissa)
18+
self.assertEqual(exponent, 0)
19+
20+
21+
def test_main():
22+
test_support.run_unittest(MathTestCase)
23+
24+
25+
if __name__ == '__main__':
26+
test_main()

src/org/python/core/PyFloat.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,22 @@ public Object __tojava__(Class c) {
168168
return super.__tojava__(c);
169169
}
170170

171+
public PyObject __eq__(PyObject other) {
172+
// preclude _cmp_unsafe's this == other shortcut because NaN != anything, even
173+
// itself
174+
if (Double.isNaN(value)) {
175+
return Py.False;
176+
}
177+
return null;
178+
}
179+
180+
public PyObject __ne__(PyObject other) {
181+
if (Double.isNaN(value)) {
182+
return Py.True;
183+
}
184+
return null;
185+
}
186+
171187
public int __cmp__(PyObject other) {
172188
return float___cmp__(other);
173189
}
@@ -197,7 +213,17 @@ final int float___cmp__(PyObject other) {
197213
} else {
198214
return -2;
199215
}
200-
return i < j ? -1 : i > j ? 1 : 0;
216+
217+
if (i < j) {
218+
return -1;
219+
} else if (i > j) {
220+
return 1;
221+
} else if (i == j) {
222+
return 0;
223+
} else {
224+
// at least one side is NaN
225+
return Double.isNaN(i) ? (Double.isNaN(j) ? 1 : -1) : 1;
226+
}
201227
}
202228

203229
public Object __coerce_ex__(PyObject other) {

src/org/python/modules/math.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -157,26 +157,26 @@ public static PyTuple modf(double v) {
157157
return new PyTuple(new PyFloat(w), new PyFloat(v));
158158
}
159159

160-
public static PyTuple frexp(double v) {
161-
int i = 0;
162-
if (v != 0.0) {
163-
int sign = 1;
164-
if (v < 0) {
160+
public static PyTuple frexp(double x) {
161+
int exponent = 0;
162+
163+
if (Double.isNaN(x) || Double.isInfinite(x) || x == 0.0) {
164+
exponent = 0;
165+
} else {
166+
short sign = 1;
167+
168+
if (x < 0.0) {
169+
x = -x;
165170
sign = -1;
166-
v = -v;
167-
}
168-
// slow...
169-
while (v < 0.5) {
170-
v = v*2.0;
171-
i = i-1;
172171
}
173-
while (v >= 1.0) {
174-
v = v*0.5;
175-
i = i+1;
176-
}
177-
v = v*sign;
172+
173+
for (; x < 0.5; x *= 2.0, exponent--);
174+
175+
for (; x >= 1.0; x *= 0.5, exponent++);
176+
177+
x *= sign;
178178
}
179-
return new PyTuple(new PyFloat(v), new PyInteger(i));
179+
return new PyTuple(new PyFloat(x), new PyInteger(exponent));
180180
}
181181

182182
public static double ldexp(double v, int w) {

0 commit comments

Comments
 (0)