diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
index 38a752c6810ffe..e22a12d24f6440 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
@@ -268,11 +268,11 @@ internal static partial class Number
300;
#endif
/// Lazily-populated cache of strings for uint values in the range [0, ).
- private static readonly string[] s_smallNumberCache = new string[SmallNumberCacheLength];
+ private static readonly string?[] s_smallNumberCache = new string[SmallNumberCacheLength];
// Optimizations using "TwoDigits" inspired by:
// https://engineering.fb.com/2013/03/15/developer-tools/three-optimization-tips-for-c/
- private static readonly byte[] TwoDigitsCharsAsBytes =
+ private static ReadOnlySpan TwoDigitsCharsAsBytes =>
MemoryMarshal.AsBytes("00010203040506070809" +
"10111213141516171819" +
"20212223242526272829" +
@@ -282,9 +282,9 @@ internal static partial class Number
"60616263646566676869" +
"70717273747576777879" +
"80818283848586878889" +
- "90919293949596979899").ToArray();
- private static readonly byte[] TwoDigitsBytes =
- ("00010203040506070809"u8 +
+ "90919293949596979899");
+ private static ReadOnlySpan TwoDigitsBytes =>
+ "00010203040506070809"u8 +
"10111213141516171819"u8 +
"20212223242526272829"u8 +
"30313233343536373839"u8 +
@@ -293,7 +293,7 @@ internal static partial class Number
"60616263646566676869"u8 +
"70717273747576777879"u8 +
"80818283848586878889"u8 +
- "90919293949596979899"u8).ToArray();
+ "90919293949596979899"u8;
public static unsafe string FormatDecimal(decimal value, ReadOnlySpan format, NumberFormatInfo info)
{
@@ -387,9 +387,8 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
int maxDigits = precision;
- switch (fmt)
+ switch (fmt | 0x20)
{
- case 'C':
case 'c':
{
// The currency format uses the precision specifier to indicate the number of
@@ -404,7 +403,6 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
break;
}
- case 'E':
case 'e':
{
// The exponential format uses the precision specifier to indicate the number of
@@ -423,9 +421,7 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
break;
}
- case 'F':
case 'f':
- case 'N':
case 'n':
{
// The fixed-point and number formats use the precision specifier to indicate the number
@@ -440,7 +436,6 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
break;
}
- case 'G':
case 'g':
{
// The general format uses the precision specifier to indicate the number of significant
@@ -457,7 +452,6 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
break;
}
- case 'P':
case 'p':
{
// The percent format uses the precision specifier to indicate the number of
@@ -476,7 +470,6 @@ private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int preci
break;
}
- case 'R':
case 'r':
{
// The roundtrip format ignores the precision specifier and always returns the shortest
@@ -1579,7 +1572,7 @@ internal static unsafe void WriteTwoDigits(uint value, TChar* ptr) where
Unsafe.CopyBlockUnaligned(
ref *(byte*)ptr,
- ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(typeof(TChar) == typeof(char) ? TwoDigitsCharsAsBytes : TwoDigitsBytes), (uint)sizeof(TChar) * 2 * value),
+ ref Unsafe.Add(ref MemoryMarshal.GetReference(typeof(TChar) == typeof(char) ? TwoDigitsCharsAsBytes : TwoDigitsBytes), (uint)sizeof(TChar) * 2 * value),
(uint)sizeof(TChar) * 2);
}
@@ -1595,7 +1588,7 @@ internal static unsafe void WriteFourDigits(uint value, TChar* ptr) where
(value, uint remainder) = Math.DivRem(value, 100);
- ref byte charsArray = ref MemoryMarshal.GetArrayDataReference(typeof(TChar) == typeof(char) ? TwoDigitsCharsAsBytes : TwoDigitsBytes);
+ ref byte charsArray = ref MemoryMarshal.GetReference(typeof(TChar) == typeof(char) ? TwoDigitsCharsAsBytes : TwoDigitsBytes);
Unsafe.CopyBlockUnaligned(
ref *(byte*)ptr,
@@ -1677,7 +1670,7 @@ internal static unsafe void WriteDigits(uint value, TChar* ptr, int count
return bufferEnd;
}
- internal static unsafe string UInt32ToDecStr(uint value)
+ internal static string UInt32ToDecStr(uint value)
{
// For small numbers, consult a lazily-populated cache.
if (value < SmallNumberCacheLength)
@@ -2540,102 +2533,6 @@ private static unsafe bool TryUInt128ToDecStr(UInt128 value, int digits,
return false;
}
- private static ulong ExtractFractionAndBiasedExponent(double value, out int exponent)
- {
- ulong bits = BitConverter.DoubleToUInt64Bits(value);
- ulong fraction = (bits & 0xFFFFFFFFFFFFF);
- exponent = ((int)(bits >> 52) & 0x7FF);
-
- if (exponent != 0)
- {
- // For normalized value, according to https://en.wikipedia.org/wiki/Double-precision_floating-point_format
- // value = 1.fraction * 2^(exp - 1023)
- // = (1 + mantissa / 2^52) * 2^(exp - 1023)
- // = (2^52 + mantissa) * 2^(exp - 1023 - 52)
- //
- // So f = (2^52 + mantissa), e = exp - 1075;
-
- fraction |= (1UL << 52);
- exponent -= 1075;
- }
- else
- {
- // For denormalized value, according to https://en.wikipedia.org/wiki/Double-precision_floating-point_format
- // value = 0.fraction * 2^(1 - 1023)
- // = (mantissa / 2^52) * 2^(-1022)
- // = mantissa * 2^(-1022 - 52)
- // = mantissa * 2^(-1074)
- // So f = mantissa, e = -1074
- exponent = -1074;
- }
-
- return fraction;
- }
-
- private static ushort ExtractFractionAndBiasedExponent(Half value, out int exponent)
- {
- ushort bits = BitConverter.HalfToUInt16Bits(value);
- ushort fraction = (ushort)(bits & 0x3FF);
- exponent = ((int)(bits >> 10) & 0x1F);
-
- if (exponent != 0)
- {
- // For normalized value, according to https://en.wikipedia.org/wiki/Half-precision_floating-point_format
- // value = 1.fraction * 2^(exp - 15)
- // = (1 + mantissa / 2^10) * 2^(exp - 15)
- // = (2^10 + mantissa) * 2^(exp - 15 - 10)
- //
- // So f = (2^10 + mantissa), e = exp - 25;
-
- fraction |= (ushort)(1U << 10);
- exponent -= 25;
- }
- else
- {
- // For denormalized value, according to https://en.wikipedia.org/wiki/Half-precision_floating-point_format
- // value = 0.fraction * 2^(1 - 15)
- // = (mantissa / 2^10) * 2^(-14)
- // = mantissa * 2^(-14 - 10)
- // = mantissa * 2^(-24)
- // So f = mantissa, e = -24
- exponent = -24;
- }
-
- return fraction;
- }
-
- private static uint ExtractFractionAndBiasedExponent(float value, out int exponent)
- {
- uint bits = BitConverter.SingleToUInt32Bits(value);
- uint fraction = (bits & 0x7FFFFF);
- exponent = ((int)(bits >> 23) & 0xFF);
-
- if (exponent != 0)
- {
- // For normalized value, according to https://en.wikipedia.org/wiki/Single-precision_floating-point_format
- // value = 1.fraction * 2^(exp - 127)
- // = (1 + mantissa / 2^23) * 2^(exp - 127)
- // = (2^23 + mantissa) * 2^(exp - 127 - 23)
- //
- // So f = (2^23 + mantissa), e = exp - 150;
-
- fraction |= (1U << 23);
- exponent -= 150;
- }
- else
- {
- // For denormalized value, according to https://en.wikipedia.org/wiki/Single-precision_floating-point_format
- // value = 0.fraction * 2^(1 - 127)
- // = (mantissa / 2^23) * 2^(-126)
- // = mantissa * 2^(-126 - 23)
- // = mantissa * 2^(-149)
- // So f = mantissa, e = -149
- exponent = -149;
- }
-
- return fraction;
- }
-
private static ulong ExtractFractionAndBiasedExponent(TNumber value, out int exponent)
where TNumber : unmanaged, IBinaryFloatParseAndFormatInfo
{