cmp/internal/value: fix handling of negative zero for floats (#152)

* Fix IsZero to properly report false for IsZero(-0.0) since
we define IsZero as whether it is equal to the zero memory value.
* Add note to isLess that we don't need to handle -0.0 since
we can't possibly have both keys present in the same map.
* Use sort.SliceStable in SortedKeys for deterministic output since
it is possible to have both -0.0 and +0.0 from two different maps.
The zero key from the left left map will be taken over the right map.
diff --git a/cmp/internal/value/sort.go b/cmp/internal/value/sort.go
index 938f646..24fbae6 100644
--- a/cmp/internal/value/sort.go
+++ b/cmp/internal/value/sort.go
@@ -19,7 +19,7 @@
 	}
 
 	// Sort the map keys.
-	sort.Slice(vs, func(i, j int) bool { return isLess(vs[i], vs[j]) })
+	sort.SliceStable(vs, func(i, j int) bool { return isLess(vs[i], vs[j]) })
 
 	// Deduplicate keys (fails for NaNs).
 	vs2 := vs[:1]
@@ -42,6 +42,8 @@
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 		return x.Uint() < y.Uint()
 	case reflect.Float32, reflect.Float64:
+		// NOTE: This does not sort -0 as less than +0
+		// since Go maps treat -0 and +0 as equal keys.
 		fx, fy := x.Float(), y.Float()
 		return fx < fy || math.IsNaN(fx) && !math.IsNaN(fy)
 	case reflect.Complex64, reflect.Complex128:
diff --git a/cmp/internal/value/zero.go b/cmp/internal/value/zero.go
index d13a12c..06a8ffd 100644
--- a/cmp/internal/value/zero.go
+++ b/cmp/internal/value/zero.go
@@ -4,7 +4,10 @@
 
 package value
 
-import "reflect"
+import (
+	"math"
+	"reflect"
+)
 
 // IsZero reports whether v is the zero value.
 // This does not rely on Interface and so can be used on unexported fields.
@@ -17,9 +20,9 @@
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 		return v.Uint() == 0
 	case reflect.Float32, reflect.Float64:
-		return v.Float() == 0
+		return math.Float64bits(v.Float()) == 0
 	case reflect.Complex64, reflect.Complex128:
-		return v.Complex() == 0
+		return math.Float64bits(real(v.Complex())) == 0 && math.Float64bits(imag(v.Complex())) == 0
 	case reflect.String:
 		return v.String() == ""
 	case reflect.UnsafePointer:
diff --git a/cmp/internal/value/zero_test.go b/cmp/internal/value/zero_test.go
index 536d50b..1d6c434 100644
--- a/cmp/internal/value/zero_test.go
+++ b/cmp/internal/value/zero_test.go
@@ -6,6 +6,7 @@
 
 import (
 	"archive/tar"
+	"math"
 	"reflect"
 	"testing"
 )
@@ -32,6 +33,12 @@
 		{TestIsZero, false},
 		{[...]int{0, 0, 0}, true},
 		{[...]int{0, 1, 0}, false},
+		{math.Copysign(0, +1), true},
+		{math.Copysign(0, -1), false},
+		{complex(math.Copysign(0, +1), math.Copysign(0, +1)), true},
+		{complex(math.Copysign(0, -1), math.Copysign(0, +1)), false},
+		{complex(math.Copysign(0, +1), math.Copysign(0, -1)), false},
+		{complex(math.Copysign(0, -1), math.Copysign(0, -1)), false},
 	}
 
 	for _, tt := range tests {