Patch # 1507 by Mark Dickinson. Make complex(x, -0) retain the sign of

the imaginary part (as long as it's not complex).
Backport candidate?
This commit is contained in:
Guido van Rossum 2007-11-27 22:38:36 +00:00
parent b61a1f5219
commit 715ec1818d
2 changed files with 28 additions and 9 deletions

View File

@ -9,6 +9,7 @@ warnings.filterwarnings(
)
from random import random
from math import atan2
# These tests ensure that complex math does the right thing
@ -225,6 +226,18 @@ class ComplexTest(unittest.TestCase):
self.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)
self.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)
# check that the sign of a zero in the real or imaginary part
# is preserved when constructing from two floats. (These checks
# are harmless on systems without support for signed zeros.)
def split_zeros(x):
"""Function that produces different results for 0. and -0."""
return atan2(x, -1.)
self.assertEqual(split_zeros(complex(1., 0.).imag), split_zeros(0.))
self.assertEqual(split_zeros(complex(1., -0.).imag), split_zeros(-0.))
self.assertEqual(split_zeros(complex(0., 1.).real), split_zeros(0.))
self.assertEqual(split_zeros(complex(-0., 1.).real), split_zeros(-0.))
c = 3.14 + 1j
self.assert_(complex(c) is c)
del c

View File

@ -897,6 +897,8 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyNumberMethods *nbr, *nbi = NULL;
Py_complex cr, ci;
int own_r = 0;
int cr_is_complex = 0;
int ci_is_complex = 0;
static PyObject *complexstr;
static char *kwlist[] = {"real", "imag", 0};
@ -977,6 +979,7 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
retaining its real & imag parts here, and the return
value is (properly) of the builtin complex type. */
cr = ((PyComplexObject*)r)->cval;
cr_is_complex = 1;
if (own_r) {
Py_DECREF(r);
}
@ -985,7 +988,6 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* The "real" part really is entirely real, and contributes
nothing in the imaginary direction.
Just treat it as a double. */
cr.imag = 0.0;
tmp = PyNumber_Float(r);
if (own_r) {
/* r was a newly created complex number, rather
@ -1005,15 +1007,14 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
if (i == NULL) {
ci.real = 0.0;
ci.imag = 0.0;
}
else if (PyComplex_Check(i))
else if (PyComplex_Check(i)) {
ci = ((PyComplexObject*)i)->cval;
else {
ci_is_complex = 1;
} else {
/* The "imag" part really is entirely imaginary, and
contributes nothing in the real direction.
Just treat it as a double. */
ci.imag = 0.0;
tmp = (*nbi->nb_float)(i);
if (tmp == NULL)
return NULL;
@ -1021,11 +1022,16 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_DECREF(tmp);
}
/* If the input was in canonical form, then the "real" and "imag"
parts are real numbers, so that ci.real and cr.imag are zero.
parts are real numbers, so that ci.imag and cr.imag are zero.
We need this correction in case they were not real numbers. */
cr.real -= ci.imag;
cr.imag += ci.real;
return complex_subtype_from_c_complex(type, cr);
if (ci_is_complex) {
cr.real -= ci.imag;
}
if (cr_is_complex) {
ci.real += cr.imag;
}
return complex_subtype_from_doubles(type, cr.real, ci.real);
}
PyDoc_STRVAR(complex_doc,