]> granicus.if.org Git - python/commitdiff
Merged revisions 76575 via svnmerge from
authorMark Dickinson <dickinsm@gmail.com>
Sat, 28 Nov 2009 16:38:16 +0000 (16:38 +0000)
committerMark Dickinson <dickinsm@gmail.com>
Sat, 28 Nov 2009 16:38:16 +0000 (16:38 +0000)
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.
........

Python/compile.c

index d8fb47b16ecb5de890742fab4f2d4fcb9f6dbcb2..2c58d449b5e24cbeeff8c14aecaa1918f849e65e 100644 (file)
@@ -895,50 +895,39 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
 {
        PyObject *t, *v;
        Py_ssize_t arg;
-       unsigned char *p;
        double d;
 
        /* 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 */
         if (PyFloat_Check(o)) {
                d = PyFloat_AS_DOUBLE(o);
-               p = (unsigned char*) &d;
                /* 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".
                 */
-               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);
                else
                        t = PyTuple_Pack(2, o, o->ob_type);
        }
        else if (PyComplex_Check(o)) {
                Py_complex z;
-               int real_part_zero, imag_part_zero;
-               unsigned char *q;
-               /* complex case is even messier: we need to make complex(x,
-                  0.) different from complex(x, -0.) and complex(0., y)
-                  different from complex(-0., y), for any x and y.  In
-                  particular, all four complex zeros should be
-                  distinguished.*/
+               int real_negzero, imag_negzero;
+               /* For the complex case we must make complex(x, 0.)
+                  different from complex(x, -0.) and complex(0., y)
+                  different from complex(-0., y), for any x and y.
+                  All four complex zeros must be distinguished.*/
                z = PyComplex_AsCComplex(o);
-               p = (unsigned char*) &(z.real);
-               q = (unsigned char*) &(z.imag);
-               /* all that matters here is that on IEEE platforms
-                  real_part_zero will be true if z.real == 0., and false if
-                  z.real == -0.  In fact, real_part_zero will also be true
-                  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) {
-                       t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_False);
-               }
-               else if (!real_part_zero && imag_part_zero) {
-                       t = PyTuple_Pack(4, o, o->ob_type, Py_False, Py_True);
+               real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
+               imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
+               if (real_negzero && imag_negzero) {
+                       t = PyTuple_Pack(5, o, o->ob_type,
+                                        Py_None, Py_None, Py_None);
+               }
+               else if (imag_negzero) {
+                       t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None);
+               }
+               else if (real_negzero) {
+                       t = PyTuple_Pack(3, o, o->ob_type, Py_None);
                }
                else {
                        t = PyTuple_Pack(2, o, o->ob_type);