From: Tanner Gooding Date: Wed, 17 Apr 2019 03:13:12 +0000 (-0700) Subject: Changing Math.Max, Math.Min, Math.MaxMagnitude, and Math.MinMagnitude to propagate... X-Git-Tag: submit/tizen/20210909.063632~11030^2~1814 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0a733e46d441fd6df2f14f01c4cf24d641661d2e;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Changing Math.Max, Math.Min, Math.MaxMagnitude, and Math.MinMagnitude to propagate NaN inputs (dotnet/coreclr#24039) Commit migrated from https://github.com/dotnet/coreclr/commit/c5b2e71106b1a8d2480e1f08bffcb09358f0a45a --- diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index 1c36c9d..ac9be48 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -538,31 +538,23 @@ namespace System public static double Max(double val1, double val2) { - // When val1 and val2 are both finite or infinite, return the larger - // * We count +0.0 as larger than -0.0 to match MSVC - // When val1 or val2, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `maximum` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the larger of the inputs. It + // treats +0 as larger than -0 as per the specification. - if (double.IsNaN(val1)) - { - return val2; - } - - if (double.IsNaN(val2)) + if ((val1 > val2) || double.IsNaN(val1)) { return val1; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT - // which would then return an incorrect value - if (val1 == val2) { return double.IsNegative(val1) ? val2 : val1; } - return (val1 < val2) ? val2 : val1; + return val2; } [NonVersionable] @@ -592,31 +584,23 @@ namespace System public static float Max(float val1, float val2) { - // When val1 and val2 are both finite or infinite, return the larger - // * We count +0.0 as larger than -0.0 to match MSVC - // When val1 or val2, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `maximum` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the larger of the inputs. It + // treats +0 as larger than -0 as per the specification. - if (float.IsNaN(val1)) - { - return val2; - } - - if (float.IsNaN(val2)) + if ((val1 > val2) || float.IsNaN(val1)) { return val1; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT - // which would then return an incorrect value - if (val1 == val2) { return float.IsNegative(val1) ? val2 : val1; } - return (val1 < val2) ? val2 : val1; + return val2; } [CLSCompliant(false)] @@ -642,34 +626,26 @@ namespace System public static double MaxMagnitude(double x, double y) { - // When x and y are both finite or infinite, return the larger magnitude - // * We count +0.0 as larger than -0.0 to match MSVC - // When x or y, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `maximumMagnitude` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the input with a larger magnitude. + // It treats +0 as larger than -0 as per the specification. - if (double.IsNaN(x)) - { - return y; - } + double ax = Abs(x); + double ay = Abs(y); - if (double.IsNaN(y)) + if ((ax > ay) || double.IsNaN(ax)) { return x; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would - // then return an incorrect value - - double ax = Abs(x); - double ay = Abs(y); - if (ax == ay) { return double.IsNegative(x) ? y : x; } - return (ax < ay) ? y : x; + return y; } [NonVersionable] @@ -686,31 +662,23 @@ namespace System public static double Min(double val1, double val2) { - // When val1 and val2 are both finite or infinite, return the smaller - // * We count -0.0 as smaller than -0.0 to match MSVC - // When val1 or val2, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `minimum` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the larger of the inputs. It + // treats +0 as larger than -0 as per the specification. - if (double.IsNaN(val1)) - { - return val2; - } - - if (double.IsNaN(val2)) + if ((val1 < val2) || double.IsNaN(val1)) { return val1; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT - // which would then return an incorrect value - if (val1 == val2) { return double.IsNegative(val1) ? val1 : val2; } - return (val1 < val2) ? val1 : val2; + return val2; } [NonVersionable] @@ -740,31 +708,23 @@ namespace System public static float Min(float val1, float val2) { - // When val1 and val2 are both finite or infinite, return the smaller - // * We count -0.0 as smaller than -0.0 to match MSVC - // When val1 or val2, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `minimum` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the larger of the inputs. It + // treats +0 as larger than -0 as per the specification. - if (float.IsNaN(val1)) - { - return val2; - } - - if (float.IsNaN(val2)) + if ((val1 < val2) || float.IsNaN(val1)) { return val1; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT - // which would then return an incorrect value - if (val1 == val2) { return float.IsNegative(val1) ? val1 : val2; } - return (val1 < val2) ? val1 : val2; + return val2; } [CLSCompliant(false)] @@ -790,34 +750,26 @@ namespace System public static double MinMagnitude(double x, double y) { - // When x and y are both finite or infinite, return the smaller magnitude - // * We count -0.0 as smaller than -0.0 to match MSVC - // When x or y, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `minimumMagnitude` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the input with a larger magnitude. + // It treats +0 as larger than -0 as per the specification. - if (double.IsNaN(x)) - { - return y; - } + double ax = Abs(x); + double ay = Abs(y); - if (double.IsNaN(y)) + if ((ax < ay) || double.IsNaN(ax)) { return x; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would - // then return an incorrect value - - double ax = Abs(x); - double ay = Abs(y); - if (ax == ay) { return double.IsNegative(x) ? x : y; } - return (ax < ay) ? x : y; + return y; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/MathF.cs b/src/libraries/System.Private.CoreLib/src/System/MathF.cs index 1defa4e..bf32486 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MathF.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MathF.cs @@ -190,34 +190,26 @@ namespace System public static float MaxMagnitude(float x, float y) { - // When x and y are both finite or infinite, return the larger magnitude - // * We count +0.0 as larger than -0.0 to match MSVC - // When x or y, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `maximumMagnitude` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the input with a larger magnitude. + // It treats +0 as larger than -0 as per the specification. - if (float.IsNaN(x)) - { - return y; - } + float ax = Abs(x); + float ay = Abs(y); - if (float.IsNaN(y)) + if ((ax > ay) || float.IsNaN(ax)) { return x; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would - // then return an incorrect value - - float ax = Abs(x); - float ay = Abs(y); - if (ax == ay) { return float.IsNegative(x) ? y : x; } - return (ax < ay) ? y : x; + return y; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -228,34 +220,26 @@ namespace System public static float MinMagnitude(float x, float y) { - // When x and y are both finite or infinite, return the smaller magnitude - // * We count -0.0 as smaller than -0.0 to match MSVC - // When x or y, but not both, are NaN return the opposite - // * We return the opposite if either is NaN to match MSVC + // This matches the IEEE 754:2019 `minimumMagnitude` function + // + // It propagates NaN inputs back to the caller and + // otherwise returns the input with a larger magnitude. + // It treats +0 as larger than -0 as per the specification. - if (float.IsNaN(x)) - { - return y; - } + float ax = Abs(x); + float ay = Abs(y); - if (float.IsNaN(y)) + if ((ax < ay) || float.IsNaN(ax)) { return x; } - // We do this comparison first and separately to handle the -0.0 to +0.0 comparision - // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would - // then return an incorrect value - - float ax = Abs(x); - float ay = Abs(y); - if (ax == ay) { return float.IsNegative(x) ? x : y; } - return (ax < ay) ? x : y; + return y; } [Intrinsic]