Fix Half comparison (#39773)
authorGanbarukamo41 <ganbarukamo@gmail.com>
Mon, 27 Jul 2020 15:26:22 +0000 (00:26 +0900)
committerGitHub <noreply@github.com>
Mon, 27 Jul 2020 15:26:22 +0000 (08:26 -0700)
* Fix Half comparison

* Fixes the comparison to be correct when both numbers are negative
* Add relevant tests

* Add parentheses for clarity

* Add tests validating comparison between negative numbers for Single/Double as well

src/libraries/System.Private.CoreLib/src/System/Half.cs
src/libraries/System.Runtime/tests/System/DoubleTests.cs
src/libraries/System.Runtime/tests/System/HalfTests.cs
src/libraries/System.Runtime/tests/System/SingleTests.cs

index d124d7a..34adab5 100644 (file)
@@ -116,7 +116,7 @@ namespace System
                 // says they should be equal, even if the signs differ.
                 return leftIsNegative && !AreZero(left, right);
             }
-            return (short)(left._value) < (short)(right._value);
+            return (left._value < right._value) ^ leftIsNegative;
         }
 
         public static bool operator >(Half left, Half right)
@@ -141,7 +141,7 @@ namespace System
                 // says they should be equal, even if the signs differ.
                 return leftIsNegative || AreZero(left, right);
             }
-            return (short)(left._value) <= (short)(right._value);
+            return (left._value <= right._value) ^ leftIsNegative;
         }
 
         public static bool operator >=(Half left, Half right)
index 92f413c..3de09c6 100644 (file)
@@ -39,6 +39,10 @@ namespace System.Tests
         [InlineData(double.NaN, double.NaN, 0)]
         [InlineData(double.NaN, 0.0, -1)]
         [InlineData(234.0, null, 1)]
+        [InlineData(double.MinValue, double.NegativeInfinity, 1)]
+        [InlineData(double.NegativeInfinity, double.MinValue, -1)]
+        [InlineData(-0d, double.NegativeInfinity, 1)]
+        [InlineData(double.NegativeInfinity, -0d, -1)]
         public static void CompareTo_Other_ReturnsExpected(double d1, object value, int expected)
         {
             if (value is double d2)
index 4de5db4..de5eddf 100644 (file)
@@ -281,6 +281,10 @@ namespace System.Tests
             yield return new object[] { Half.NaN, Half.NaN, 0 };
             yield return new object[] { Half.NaN, UInt16BitsToHalf(0x0000), -1 };
             yield return new object[] { Half.MaxValue, null, 1 };
+            yield return new object[] { Half.MinValue, Half.NegativeInfinity, 1 };
+            yield return new object[] { Half.NegativeInfinity, Half.MinValue, -1 };
+            yield return new object[] { UInt16BitsToHalf(0x8000), Half.NegativeInfinity, 1 }; // Negative zero
+            yield return new object[] { Half.NegativeInfinity, UInt16BitsToHalf(0x8000), -1 }; // Negative zero
         }
 
         [Theory]
index 53018c7..a9701f3 100644 (file)
@@ -40,6 +40,10 @@ namespace System.Tests
         [InlineData(float.NaN, float.NaN, 0)]
         [InlineData(float.NaN, 0.0f, -1)]
         [InlineData(234.0f, null, 1)]
+        [InlineData(float.MinValue, float.NegativeInfinity, 1)]
+        [InlineData(float.NegativeInfinity, float.MinValue, -1)]
+        [InlineData(-0f, float.NegativeInfinity, 1)]
+        [InlineData(float.NegativeInfinity, -0f, -1)]
         public static void CompareTo_Other_ReturnsExpected(float f1, object value, int expected)
         {
             if (value is float f2)