From 1344d37076b1cda691d49eb31edbda5c378413d6 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 8 Jan 2021 10:27:22 -0800 Subject: [PATCH] Adding System.Math overloads for nint/nuint (#46647) * Adding System.Math overloads for nint/nuint * Adding a missing cast * Fixing the Clamp_NInt and Clamp_NUInt tests to work with the provided MemberData --- .../System.Private.CoreLib/src/System/Math.cs | 139 +++++++++++++++++++++ .../System.Runtime.Extensions/tests/System/Math.cs | 64 +++++++++- src/libraries/System.Runtime/ref/System.Runtime.cs | 19 ++- 3 files changed, 216 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index 335a3cc..5ca23b8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -85,6 +85,23 @@ namespace System return value; } + /// Returns the absolute value of a native signed integer. + /// A number that is greater than , but less than or equal to . + /// A native signed integer, x, such that 0 ≤ x ≤ . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Abs(nint value) + { + if (value < 0) + { + value = -value; + if (value < 0) + { + ThrowAbsOverflow(); + } + } + return value; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] [CLSCompliant(false)] public static sbyte Abs(sbyte value) @@ -522,6 +539,41 @@ namespace System return value; } + /// Returns clamped to the inclusive range of and . + /// The value to be clamped. + /// The lower bound of the result. + /// The upper bound of the result. + /// + /// if ≤ ≤ . + /// + /// -or- + /// + /// if < . + /// + /// -or- + /// + /// if < . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static nint Clamp(nint value, nint min, nint max) + { + if (min > max) + { + ThrowMinMaxException(min, max); + } + + if (value < min) + { + return min; + } + else if (value > max) + { + return max; + } + + return value; + } + [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static sbyte Clamp(sbyte value, sbyte min, sbyte max) @@ -626,6 +678,42 @@ namespace System return value; } + /// Returns clamped to the inclusive range of and . + /// The value to be clamped. + /// The lower bound of the result. + /// The upper bound of the result. + /// + /// if ≤ ≤ . + /// + /// -or- + /// + /// if < . + /// + /// -or- + /// + /// if < . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [CLSCompliant(false)] + public static nuint Clamp(nuint value, nuint min, nuint max) + { + if (min > max) + { + ThrowMinMaxException(min, max); + } + + if (value < min) + { + return min; + } + else if (value > max) + { + return max; + } + + return value; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Floor(decimal d) { @@ -760,6 +848,16 @@ namespace System return (val1 >= val2) ? val1 : val2; } + /// Returns the larger of two native signed integers. + /// The first of two native signed integers to compare. + /// The second of two native signed integers to compare. + /// Parameter or , whichever is larger. + [NonVersionable] + public static nint Max(nint val1, nint val2) + { + return (val1 >= val2) ? val1 : val2; + } + [CLSCompliant(false)] [NonVersionable] public static sbyte Max(sbyte val1, sbyte val2) @@ -810,6 +908,17 @@ namespace System return (val1 >= val2) ? val1 : val2; } + /// Returns the larger of two native unsigned integers. + /// The first of two native unsigned integers to compare. + /// The second of two native unsigned integers to compare. + /// Parameter or , whichever is larger. + [CLSCompliant(false)] + [NonVersionable] + public static nuint Max(nuint val1, nuint val2) + { + return (val1 >= val2) ? val1 : val2; + } + public static double MaxMagnitude(double x, double y) { // This matches the IEEE 754:2019 `maximumMagnitude` function @@ -881,6 +990,16 @@ namespace System return (val1 <= val2) ? val1 : val2; } + /// Returns the smaller of two native signed integers. + /// The first of two native signed integers to compare. + /// The second of two native signed integers to compare. + /// Parameter or , whichever is smaller. + [NonVersionable] + public static nint Min(nint val1, nint val2) + { + return (val1 <= val2) ? val1 : val2; + } + [CLSCompliant(false)] [NonVersionable] public static sbyte Min(sbyte val1, sbyte val2) @@ -926,6 +1045,17 @@ namespace System return (val1 <= val2) ? val1 : val2; } + /// Returns the smaller of two native unsigned integers. + /// The first of two native unsigned integers to compare. + /// The second of two native unsigned integers to compare. + /// Parameter or , whichever is smaller. + [CLSCompliant(false)] + [NonVersionable] + public static nuint Min(nuint val1, nuint val2) + { + return (val1 <= val2) ? val1 : val2; + } + public static double MinMagnitude(double x, double y) { // This matches the IEEE 754:2019 `minimumMagnitude` function @@ -1165,6 +1295,15 @@ namespace System return unchecked((int)(value >> 63 | (long)((ulong)-value >> 63))); } + public static int Sign(nint value) + { +#if TARGET_64BIT + return unchecked((int)(value >> 63 | (long)((ulong)-value >> 63))); +#else + return unchecked((int)(value >> 31) | (int)((uint)-value >> 31)); +#endif + } + [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Sign(sbyte value) diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Math.cs b/src/libraries/System.Runtime.Extensions/tests/System/Math.cs index a774266..2fc59ef 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/Math.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/Math.cs @@ -441,6 +441,15 @@ namespace System.Tests } [Fact] + public static void Abs_NInt() + { + Assert.Equal((nint)3, Math.Abs((nint)3)); + Assert.Equal((nint)0, Math.Abs((nint)0)); + Assert.Equal((nint)3, Math.Abs((nint)(-3))); + Assert.Throws(() => Math.Abs(nint.MinValue)); + } + + [Fact] public static void Abs_SByte() { Assert.Equal((sbyte)3, Math.Abs((sbyte)3)); @@ -1113,6 +1122,13 @@ namespace System.Tests } [Fact] + public static void Max_NInt() + { + Assert.Equal((nint)3, Math.Max((nint)(-2), (nint)3)); + Assert.Equal(nint.MaxValue, Math.Max(nint.MinValue, nint.MaxValue)); + } + + [Fact] public static void Max_SByte() { Assert.Equal((sbyte)3, Math.Max((sbyte)(-2), (sbyte)3)); @@ -1164,6 +1180,13 @@ namespace System.Tests } [Fact] + public static void Max_NUInt() + { + Assert.Equal((nuint)3, Math.Max((nuint)2, (nuint)3)); + Assert.Equal(nuint.MaxValue, Math.Max(nuint.MinValue, nuint.MaxValue)); + } + + [Fact] public static void Min_Byte() { Assert.Equal((byte)2, Math.Min((byte)3, (byte)2)); @@ -1222,6 +1245,13 @@ namespace System.Tests } [Fact] + public static void Min_NInt() + { + Assert.Equal((nint)(-2), Math.Min((nint)3, (nint)(-2))); + Assert.Equal(nint.MinValue, Math.Min(nint.MinValue, nint.MaxValue)); + } + + [Fact] public static void Min_SByte() { Assert.Equal((sbyte)(-2), Math.Min((sbyte)3, (sbyte)(-2))); @@ -1272,6 +1302,13 @@ namespace System.Tests Assert.Equal(ulong.MinValue, Math.Min(ulong.MinValue, ulong.MaxValue)); } + [Fact] + public static void Min_NUInt() + { + Assert.Equal((nuint)2, Math.Min((nuint)3, (nuint)2)); + Assert.Equal(nuint.MinValue, Math.Min(nuint.MinValue, nuint.MaxValue)); + } + public static IEnumerable Pow_TestData { get @@ -1524,6 +1561,14 @@ namespace System.Tests } [Fact] + public static void Sign_NInt() + { + Assert.Equal(0, Math.Sign((nint)0)); + Assert.Equal(-1, Math.Sign((nint)(-3))); + Assert.Equal(1, Math.Sign((nint)3)); + } + + [Fact] public static void Sign_SByte() { Assert.Equal(0, Math.Sign((sbyte)0)); @@ -2388,6 +2433,21 @@ namespace System.Tests Assert.Equal(expected, Math.Clamp(value, min, max)); } + + [Theory] + [MemberData(nameof(Clamp_SignedInt_TestData))] + public static void Clamp_NInt(int value, int min, int max, int expected) + { + Assert.Equal((nint)expected, Math.Clamp((nint)value, (nint)min, (nint)max)); + } + + [Theory] + [MemberData(nameof(Clamp_UnsignedInt_TestData))] + public static void Clamp_NUInt(uint value, uint min, uint max, uint expected) + { + Assert.Equal((nuint)expected, Math.Clamp((nuint)value, (nuint)min, (nuint)max)); + } + [Theory] [MemberData(nameof(Clamp_SignedInt_TestData))] [InlineData(double.NegativeInfinity, double.NegativeInfinity, double.PositiveInfinity, double.NegativeInfinity)] @@ -2876,7 +2936,7 @@ namespace System.Tests Assert.Equal(-3, Math.Round(-3.0)); Assert.Equal( 4, Math.Round( 3.5)); Assert.Equal(-4, Math.Round(-3.5)); - + Assert.Equal( 0, Math.Round( 0.5, MidpointRounding.ToZero)); Assert.Equal( 0, Math.Round( 0.5, MidpointRounding.ToZero)); Assert.Equal( 1, Math.Round( 1.0, MidpointRounding.ToZero)); @@ -2925,7 +2985,7 @@ namespace System.Tests Assert.Equal(-3, MathF.Round(-3.0f)); Assert.Equal( 4, MathF.Round( 3.5f)); Assert.Equal(-4, MathF.Round(-3.5f)); - + Assert.Equal( 0, MathF.Round( 0.5f, MidpointRounding.ToZero)); Assert.Equal( 0, MathF.Round( 0.5f, MidpointRounding.ToZero)); Assert.Equal( 1, MathF.Round( 1.0f, MidpointRounding.ToZero)); diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 2282fe5..2691568 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -2655,6 +2655,7 @@ namespace System public static short Abs(short value) { throw null; } public static int Abs(int value) { throw null; } public static long Abs(long value) { throw null; } + public static nint Abs(nint value) { throw null; } [System.CLSCompliantAttribute(false)] public static sbyte Abs(sbyte value) { throw null; } public static float Abs(float value) { throw null; } @@ -2680,6 +2681,7 @@ namespace System public static short Clamp(short value, short min, short max) { throw null; } public static int Clamp(int value, int min, int max) { throw null; } public static long Clamp(long value, long min, long max) { throw null; } + public static nint Clamp(nint value, nint min, nint max) { throw null; } [System.CLSCompliantAttribute(false)] public static sbyte Clamp(sbyte value, sbyte min, sbyte max) { throw null; } public static float Clamp(float value, float min, float max) { throw null; } @@ -2689,24 +2691,26 @@ namespace System public static uint Clamp(uint value, uint min, uint max) { throw null; } [System.CLSCompliantAttribute(false)] public static ulong Clamp(ulong value, ulong min, ulong max) { throw null; } + [System.CLSCompliantAttribute(false)] + public static nuint Clamp(nuint value, nuint min, nuint max) { throw null; } public static double CopySign(double x, double y) { throw null; } public static double Cos(double d) { throw null; } public static double Cosh(double value) { throw null; } public static int DivRem(int a, int b, out int result) { throw null; } public static long DivRem(long a, long b, out long result) { throw null; } public static (byte Quotient, byte Remainder) DivRem(byte left, byte right) { throw null; } + public static (short Quotient, short Remainder) DivRem(short left, short right) { throw null; } + public static (int Quotient, int Remainder) DivRem(int left, int right) { throw null; } + public static (long Quotient, long Remainder) DivRem(long left, long right) { throw null; } + public static (nint Quotient, nint Remainder) DivRem(nint left, nint right) { throw null; } [System.CLSCompliantAttribute(false)] public static (sbyte Quotient, sbyte Remainder) DivRem(sbyte left, sbyte right) { throw null; } - public static (short Quotient, short Remainder) DivRem(short left, short right) { throw null; } [System.CLSCompliantAttribute(false)] public static (ushort Quotient, ushort Remainder) DivRem(ushort left, ushort right) { throw null; } - public static (int Quotient, int Remainder) DivRem(int left, int right) { throw null; } [System.CLSCompliantAttribute(false)] public static (uint Quotient, uint Remainder) DivRem(uint left, uint right) { throw null; } - public static (long Quotient, long Remainder) DivRem(long left, long right) { throw null; } [System.CLSCompliantAttribute(false)] public static (ulong Quotient, ulong Remainder) DivRem(ulong left, ulong right) { throw null; } - public static (nint Quotient, nint Remainder) DivRem(nint left, nint right) { throw null; } [System.CLSCompliantAttribute(false)] public static (nuint Quotient, nuint Remainder) DivRem(nuint left, nuint right) { throw null; } public static double Exp(double d) { throw null; } @@ -2725,6 +2729,7 @@ namespace System public static short Max(short val1, short val2) { throw null; } public static int Max(int val1, int val2) { throw null; } public static long Max(long val1, long val2) { throw null; } + public static nint Max(nint val1, nint val2) { throw null; } [System.CLSCompliantAttribute(false)] public static sbyte Max(sbyte val1, sbyte val2) { throw null; } public static float Max(float val1, float val2) { throw null; } @@ -2734,6 +2739,8 @@ namespace System public static uint Max(uint val1, uint val2) { throw null; } [System.CLSCompliantAttribute(false)] public static ulong Max(ulong val1, ulong val2) { throw null; } + [System.CLSCompliantAttribute(false)] + public static nuint Max(nuint val1, nuint val2) { throw null; } public static double MaxMagnitude(double x, double y) { throw null; } public static byte Min(byte val1, byte val2) { throw null; } public static decimal Min(decimal val1, decimal val2) { throw null; } @@ -2741,6 +2748,7 @@ namespace System public static short Min(short val1, short val2) { throw null; } public static int Min(int val1, int val2) { throw null; } public static long Min(long val1, long val2) { throw null; } + public static nint Min(nint val1, nint val2) { throw null; } [System.CLSCompliantAttribute(false)] public static sbyte Min(sbyte val1, sbyte val2) { throw null; } public static float Min(float val1, float val2) { throw null; } @@ -2750,6 +2758,8 @@ namespace System public static uint Min(uint val1, uint val2) { throw null; } [System.CLSCompliantAttribute(false)] public static ulong Min(ulong val1, ulong val2) { throw null; } + [System.CLSCompliantAttribute(false)] + public static nuint Min(nuint val1, nuint val2) { throw null; } public static double MinMagnitude(double x, double y) { throw null; } public static double Pow(double x, double y) { throw null; } public static decimal Round(decimal d) { throw null; } @@ -2766,6 +2776,7 @@ namespace System public static int Sign(short value) { throw null; } public static int Sign(int value) { throw null; } public static int Sign(long value) { throw null; } + public static int Sign(nint value) { throw null; } [System.CLSCompliantAttribute(false)] public static int Sign(sbyte value) { throw null; } public static int Sign(float value) { throw null; } -- 2.7.4