From 3c721174f1bec9ae22bd34ea479da0c5397a9124 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 10 Jul 2024 09:57:52 -0700 Subject: [PATCH] Ensure that `char` doesn't box when using generic math --- .../System.Private.CoreLib/src/System/Char.cs | 75 ++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs index 7df1b14afc0332..085ff51ef9051e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs @@ -1159,6 +1159,9 @@ public static int ConvertToUtf32(string s, int index) // IBinaryInteger // + /// + static (char Quotient, char Remainder) IBinaryInteger.DivRem(char left, char right) => ((char, char))Math.DivRem(left, right); + /// static char IBinaryInteger.LeadingZeroCount(char value) => (char)(BitOperations.LeadingZeroCount(value) - 16); @@ -1446,6 +1449,60 @@ bool IBinaryInteger.TryWriteLittleEndian(Span destination, out int b /// static char INumberBase.Abs(char value) => value; + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static char INumberBase.CreateChecked(TOther value) + { + char result; + + if (typeof(TOther) == typeof(char)) + { + result = (char)(object)value; + } + else if (!TryConvertFromChecked(value, out result) && !TOther.TryConvertToChecked(value, out result)) + { + ThrowHelper.ThrowNotSupportedException(); + } + + return result; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static char INumberBase.CreateSaturating(TOther value) + { + char result; + + if (typeof(TOther) == typeof(char)) + { + result = (char)(object)value; + } + else if (!TryConvertFromSaturating(value, out result) && !TOther.TryConvertToSaturating(value, out result)) + { + ThrowHelper.ThrowNotSupportedException(); + } + + return result; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static char INumberBase.CreateTruncating(TOther value) + { + char result; + + if (typeof(TOther) == typeof(char)) + { + result = (char)(object)value; + } + else if (!TryConvertFromTruncating(value, out result) && !TOther.TryConvertToTruncating(value, out result)) + { + ThrowHelper.ThrowNotSupportedException(); + } + + return result; + } + /// static bool INumberBase.IsCanonical(char value) => true; @@ -1518,7 +1575,11 @@ bool IBinaryInteger.TryWriteLittleEndian(Span destination, out int b /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertFromChecked(TOther value, out char result) + static bool INumberBase.TryConvertFromChecked(TOther value, out char result) => TryConvertFromChecked(value, out result); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryConvertFromChecked(TOther value, out char result) + where TOther : INumberBase { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1580,7 +1641,11 @@ static bool INumberBase.TryConvertFromChecked(TOther value, out ch /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertFromSaturating(TOther value, out char result) + static bool INumberBase.TryConvertFromSaturating(TOther value, out char result) => TryConvertFromSaturating(value, out result); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryConvertFromSaturating(TOther value, out char result) + where TOther : INumberBase { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and @@ -1643,7 +1708,11 @@ static bool INumberBase.TryConvertFromSaturating(TOther value, out /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - static bool INumberBase.TryConvertFromTruncating(TOther value, out char result) + static bool INumberBase.TryConvertFromTruncating(TOther value, out char result) => TryConvertFromTruncating(value, out result); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryConvertFromTruncating(TOther value, out char result) + where TOther : INumberBase { // In order to reduce overall code duplication and improve the inlinabilty of these // methods for the corelib types we have `ConvertFrom` handle the same sign and