Issue 1678380:  fix a bug identifying -0.0 and 0.0
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
index fb47db8..2f0d784 100644
--- a/Lib/test/test_float.py
+++ b/Lib/test/test_float.py
@@ -99,6 +99,27 @@
                               ('<f', LE_FLOAT_NAN)]:
                 struct.unpack(fmt, data)
 
+    if float.__getformat__("double").startswith("IEEE"):
+        def test_negative_zero(self):
+            import math
+            def pos_pos():
+                return 0.0, math.atan2(0.0, -1)
+            def pos_neg():
+                return 0.0, math.atan2(-0.0, -1)
+            def neg_pos():
+                return -0.0, math.atan2(0.0, -1)
+            def neg_neg():
+                return -0.0, math.atan2(-0.0, -1)
+            self.assertEquals(pos_pos(), neg_pos())
+            self.assertEquals(pos_neg(), neg_neg())
+
+    if float.__getformat__("double").startswith("IEEE"):
+        def test_underflow_sign(self):
+            import math
+            # check that -1e-1000 gives -0.0, not 0.0
+            self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
+            self.assertEquals(math.atan2(float('-1e-1000'), -1),
+                              math.atan2(-0.0, -1))
 
 def test_main():
     test_support.run_unittest(
diff --git a/Misc/NEWS b/Misc/NEWS
index 00db9af..dd06f60 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@
 Core and builtins
 -----------------
 
+- Issue #1678380: distinction between 0.0 and -0.0 was lost during constant
+  folding optimization.  This was a regression from Python 2.4.
+
 - Issue #1882: when compiling code from a string, encoding cookies in the
   second line of code were not always recognized correctly.
 
diff --git a/Python/compile.c b/Python/compile.c
index ce19aa9..0e824ca 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1567,7 +1567,20 @@
 	Py_ssize_t arg;
 
 	/* necessary to make sure types aren't coerced (e.g., int and long) */
-	t = PyTuple_Pack(2, o, o->ob_type);
+        /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */
+        if (PyFloat_Check(o)) {
+            double d = PyFloat_AS_DOUBLE(o);
+            unsigned char* 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)
+                t = PyTuple_Pack(3, o, o->ob_type, Py_None);
+            else
+	        t = PyTuple_Pack(2, o, o->ob_type);
+        } else {
+	    t = PyTuple_Pack(2, o, o->ob_type);
+        }
 	if (t == NULL)
 	    return -1;