Merged revisions 76575 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r76575 | mark.dickinson | 2009-11-28 16:32:27 +0000 (Sat, 28 Nov 2009) | 5 lines

  Issue #1678380: When distinguishing between -0.0 and 0.0 in
  compiler_add_o, use copysign instead of examining the first and last
  bytes of the double.  The latter method fails for little-endian
  ARM, OABI, where doubles are little-endian but with the words swapped.
........
This commit is contained in:
Mark Dickinson 2009-11-28 16:37:36 +00:00
parent 22919aaa38
commit 48a522de9a
1 changed files with 15 additions and 26 deletions

View File

@ -922,18 +922,16 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
{ {
PyObject *t, *v; PyObject *t, *v;
Py_ssize_t arg; Py_ssize_t arg;
unsigned char *p;
double d; double d;
/* necessary to make sure types aren't coerced (e.g., int and long) */ /* necessary to make sure types aren't coerced (e.g., int and long) */
/* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */
if (PyFloat_Check(o)) { if (PyFloat_Check(o)) {
d = PyFloat_AS_DOUBLE(o); d = PyFloat_AS_DOUBLE(o);
p = (unsigned char*) &d;
/* all we need is to make the tuple different in either the 0.0 /* all we need is to make the tuple different in either the 0.0
* or -0.0 case from all others, just to avoid the "coercion". * or -0.0 case from all others, just to avoid the "coercion".
*/ */
if (*p==0 && p[sizeof(double)-1]==0) if (d == 0.0 && copysign(1.0, d) < 0.0)
t = PyTuple_Pack(3, o, o->ob_type, Py_None); t = PyTuple_Pack(3, o, o->ob_type, Py_None);
else else
t = PyTuple_Pack(2, o, o->ob_type); t = PyTuple_Pack(2, o, o->ob_type);
@ -941,32 +939,23 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
#ifndef WITHOUT_COMPLEX #ifndef WITHOUT_COMPLEX
else if (PyComplex_Check(o)) { else if (PyComplex_Check(o)) {
Py_complex z; Py_complex z;
int real_part_zero, imag_part_zero; int real_negzero, imag_negzero;
unsigned char *q; /* For the complex case we must make complex(x, 0.)
/* complex case is even messier: we need to make complex(x, different from complex(x, -0.) and complex(0., y)
0.) different from complex(x, -0.) and complex(0., y) different from complex(-0., y), for any x and y.
different from complex(-0., y), for any x and y. In All four complex zeros must be distinguished.*/
particular, all four complex zeros should be
distinguished.*/
z = PyComplex_AsCComplex(o); z = PyComplex_AsCComplex(o);
p = (unsigned char*) &(z.real); real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
q = (unsigned char*) &(z.imag); imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
/* all that matters here is that on IEEE platforms if (real_negzero && imag_negzero) {
real_part_zero will be true if z.real == 0., and false if t = PyTuple_Pack(5, o, o->ob_type,
z.real == -0. In fact, real_part_zero will also be true Py_None, Py_None, Py_None);
for some other rarely occurring nonzero floats, but this
doesn't matter. Similar comments apply to
imag_part_zero. */
real_part_zero = *p==0 && p[sizeof(double)-1]==0;
imag_part_zero = *q==0 && q[sizeof(double)-1]==0;
if (real_part_zero && imag_part_zero) {
t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_True);
} }
else if (real_part_zero && !imag_part_zero) { else if (imag_negzero) {
t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_False); t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None);
} }
else if (!real_part_zero && imag_part_zero) { else if (real_negzero) {
t = PyTuple_Pack(4, o, o->ob_type, Py_False, Py_True); t = PyTuple_Pack(3, o, o->ob_type, Py_None);
} }
else { else {
t = PyTuple_Pack(2, o, o->ob_type); t = PyTuple_Pack(2, o, o->ob_type);