Skip to content

Commit c0b336e

Browse files
authored
bpo-29602: fix signed zero handling in complex constructor (#204)
* bpo-29602: fix signed zero handling in complex constructor * Add missing have_getformat definition; remove use of unittest subtests.
1 parent 7131a73 commit c0b336e

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

Lib/test/test_complex.py

+29
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
NAN = float("nan")
99
# These tests ensure that complex math does the right thing
1010

11+
# decorator for skipping tests on non-IEEE 754 platforms
12+
have_getformat = hasattr(float, "__getformat__")
13+
requires_IEEE_754 = unittest.skipUnless(have_getformat and
14+
float.__getformat__("double").startswith("IEEE"),
15+
"test requires IEEE 754 doubles")
16+
17+
1118
class ComplexTest(unittest.TestCase):
1219

1320
def assertAlmostEqual(self, a, b):
@@ -441,6 +448,28 @@ def __rmod__(self,other):
441448
b = 'y %s x' % op
442449
self.assertTrue(type(eval(a)) is type(eval(b)) is xcomplex)
443450

451+
@requires_IEEE_754
452+
def test_constructor_special_numbers(self):
453+
class complex2(complex):
454+
pass
455+
for x in 0.0, -0.0, INF, -INF, NAN:
456+
for y in 0.0, -0.0, INF, -INF, NAN:
457+
z = complex(x, y)
458+
self.assertFloatsAreIdentical(z.real, x)
459+
self.assertFloatsAreIdentical(z.imag, y)
460+
z = complex2(x, y)
461+
self.assertIs(type(z), complex2)
462+
self.assertFloatsAreIdentical(z.real, x)
463+
self.assertFloatsAreIdentical(z.imag, y)
464+
z = complex(complex2(x, y))
465+
self.assertIs(type(z), complex)
466+
self.assertFloatsAreIdentical(z.real, x)
467+
self.assertFloatsAreIdentical(z.imag, y)
468+
z = complex2(complex(x, y))
469+
self.assertIs(type(z), complex2)
470+
self.assertFloatsAreIdentical(z.real, x)
471+
self.assertFloatsAreIdentical(z.imag, y)
472+
444473
def test_hash(self):
445474
for x in xrange(-30, 30):
446475
self.assertEqual(hash(x), hash(complex(x, 0)))

Misc/NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ What's New in Python 2.7.14?
1010
Core and Builtins
1111
-----------------
1212

13+
- bpo-29602: Fix incorrect handling of signed zeros in complex constructor for
14+
complex subclasses and for inputs having a __complex__ method. Patch
15+
by Serhiy Storchaka.
16+
1317
- bpo-29347: Fixed possibly dereferencing undefined pointers
1418
when creating weakref objects.
1519

Objects/complexobject.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1232,11 +1232,11 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
12321232
return NULL;
12331233
}
12341234
cr.real = PyFloat_AsDouble(tmp);
1235-
cr.imag = 0.0; /* Shut up compiler warning */
1235+
cr.imag = 0.0;
12361236
Py_DECREF(tmp);
12371237
}
12381238
if (i == NULL) {
1239-
ci.real = 0.0;
1239+
ci.real = cr.imag;
12401240
}
12411241
else if (PyComplex_Check(i)) {
12421242
ci = ((PyComplexObject*)i)->cval;
@@ -1258,7 +1258,7 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
12581258
if (ci_is_complex) {
12591259
cr.real -= ci.imag;
12601260
}
1261-
if (cr_is_complex) {
1261+
if (cr_is_complex && i != NULL) {
12621262
ci.real += cr.imag;
12631263
}
12641264
return complex_subtype_from_doubles(type, cr.real, ci.real);

0 commit comments

Comments
 (0)