diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Rc2CbcParameters.manual.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Rc2CbcParameters.manual.cs index 8ab8093c29e677..eade371efe4f63 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Rc2CbcParameters.manual.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Rc2CbcParameters.manual.cs @@ -12,7 +12,7 @@ namespace System.Security.Cryptography.Asn1 // smallest supported by .NET that's not really a problem. internal partial struct Rc2CbcParameters { - private static readonly byte[] s_rc2EkbEncoding = + private static ReadOnlySpan Rc2EkbEncoding => new byte[] { 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0, 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, @@ -34,26 +34,16 @@ internal partial struct Rc2CbcParameters internal Rc2CbcParameters(ReadOnlyMemory iv, int keySize) { - if (keySize > byte.MaxValue) - { - Rc2Version = keySize; - } - else - { - Rc2Version = s_rc2EkbEncoding[keySize]; - } + Rc2Version = keySize > byte.MaxValue ? + keySize : + Rc2EkbEncoding[keySize]; Iv = iv; } - internal int GetEffectiveKeyBits() - { - if (Rc2Version > byte.MaxValue) - { - return Rc2Version; - } - - return Array.IndexOf(s_rc2EkbEncoding, (byte)Rc2Version); - } + internal int GetEffectiveKeyBits() => + Rc2Version > byte.MaxValue ? + Rc2Version : + Rc2EkbEncoding.IndexOf((byte)Rc2Version); } } diff --git a/src/libraries/Common/src/System/Security/IdentityHelper.cs b/src/libraries/Common/src/System/Security/IdentityHelper.cs index 9ce528a47c347f..5f60a8758d99d6 100644 --- a/src/libraries/Common/src/System/Security/IdentityHelper.cs +++ b/src/libraries/Common/src/System/Security/IdentityHelper.cs @@ -15,14 +15,6 @@ namespace System.Security /// internal static class IdentityHelper { - private static readonly char[] s_base32Char = - { - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5' - }; - /// /// Gives a hash equivalent to what Url.Normalize() gives. /// @@ -95,6 +87,7 @@ internal static string ToBase32StringSuitableForDirName(byte[] buff) // Create l chars using the last 5 bits of each byte. // Consume 3 MSB bits 5 bytes at a time. + ReadOnlySpan base32Chars = "abcdefghijklmnopqrstuvwxyz012345"u8; do { byte b0 = (i < l) ? buff[i++] : (byte)0; @@ -104,18 +97,18 @@ internal static string ToBase32StringSuitableForDirName(byte[] buff) byte b4 = (i < l) ? buff[i++] : (byte)0; // Consume the 5 Least significant bits of each byte - sb.Append(s_base32Char[b0 & 0x1F]); - sb.Append(s_base32Char[b1 & 0x1F]); - sb.Append(s_base32Char[b2 & 0x1F]); - sb.Append(s_base32Char[b3 & 0x1F]); - sb.Append(s_base32Char[b4 & 0x1F]); + sb.Append((char)base32Chars[b0 & 0x1F]); + sb.Append((char)base32Chars[b1 & 0x1F]); + sb.Append((char)base32Chars[b2 & 0x1F]); + sb.Append((char)base32Chars[b3 & 0x1F]); + sb.Append((char)base32Chars[b4 & 0x1F]); // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4 - sb.Append(s_base32Char[( + sb.Append((char)base32Chars[( ((b0 & 0xE0) >> 5) | ((b3 & 0x60) >> 2))]); - sb.Append(s_base32Char[( + sb.Append((char)base32Chars[( ((b1 & 0xE0) >> 5) | ((b4 & 0x60) >> 2))]); @@ -130,7 +123,7 @@ internal static string ToBase32StringSuitableForDirName(byte[] buff) if ((b4 & 0x80) != 0) b2 |= 0x10; - sb.Append(s_base32Char[b2]); + sb.Append((char)base32Chars[b2]); } while (i < l); diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs index 86e290eadf6d85..1b9ca9c078c4a3 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs @@ -36,8 +36,6 @@ public struct SqlDateTime : INullable, IComparable, IXmlSerializable, IEquatable public static readonly int SQLTicksPerHour = SQLTicksPerMinute * 60; private static readonly int s_SQLTicksPerDay = SQLTicksPerHour * 24; - private const long s_ticksPerSecond = TimeSpan.TicksPerMillisecond * 1000; - private static readonly DateTime s_SQLBaseDate = new DateTime(1900, 1, 1); private static readonly long s_SQLBaseDateTicks = s_SQLBaseDate.Ticks; @@ -51,17 +49,14 @@ public struct SqlDateTime : INullable, IComparable, IXmlSerializable, IEquatable private const int s_dayBase = 693595; // Jan 1 1900 is this many days from Jan 1 0001 - - private static readonly int[] s_daysToMonth365 = new int[] { + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; - private static readonly int[] s_daysToMonth366 = new int[] { + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; - private static readonly DateTime s_minDateTime = new DateTime(1753, 1, 1); - private static readonly DateTime s_maxDateTime = DateTime.MaxValue; - private static readonly TimeSpan s_minTimeSpan = s_minDateTime.Subtract(s_SQLBaseDate); - private static readonly TimeSpan s_maxTimeSpan = s_maxDateTime.Subtract(s_SQLBaseDate); - private const string s_ISO8601_DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fff"; + private static readonly TimeSpan s_minTimeSpan = new DateTime(1753, 1, 1).Subtract(s_SQLBaseDate); + private static readonly TimeSpan s_maxTimeSpan = DateTime.MaxValue.Subtract(s_SQLBaseDate); + private const string ISO8601_DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fff"; // These formats are valid styles in SQL Server (style 9, 12, 13, 14) // but couldn't be recognized by the default parse. Needs to call @@ -105,7 +100,9 @@ public SqlDateTime(int year, int month, int day, int hour, int minute, int secon { if (year >= s_minYear && year <= s_maxYear && month >= 1 && month <= 12) { - int[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = IsLeapYear(year) ? + DaysToMonth366 : + DaysToMonth365; if (day >= 1 && day <= days[month] - days[month - 1]) { int y = year - 1; @@ -670,7 +667,7 @@ void IXmlSerializable.WriteXml(XmlWriter writer) } else { - writer.WriteString(XmlConvert.ToString(Value, s_ISO8601_DateTimeFormat)); + writer.WriteString(XmlConvert.ToString(Value, ISO8601_DateTimeFormat)); } } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs index 23a37786006e8c..79bb3d871a31b4 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs @@ -71,7 +71,7 @@ public struct SqlDecimal : INullable, IComparable, IXmlSerializable, IEquatable< private const byte s_cNumeDivScaleMin = 6; // Minimum result scale of numeric division // Array of multipliers for lAdjust and Ceiling/Floor. - private static readonly uint[] s_rgulShiftBase = new uint[9] { + private static ReadOnlySpan RgulShiftBase => new uint[9] { 10, 10 * 10, 10 * 10 * 10, @@ -130,7 +130,7 @@ public static void CreateDecimalHelperTable() #endregion #region DecimalHelperTable - private static readonly uint[] s_decimalHelpersLo = { + private static ReadOnlySpan DecimalHelpersLo => new uint[] { 0x0000000a, // precision:2, value:10 0x00000064, // precision:3, value:100 0x000003e8, // precision:4, value:1000 @@ -171,7 +171,7 @@ public static void CreateDecimalHelperTable() 0x00000000, // precision:38+1, value:99999999999999999999999999999999999999+1 }; - private static readonly uint[] s_decimalHelpersMid = { + private static ReadOnlySpan DecimalHelpersMid => new uint[] { 0x00000000, // precision:2, value:10 0x00000000, // precision:3, value:100 0x00000000, // precision:4, value:1000 @@ -212,7 +212,7 @@ public static void CreateDecimalHelperTable() 0x098a2240, // precision:38+1, value:99999999999999999999999999999999999999+1 }; - private static readonly uint[] s_decimalHelpersHi = { + private static ReadOnlySpan DecimalHelpersHi => new uint[] { 0x00000000, // precision:2, value:10 0x00000000, // precision:3, value:100 0x00000000, // precision:4, value:1000 @@ -253,7 +253,7 @@ public static void CreateDecimalHelperTable() 0x5a86c47a, // precision:38+1, value:99999999999999999999999999999999999999+1 }; - private static readonly uint[] s_decimalHelpersHiHi = { + private static ReadOnlySpan DecimalHelpersHiHi => new uint[] { 0x00000000, // precision:2, value:10 0x00000000, // precision:3, value:100 0x00000000, // precision:4, value:1000 @@ -313,31 +313,31 @@ private byte CalculatePrecision() { int tableIndex; byte precision; - uint[] decimalHelpers; + ReadOnlySpan decimalHelpers; uint decimalPart; if (_data4 != 0) { tableIndex = HelperTableStartIndexHiHi; - decimalHelpers = s_decimalHelpersHiHi; + decimalHelpers = DecimalHelpersHiHi; decimalPart = _data4; } else if (_data3 != 0) { tableIndex = HelperTableStartIndexHi; - decimalHelpers = s_decimalHelpersHi; + decimalHelpers = DecimalHelpersHi; decimalPart = _data3; } else if (_data2 != 0) { tableIndex = HelperTableStartIndexMid; - decimalHelpers = s_decimalHelpersMid; + decimalHelpers = DecimalHelpersMid; decimalPart = _data2; } else { tableIndex = HelperTableStartIndexLo; - decimalHelpers = s_decimalHelpersLo; + decimalHelpers = DecimalHelpersLo; decimalPart = _data1; } @@ -429,25 +429,25 @@ private bool VerifyPrecision(byte precision) Debug.Assert(precision <= MaxPrecision, "Precision > MaxPrecision"); int tableIndex = checked((precision - 1)); - if (_data4 < s_decimalHelpersHiHi[tableIndex]) + if (_data4 < DecimalHelpersHiHi[tableIndex]) { return true; } - else if (_data4 == s_decimalHelpersHiHi[tableIndex]) + else if (_data4 == DecimalHelpersHiHi[tableIndex]) { - if (_data3 < s_decimalHelpersHi[tableIndex]) + if (_data3 < DecimalHelpersHi[tableIndex]) { return true; } - else if (_data3 == s_decimalHelpersHi[tableIndex]) + else if (_data3 == DecimalHelpersHi[tableIndex]) { - if (_data2 < s_decimalHelpersMid[tableIndex]) + if (_data2 < DecimalHelpersMid[tableIndex]) { return true; } - else if (_data2 == s_decimalHelpersMid[tableIndex]) + else if (_data2 == DecimalHelpersMid[tableIndex]) { - if (_data1 < s_decimalHelpersLo[tableIndex]) + if (_data1 < DecimalHelpersLo[tableIndex]) { return true; } @@ -754,9 +754,9 @@ public SqlDecimal(double dVal) : this(false) { ulLenDelta = (ulLen >= 9) ? 9 : ulLen; - dFrac *= s_rgulShiftBase[(int)ulLenDelta - 1]; + dFrac *= RgulShiftBase[(int)ulLenDelta - 1]; ulLen -= ulLenDelta; - MultByULong(s_rgulShiftBase[(int)ulLenDelta - 1]); + MultByULong(RgulShiftBase[(int)ulLenDelta - 1]); AddULong((uint)dFrac); dFrac -= Math.Floor(dFrac); } @@ -1542,12 +1542,12 @@ public static explicit operator decimal(SqlDecimal x) { if (lScaleAdjust <= -9) { - ulShiftBase = s_rgulShiftBase[8]; + ulShiftBase = RgulShiftBase[8]; lScaleAdjust += 9; } else { - ulShiftBase = s_rgulShiftBase[-lScaleAdjust - 1]; + ulShiftBase = RgulShiftBase[-lScaleAdjust - 1]; lScaleAdjust = 0; } MpDiv1(rgulRes, ref culRes, ulShiftBase, out ulRem); @@ -2304,12 +2304,12 @@ internal void AdjustScale(int digits, bool fRound) //if lAdjust>=9, downshift by 10^9 each time, otherwise by the full amount if (lAdjust >= 9) { - ulShiftBase = s_rgulShiftBase[8]; + ulShiftBase = RgulShiftBase[8]; lAdjust -= 9; } else { - ulShiftBase = s_rgulShiftBase[lAdjust - 1]; + ulShiftBase = RgulShiftBase[lAdjust - 1]; lAdjust = 0; } MultByULong(ulShiftBase); @@ -2321,12 +2321,12 @@ internal void AdjustScale(int digits, bool fRound) { if (lAdjust <= -9) { - ulShiftBase = s_rgulShiftBase[8]; + ulShiftBase = RgulShiftBase[8]; lAdjust += 9; } else { - ulShiftBase = s_rgulShiftBase[-lAdjust - 1]; + ulShiftBase = RgulShiftBase[-lAdjust - 1]; lAdjust = 0; } ulRem = DivByULong(ulShiftBase); @@ -3051,12 +3051,12 @@ private void MakeInteger(out bool fFraction) { if (iAdjust >= 9) { - ulRem = DivByULong(s_rgulShiftBase[8]); + ulRem = DivByULong(RgulShiftBase[8]); iAdjust -= 9; } else { - ulRem = DivByULong(s_rgulShiftBase[iAdjust - 1]); + ulRem = DivByULong(RgulShiftBase[iAdjust - 1]); iAdjust = 0; } @@ -3189,14 +3189,14 @@ private static SqlDecimal Round(SqlDecimal n, int lPosition, bool fTruncate) { if (lAdjust >= 9) { - ulRem = n.DivByULong(s_rgulShiftBase[8]); - ulLastDivBase = s_rgulShiftBase[8]; + ulRem = n.DivByULong(RgulShiftBase[8]); + ulLastDivBase = RgulShiftBase[8]; lAdjust -= 9; } else { - ulRem = n.DivByULong(s_rgulShiftBase[lAdjust - 1]); - ulLastDivBase = s_rgulShiftBase[lAdjust - 1]; + ulRem = n.DivByULong(RgulShiftBase[lAdjust - 1]); + ulLastDivBase = RgulShiftBase[lAdjust - 1]; lAdjust = 0; } } diff --git a/src/libraries/System.Drawing.Primitives/src/System/Drawing/KnownColorTable.cs b/src/libraries/System.Drawing.Primitives/src/System/Drawing/KnownColorTable.cs index 281f246d13ade8..3ec5d7ab825cb6 100644 --- a/src/libraries/System.Drawing.Primitives/src/System/Drawing/KnownColorTable.cs +++ b/src/libraries/System.Drawing.Primitives/src/System/Drawing/KnownColorTable.cs @@ -12,7 +12,7 @@ internal static class KnownColorTable public const byte KnownColorKindUnknown = 2; // All known color values (in order of definition in the KnownColor enum). - public static readonly uint[] s_colorValueTable = new uint[] + public static ReadOnlySpan ColorValueTable => new uint[] { // "not a known color" 0, @@ -466,11 +466,12 @@ internal static class KnownColorTable internal static Color ArgbToKnownColor(uint argb) { Debug.Assert((argb & Color.ARGBAlphaMask) == Color.ARGBAlphaMask); - Debug.Assert(s_colorValueTable.Length == ColorKindTable.Length); + Debug.Assert(ColorValueTable.Length == ColorKindTable.Length); - for (int index = 1; index < s_colorValueTable.Length; ++index) + ReadOnlySpan colorValueTable = ColorValueTable; + for (int index = 1; index < colorValueTable.Length; ++index) { - if (ColorKindTable[index] == KnownColorKindWeb && s_colorValueTable[index] == argb) + if (ColorKindTable[index] == KnownColorKindWeb && colorValueTable[index] == argb) { return Color.FromKnownColor((KnownColor)index); } @@ -486,7 +487,7 @@ public static uint KnownColorToArgb(KnownColor color) return ColorKindTable[(int)color] == KnownColorKindSystem ? GetSystemColorArgb(color) - : s_colorValueTable[(int)color]; + : ColorValueTable[(int)color]; } #if FEATURE_WINDOWS_SYSTEM_COLORS @@ -494,14 +495,14 @@ public static uint GetSystemColorArgb(KnownColor color) { Debug.Assert(Color.IsKnownColorSystem(color)); - return ColorTranslator.COLORREFToARGB(Interop.User32.GetSysColor((byte)s_colorValueTable[(int)color])); + return ColorTranslator.COLORREFToARGB(Interop.User32.GetSysColor((byte)ColorValueTable[(int)color])); } #else public static uint GetSystemColorArgb(KnownColor color) { Debug.Assert(Color.IsKnownColorSystem(color)); - return s_colorValueTable[(int)color]; + return ColorValueTable[(int)color]; } #endif } diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs index 4dce72fb505a8e..fd75b5ac0213cb 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs @@ -18,7 +18,7 @@ internal sealed class InflaterManaged // The base length for length code 257 - 285. // The formula to get the real length for a length code is lengthBase[code - 257] + (value stored in extraBits) - private static readonly int[] s_lengthBase = + private static ReadOnlySpan LengthBase => new byte[] { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3 @@ -26,7 +26,7 @@ internal sealed class InflaterManaged // The base distance for distance code 0 - 31 // The real distance for a distance code is distanceBasePosition[code] + (value stored in extraBits) - private static readonly int[] s_distanceBasePosition = + private static ReadOnlySpan DistanceBasePosition => new ushort[] { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153 @@ -410,11 +410,11 @@ private bool DecodeBlock(out bool end_of_block_code_seen) return false; } - if (_length < 0 || _length >= s_lengthBase.Length) + if (_length < 0 || _length >= LengthBase.Length) { throw new InvalidDataException(SR.GenericInvalidData); } - _length = s_lengthBase[_length] + bits; + _length = LengthBase[_length] + bits; } _state = InflaterState.HaveFullLength; goto case InflaterState.HaveFullLength; @@ -456,7 +456,7 @@ private bool DecodeBlock(out bool end_of_block_code_seen) { return false; } - offset = s_distanceBasePosition[_distanceCode] + bits; + offset = DistanceBasePosition[_distanceCode] + bits; } else { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs index 7557ece3e264e0..d5199afc6deb50 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs @@ -480,7 +480,7 @@ public void OnWindowUpdate(int amount) private const int FirstHPackNormalHeaderId = 15; private const int LastHPackNormalHeaderId = 61; - private static readonly int[] s_hpackStaticStatusCodeTable = new int[LastHPackStatusPseudoHeaderId - FirstHPackStatusPseudoHeaderId + 1] { 200, 204, 206, 304, 400, 404, 500 }; + private static ReadOnlySpan HpackStaticStatusCodeTable => new int[LastHPackStatusPseudoHeaderId - FirstHPackStatusPseudoHeaderId + 1] { 200, 204, 206, 304, 400, 404, 500 }; private static readonly (HeaderDescriptor descriptor, byte[] value)[] s_hpackStaticHeaderTable = new (HeaderDescriptor, byte[])[LastHPackNormalHeaderId - FirstHPackNormalHeaderId + 1] { @@ -544,7 +544,7 @@ void IHttpStreamHeadersHandler.OnStaticIndexedHeader(int index) } else if (index <= LastHPackStatusPseudoHeaderId) { - int statusCode = s_hpackStaticStatusCodeTable[index - FirstHPackStatusPseudoHeaderId]; + int statusCode = HpackStaticStatusCodeTable[index - FirstHPackStatusPseudoHeaderId]; OnStatus(statusCode); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Helpers.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Helpers.cs index 8dcea70dbf14e0..763aa4d9711ae4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Helpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Helpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Globalization; namespace System.Buffers.Text { @@ -144,7 +145,7 @@ private static bool TryCreateDateTime(int year, int month, int day, int hour, in Debug.Assert(fraction >= 0 && fraction <= Utf8Constants.MaxDateTimeFraction); // All of our callers to date parse the fraction from fixed 7-digit fields so this value is trusted. - int[] days = DateTime.IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = DateTime.IsLeapYear(year) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365; int yearMinusOne = year - 1; int totalDays = (yearMinusOne * 365) + (yearMinusOne / 4) - (yearMinusOne / 100) + (yearMinusOne / 400) + days[month - 1] + day - 1; long ticks = totalDays * TimeSpan.TicksPerDay; @@ -154,8 +155,5 @@ private static bool TryCreateDateTime(int year, int month, int day, int hour, in value = new DateTime(ticks: ticks, kind: kind); return true; } - - private static readonly int[] s_daysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly int[] s_daysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Convert.cs b/src/libraries/System.Private.CoreLib/src/System/Convert.cs index 6899925d140b39..880bc2f6599ef8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Convert.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Convert.cs @@ -102,8 +102,6 @@ public static partial class Convert // Need to special case Enum because typecode will be underlying type, e.g. Int32 private static readonly Type EnumType = typeof(Enum); - internal const string Base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - private const int Base64LineBreakPosition = 76; private const int Base64VectorizationLengthThreshold = 16; @@ -2535,8 +2533,8 @@ private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int // Convert three bytes at a time to base64 notation. This will consume 4 chars. int i; - // get a pointer to the Base64Table to avoid unnecessary range checking - fixed (char* base64 = Base64Table) + // get a pointer to the base64 table to avoid unnecessary range checking + fixed (byte* base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="u8) { for (i = offset; i < calcLength; i += 3) { @@ -2550,10 +2548,10 @@ private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int } charcount += 4; } - outChars[j] = base64[(inData[i] & 0xfc) >> 2]; - outChars[j + 1] = base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)]; - outChars[j + 2] = base64[((inData[i + 1] & 0x0f) << 2) | ((inData[i + 2] & 0xc0) >> 6)]; - outChars[j + 3] = base64[inData[i + 2] & 0x3f]; + outChars[j] = (char)base64[(inData[i] & 0xfc) >> 2]; + outChars[j + 1] = (char)base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)]; + outChars[j + 2] = (char)base64[((inData[i + 1] & 0x0f) << 2) | ((inData[i + 2] & 0xc0) >> 6)]; + outChars[j + 3] = (char)base64[inData[i + 2] & 0x3f]; j += 4; } @@ -2569,17 +2567,17 @@ private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int switch (lengthmod3) { case 2: // One character padding needed - outChars[j] = base64[(inData[i] & 0xfc) >> 2]; - outChars[j + 1] = base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)]; - outChars[j + 2] = base64[(inData[i + 1] & 0x0f) << 2]; - outChars[j + 3] = base64[64]; // Pad + outChars[j] = (char)base64[(inData[i] & 0xfc) >> 2]; + outChars[j + 1] = (char)base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)]; + outChars[j + 2] = (char)base64[(inData[i + 1] & 0x0f) << 2]; + outChars[j + 3] = (char)base64[64]; // Pad j += 4; break; case 1: // Two character padding needed - outChars[j] = base64[(inData[i] & 0xfc) >> 2]; - outChars[j + 1] = base64[(inData[i] & 0x03) << 4]; - outChars[j + 2] = base64[64]; // Pad - outChars[j + 3] = base64[64]; // Pad + outChars[j] = (char)base64[(inData[i] & 0xfc) >> 2]; + outChars[j + 1] = (char)base64[(inData[i] & 0x03) << 4]; + outChars[j + 2] = (char)base64[64]; // Pad + outChars[j + 3] = (char)base64[64]; // Pad j += 4; break; } diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs index 1b72fccb3f4ec7..e435255365e8f4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs @@ -109,7 +109,7 @@ private static unsafe ulong ToFileTimeLeapSecondsAware(long ticks) private static DateTime CreateDateTimeFromSystemTime(in Interop.Kernel32.SYSTEMTIME time, ulong hundredNanoSecond) { uint year = time.Year; - uint[] days = IsLeapYear((int)year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = IsLeapYear((int)year) ? DaysToMonth366 : DaysToMonth365; int month = time.Month - 1; uint n = DaysToYear(year) + days[month] + time.Day - 1; ulong ticks = n * (ulong)TicksPerDay; diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs index 0f56dbaaeb58f7..e47533c785c8fa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs @@ -120,9 +120,9 @@ public readonly partial struct DateTime private const ulong TicksPer6Hours = TicksPerHour * 6; private const int March1BasedDayOfNewYear = 306; // Days between March 1 and January 1 - private static readonly uint[] s_daysToMonth365 = { + internal static ReadOnlySpan DaysToMonth365 => new uint[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly uint[] s_daysToMonth366 = { + internal static ReadOnlySpan DaysToMonth366 => new uint[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; private static ReadOnlySpan DaysInMonth365 => new byte[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; @@ -953,7 +953,7 @@ public DateTime AddMonths(int months) y += q; m -= q * 12; if (y < 1 || y > 9999) ThrowDateArithmetic(2); - uint[] daysTo = IsLeapYear(y) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan daysTo = IsLeapYear(y) ? DaysToMonth366 : DaysToMonth365; uint daysToMonth = daysTo[m - 1]; int days = (int)(daysTo[m] - daysToMonth); if (d > days) d = days; @@ -1016,12 +1016,12 @@ public DateTime AddYears(int value) int m = month - 1, d = day - 1; if (IsLeapYear(y)) { - n += s_daysToMonth366[m]; + n += DaysToMonth366[m]; } else { if (d == 28 && m == 1) d--; - n += s_daysToMonth365[m]; + n += DaysToMonth365[m]; } n += (uint)d; return new DateTime(n * (ulong)TicksPerDay + UTicks % TicksPerDay | InternalKind); @@ -1071,7 +1071,7 @@ private static ulong DateToTicks(int year, int month, int day) ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay(); } - uint[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365; if ((uint)day > days[month] - days[month - 1]) { ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay(); @@ -1952,7 +1952,7 @@ internal static bool TryCreate(int year, int month, int day, int hour, int minut return false; } - uint[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365; if ((uint)day > days[month] - days[month - 1]) { return false; diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs index 1a5834c08d42fb..03d4943b493c4d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs @@ -101,7 +101,7 @@ private ulong Low64 private const int MaxInt64Scale = 19; // Fast access for 10^n where n is 0-9 - private static readonly uint[] s_powers10 = new uint[] { + private static ReadOnlySpan UInt32Powers10 => new uint[] { 1, 10, 100, @@ -115,7 +115,7 @@ private ulong Low64 }; // Fast access for 10^n where n is 1-19 - private static readonly ulong[] s_ulongPowers10 = new ulong[] { + private static ReadOnlySpan UInt64Powers10 => new ulong[] { 10, 100, 1000, @@ -137,7 +137,7 @@ private ulong Low64 10000000000000000000, }; - private static readonly double[] s_doublePowers10 = new double[] { + private static ReadOnlySpan DoublePowers10 => new double[] { 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, @@ -931,7 +931,7 @@ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign) { if (scale <= MaxInt32Scale) { - low64 = UInt32x32To64((uint)low64, s_powers10[scale]); + low64 = UInt32x32To64((uint)low64, UInt32Powers10[scale]); goto AlignedAdd; } scale -= MaxInt32Scale; @@ -943,7 +943,7 @@ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign) { power = TenToPowerNine; if (scale < MaxInt32Scale) - power = s_powers10[scale]; + power = UInt32Powers10[scale]; tmpLow = UInt32x32To64((uint)low64, power); tmp64 = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32); low64 = (uint)tmpLow + (tmp64 << 32); @@ -959,7 +959,7 @@ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign) // power = TenToPowerNine; if (scale < MaxInt32Scale) - power = s_powers10[scale]; + power = UInt32Powers10[scale]; tmpLow = UInt32x32To64((uint)low64, power); tmp64 = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32); low64 = (uint)tmpLow + (tmp64 << 32); @@ -990,7 +990,7 @@ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign) { power = TenToPowerNine; if (scale < MaxInt32Scale) - power = s_powers10[scale]; + power = UInt32Powers10[scale]; tmp64 = 0; uint* rgulNum = (uint*)&bufNum; for (uint cur = 0; ;) @@ -1198,7 +1198,7 @@ internal static long VarCyFromDec(ref DecCalc pdecIn) { if (pdecIn.High != 0) goto ThrowOverflow; - uint pwr = s_powers10[-scale]; + uint pwr = UInt32Powers10[-scale]; ulong high = UInt32x32To64(pwr, pdecIn.Mid); if (high > uint.MaxValue) goto ThrowOverflow; @@ -1286,7 +1286,7 @@ private static int VarDecCmpSub(in decimal d1, in decimal d2) // Scaling loop, up to 10^9 at a time. do { - uint power = scale >= MaxInt32Scale ? TenToPowerNine : s_powers10[scale]; + uint power = scale >= MaxInt32Scale ? TenToPowerNine : UInt32Powers10[scale]; ulong tmpLow = UInt32x32To64((uint)low64, power); ulong tmp = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32); low64 = (uint)tmpLow + (tmp << 32); @@ -1345,7 +1345,7 @@ internal static unsafe void VarDecMul(ref DecCalc d1, ref DecCalc d2) goto ReturnZero; scale -= DEC_SCALE_MAX + 1; - ulong power = s_ulongPowers10[scale]; + ulong power = UInt64Powers10[scale]; // TODO: https://github.com/dotnet/runtime/issues/5213 tmp = low64 / power; @@ -1562,12 +1562,12 @@ internal static void VarDecFromR4(float input, out DecCalc result) if (power > DEC_SCALE_MAX) power = DEC_SCALE_MAX; - dbl *= s_doublePowers10[power]; + dbl *= DoublePowers10[power]; } else { if (power != -1 || dbl >= 1E7) - dbl /= s_doublePowers10[-power]; + dbl /= DoublePowers10[-power]; else power = 0; // didn't scale it } @@ -1604,7 +1604,7 @@ internal static void VarDecFromR4(float input, out DecCalc result) power = -power; if (power < 10) { - result.Low64 = UInt32x32To64(mant, s_powers10[power]); + result.Low64 = UInt32x32To64(mant, UInt32Powers10[power]); } else { @@ -1612,12 +1612,12 @@ internal static void VarDecFromR4(float input, out DecCalc result) // if (power > 18) { - ulong low64 = UInt32x32To64(mant, s_powers10[power - 18]); + ulong low64 = UInt32x32To64(mant, UInt32Powers10[power - 18]); UInt64x64To128(low64, TenToPowerEighteen, ref result); } else { - ulong low64 = UInt32x32To64(mant, s_powers10[power - 9]); + ulong low64 = UInt32x32To64(mant, UInt32Powers10[power - 9]); ulong hi64 = UInt32x32To64(TenToPowerNine, (uint)(low64 >> 32)); low64 = UInt32x32To64(TenToPowerNine, (uint)low64); result.Low = (uint)low64; @@ -1729,12 +1729,12 @@ internal static void VarDecFromR8(double input, out DecCalc result) if (power > DEC_SCALE_MAX) power = DEC_SCALE_MAX; - dbl *= s_doublePowers10[power]; + dbl *= DoublePowers10[power]; } else { if (power != -1 || dbl >= 1E15) - dbl /= s_doublePowers10[-power]; + dbl /= DoublePowers10[-power]; else power = 0; // didn't scale it } @@ -1771,7 +1771,7 @@ internal static void VarDecFromR8(double input, out DecCalc result) power = -power; if (power < 10) { - uint pow10 = s_powers10[power]; + uint pow10 = UInt32Powers10[power]; ulong low64 = UInt32x32To64((uint)mant, pow10); ulong hi64 = UInt32x32To64((uint)(mant >> 32), pow10); result.Low = (uint)low64; @@ -1785,7 +1785,7 @@ internal static void VarDecFromR8(double input, out DecCalc result) // Have a big power of 10. // Debug.Assert(power <= 14); - UInt64x64To128(mant, s_ulongPowers10[power - 1], ref result); + UInt64x64To128(mant, UInt64Powers10[power - 1], ref result); } } else @@ -1873,7 +1873,7 @@ internal static double VarR8FromDec(in decimal value) const double ds2to64 = 1.8446744073709552e+019; double dbl = ((double)value.Low64 + - (double)value.High * ds2to64) / s_doublePowers10[value.Scale]; + (double)value.High * ds2to64) / DoublePowers10[value.Scale]; if (decimal.IsNegative(value)) dbl = -dbl; @@ -1971,7 +1971,7 @@ internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2) } HaveScale: - power = s_powers10[curScale]; + power = UInt32Powers10[curScale]; scale += curScale; if (IncreaseScale(ref bufQuo, power) != 0) @@ -2053,7 +2053,7 @@ internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2) } HaveScale64: - power = s_powers10[curScale]; + power = UInt32Powers10[curScale]; scale += curScale; if (IncreaseScale(ref bufQuo, power) != 0) @@ -2124,7 +2124,7 @@ internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2) } HaveScale96: - power = s_powers10[curScale]; + power = UInt32Powers10[curScale]; scale += curScale; if (IncreaseScale(ref bufQuo, power) != 0) @@ -2209,7 +2209,7 @@ internal static void VarDecMod(ref DecCalc d1, ref DecCalc d2) // Divisor scale can always be increased to dividend scale for remainder calculation. do { - uint power = scale >= MaxInt32Scale ? TenToPowerNine : s_powers10[scale]; + uint power = scale >= MaxInt32Scale ? TenToPowerNine : UInt32Powers10[scale]; ulong tmp = UInt32x32To64(d2.Low, power); d2.Low = (uint)tmp; tmp >>= 32; @@ -2235,7 +2235,7 @@ internal static void VarDecMod(ref DecCalc d1, ref DecCalc d2) int iCurScale = SearchScale(ref bufQuo, DEC_SCALE_MAX + scale); if (iCurScale == 0) break; - uint power = iCurScale >= MaxInt32Scale ? TenToPowerNine : s_powers10[iCurScale]; + uint power = iCurScale >= MaxInt32Scale ? TenToPowerNine : UInt32Powers10[iCurScale]; scale += iCurScale; ulong tmp = UInt32x32To64(bufQuo.U0, power); bufQuo.U0 = (uint)tmp; @@ -2296,7 +2296,7 @@ private static unsafe void VarDecModFull(ref DecCalc d1, ref DecCalc d2, int sca uint high = 3; while (scale < 0) { - uint power = scale <= -MaxInt32Scale ? TenToPowerNine : s_powers10[-scale]; + uint power = scale <= -MaxInt32Scale ? TenToPowerNine : UInt32Powers10[-scale]; uint* buf = (uint*)&b; ulong tmp64 = UInt32x32To64(b.Buf24.U0, power); b.Buf24.U0 = (uint)tmp64; @@ -2409,7 +2409,7 @@ internal static void InternalRound(ref DecCalc d, uint scale, MidpointRounding m } { - power = s_powers10[scale]; + power = UInt32Powers10[(int)scale]; // TODO: https://github.com/dotnet/runtime/issues/5213 uint n = d.uhi; if (n == 0) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs index e344048af72df9..ce960764e6d82b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs @@ -24,16 +24,17 @@ internal static class CalendricalCalculationsHelper private static readonly long s_startOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1)); private static readonly long s_startOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1)); - private static readonly double[] s_coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 }; - private static readonly double[] s_coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 }; - private static readonly double[] s_coefficients1700to1799 = new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 }; - private static readonly double[] s_coefficients1620to1699 = new double[] { 196.58333, -4.0675, 0.0219167 }; - private static readonly double[] s_lambdaCoefficients = new double[] { 280.46645, 36000.76983, 0.0003032 }; - private static readonly double[] s_anomalyCoefficients = new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 }; - private static readonly double[] s_eccentricityCoefficients = new double[] { 0.016708617, -0.000042037, -0.0000001236 }; + private static ReadOnlySpan Coefficients1900to1987 => new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 }; + private static ReadOnlySpan Coefficients1800to1899 => new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 }; + private static ReadOnlySpan Coefficients1700to1799 => new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 }; + private static ReadOnlySpan Coefficients1620to1699 => new double[] { 196.58333, -4.0675, 0.0219167 }; + private static ReadOnlySpan LambdaCoefficients => new double[] { 280.46645, 36000.76983, 0.0003032 }; + private static ReadOnlySpan AnomalyCoefficients => new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 }; + private static ReadOnlySpan EccentricityCoefficients => new double[] { 0.016708617, -0.000042037, -0.0000001236 }; + private static ReadOnlySpan CoefficientsA => new double[] { 124.90, -1934.134, 0.002063 }; + private static ReadOnlySpan CoefficientsB => new double[] { 201.11, 72001.5377, 0.00057 }; + private static readonly double[] s_coefficients = new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) }; - private static readonly double[] s_coefficientsA = new double[] { 124.90, -1934.134, 0.002063 }; - private static readonly double[] s_coefficientsB = new double[] { 201.11, 72001.5377, 0.00057 }; private static double RadiansFromDegrees(double degree) { @@ -129,7 +130,7 @@ public static double AsDayFraction(double longitude) return longitude / FullCircleOfArc; } - private static double PolynomialSum(double[] coefficients, double indeterminate) + private static double PolynomialSum(ReadOnlySpan coefficients, double indeterminate) { double sum = coefficients[0]; double indeterminateRaised = 1; @@ -168,28 +169,28 @@ private static double EphemerisCorrection1900to1987(int gregorianYear) { Debug.Assert(1900 <= gregorianYear && gregorianYear <= 1987); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); - return PolynomialSum(s_coefficients1900to1987, centuriesFrom1900); + return PolynomialSum(Coefficients1900to1987, centuriesFrom1900); } private static double EphemerisCorrection1800to1899(int gregorianYear) { Debug.Assert(1800 <= gregorianYear && gregorianYear <= 1899); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); - return PolynomialSum(s_coefficients1800to1899, centuriesFrom1900); + return PolynomialSum(Coefficients1800to1899, centuriesFrom1900); } private static double EphemerisCorrection1700to1799(int gregorianYear) { Debug.Assert(1700 <= gregorianYear && gregorianYear <= 1799); double yearsSince1700 = gregorianYear - 1700; - return PolynomialSum(s_coefficients1700to1799, yearsSince1700) / SecondsPerDay; + return PolynomialSum(Coefficients1700to1799, yearsSince1700) / SecondsPerDay; } private static double EphemerisCorrection1620to1699(int gregorianYear) { Debug.Assert(1620 <= gregorianYear && gregorianYear <= 1699); double yearsSince1600 = gregorianYear - 1600; - return PolynomialSum(s_coefficients1620to1699, yearsSince1600) / SecondsPerDay; + return PolynomialSum(Coefficients1620to1699, yearsSince1600) / SecondsPerDay; } // ephemeris-correction: correction to account for the slowing down of the rotation of the earth @@ -233,9 +234,9 @@ public static double JulianCenturies(double moment) private static double EquationOfTime(double time) { double julianCenturies = JulianCenturies(time); - double lambda = PolynomialSum(s_lambdaCoefficients, julianCenturies); - double anomaly = PolynomialSum(s_anomalyCoefficients, julianCenturies); - double eccentricity = PolynomialSum(s_eccentricityCoefficients, julianCenturies); + double lambda = PolynomialSum(LambdaCoefficients, julianCenturies); + double anomaly = PolynomialSum(AnomalyCoefficients, julianCenturies); + double eccentricity = PolynomialSum(EccentricityCoefficients, julianCenturies); double epsilon = Obliquity(julianCenturies); double tanHalfEpsilon = TanOfDegree(epsilon / 2); @@ -345,8 +346,8 @@ private static double Aberration(double julianCenturies) private static double Nutation(double julianCenturies) { - double a = PolynomialSum(s_coefficientsA, julianCenturies); - double b = PolynomialSum(s_coefficientsB, julianCenturies); + double a = PolynomialSum(CoefficientsA, julianCenturies); + double b = PolynomialSum(CoefficientsB, julianCenturies); return (-0.004778 * SinOfDegree(a)) - (0.0003667 * SinOfDegree(b)); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs index 0294c7c240871c..f012ae3b0adf8e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs @@ -11,9 +11,8 @@ public abstract class EastAsianLunisolarCalendar : Calendar private const int nDaysPerMonth = 3; // # of days so far in the solar year - private static readonly int[] s_daysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; - - private static readonly int[] s_daysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunisolarCalendar; @@ -273,7 +272,7 @@ private void GregorianToLunar(int solarYear, int solarMonth, int solarDate, out int jan1Date; // Calculate the day number in the solar year. - int solarDay = isLeapYear ? s_daysToMonth366[solarMonth - 1] : s_daysToMonth365[solarMonth - 1]; + int solarDay = isLeapYear ? DaysToMonth366[solarMonth - 1] : DaysToMonth365[solarMonth - 1]; solarDay += solarDate; // Calculate the day number in the lunar year. @@ -314,7 +313,7 @@ private void GregorianToLunar(int solarYear, int solarMonth, int solarDate, out // part of the lunar year. since this part is always in Jan or Feb, // we don't need to handle Leap Year (LY only affects March // and later). - lunarDay -= s_daysToMonth365[jan1Month - 1]; + lunarDay -= DaysToMonth365[jan1Month - 1]; lunarDay -= (jan1Date - 1); // convert the lunar day into a lunar month/date @@ -362,7 +361,7 @@ private bool LunarToGregorian(int lunarYear, int lunarMonth, int lunarDate, out // calc the solar day of year of 1 Lunar day bool isLeapYear = GregorianIsLeapYear(lunarYear); - int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = isLeapYear ? DaysToMonth366 : DaysToMonth365; solarDay = jan1Date; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs index ed9bde883abd12..33c61798f8a2c4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs @@ -22,9 +22,9 @@ public class GregorianCalendar : Calendar private GregorianCalendarTypes _type; - private static readonly int[] DaysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + internal static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly int[] DaysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; + internal static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; private static volatile Calendar? s_defaultInstance; @@ -96,7 +96,7 @@ internal static long GetAbsoluteDate(int year, int month, int day) { if (year >= 1 && year <= MaxYear && month >= 1 && month <= 12) { - int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; if (day >= 1 && (day <= days[month] - days[month - 1])) { int y = year - 1; @@ -157,7 +157,7 @@ public override DateTime AddMonths(DateTime time, int months) y += (i - 11) / 12; } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; int days = (daysArray[m] - daysArray[m - 1]); if (d > days) @@ -278,7 +278,7 @@ internal override bool IsValidDay(int year, int month, int day, int era) return false; } - int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; return day <= (days[month] - days[month - 1]); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendarHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendarHelper.cs index 4054731d261427..b100b633e9ac06 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendarHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendarHelper.cs @@ -53,16 +53,6 @@ internal sealed class GregorianCalendarHelper // internal int MaxYear => m_maxYear; - internal static readonly int[] DaysToMonth365 = - { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 - }; - - internal static readonly int[] DaysToMonth366 = - { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 - }; - private readonly int m_maxYear; private readonly int m_minYear; private readonly Calendar m_Cal; @@ -197,7 +187,7 @@ internal static long GetAbsoluteDate(int year, int month, int day) { if (year >= 1 && year <= 9999 && month >= 1 && month <= 12) { - int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365; if (day >= 1 && (day <= days[month] - days[month - 1])) { int y = year - 1; @@ -271,7 +261,7 @@ public DateTime AddMonths(DateTime time, int months) m = 12 + (i + 1) % 12; y += (i - 11) / 12; } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365; int days = (daysArray[m] - daysArray[m - 1]); if (d > days) @@ -338,7 +328,7 @@ public int GetDaysInMonth(int year, int month, int era) { ThrowHelper.ThrowArgumentOutOfRange_Month(month); } - int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); + ReadOnlySpan days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365); return days[month] - days[month - 1]; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs index 3e8345929c9d3c..9bededeb7b3b01 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs @@ -48,7 +48,7 @@ public partial class HijriCalendar : Calendar private const int MinAdvancedHijri = -2; private const int MaxAdvancedHijri = 2; - private static readonly int[] s_hijriMonthDays = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 }; + private static ReadOnlySpan HijriMonthDays => new int[] { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 }; private int _hijriAdvance = int.MinValue; @@ -80,7 +80,7 @@ public HijriCalendar() private long GetAbsoluteDateHijri(int y, int m, int d) { - return (long)(DaysUpToHijriYear(y) + s_hijriMonthDays[m - 1] + d - 1 - HijriAdjustment); + return (long)(DaysUpToHijriYear(y) + HijriMonthDays[m - 1] + d - 1 - HijriAdjustment); } private long DaysUpToHijriYear(int HijriYear) @@ -241,7 +241,7 @@ internal virtual int GetDatePart(long ticks, int part) return (int)numDays; } - while ((hijriMonth <= 12) && (numDays > s_hijriMonthDays[hijriMonth - 1])) + while ((hijriMonth <= 12) && (numDays > HijriMonthDays[hijriMonth - 1])) { hijriMonth++; } @@ -253,7 +253,7 @@ internal virtual int GetDatePart(long ticks, int part) } // Calculate the Hijri Day. - int hijriDay = (int)(numDays - s_hijriMonthDays[hijriMonth - 1]); + int hijriDay = (int)(numDays - HijriMonthDays[hijriMonth - 1]); if (part == DatePartDay) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.generator.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.generator.cs index 4ca862777f1937..b7c4d1b0cf27fa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.generator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.generator.cs @@ -24,10 +24,10 @@ internal static partial class IcuLocaleData internal const int DoubleCommaSep = 4 << 4; private const int CulturesCount = 864; - // s_nameIndexToNumericData is mapping from index in s_localeNamesIndices to locale data. + // NameIndexToNumericData is mapping from index in s_localeNamesIndices to locale data. // each row in the table will have the following data: // Lcid, Ansi codepage, Oem codepage, MAC codepage, EBCDIC codepage, Geo Id, Digit Substitution | ListSeparator, specific locale index, Console locale index - private static readonly int[] s_nameIndexToNumericData = new int[CulturesCount * NUMERIC_LOCALE_DATA_COUNT_PER_ROW] + private static ReadOnlySpan NameIndexToNumericData => new int[CulturesCount * NUMERIC_LOCALE_DATA_COUNT_PER_ROW] { // Lcid, Ansi CP, Oem CP, MAC CP, EBCDIC CP, Geo Id, digit substitution | ListSeparator, Specific culture index, Console locale index // index - locale name 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 | SemicolonSep , 3 , 240 , // 0 - aa @@ -1327,20 +1327,20 @@ static void GenerateData(string[] cultures, (string lcid, string culture)[] lcid Console.WriteLine("private static ReadOnlySpan LcidToCultureNameIndices => new byte[CulturesCount * NumericLocaleDataBytesPerRow]"); Console.WriteLine("{"); - for (int i = 0; i < s_nameIndexToNumericData.Length; i += NUMERIC_LOCALE_DATA_COUNT_PER_ROW) + for (int i = 0; i < NameIndexToNumericData.Length; i += NUMERIC_LOCALE_DATA_COUNT_PER_ROW) { - uint Lcid = (uint)s_nameIndexToNumericData[i]; - uint AnsiCP = (uint)s_nameIndexToNumericData[i + 1]; - uint OemCP = (uint)s_nameIndexToNumericData[i + 2]; - uint MacCP = (uint)s_nameIndexToNumericData[i + 3]; - uint EBCDIC = (uint)s_nameIndexToNumericData[i + 4]; - uint GeoId = (uint)s_nameIndexToNumericData[i + 5]; - uint DigitList = (uint)s_nameIndexToNumericData[i + 6]; + uint Lcid = (uint)NameIndexToNumericData[i]; + uint AnsiCP = (uint)NameIndexToNumericData[i + 1]; + uint OemCP = (uint)NameIndexToNumericData[i + 2]; + uint MacCP = (uint)NameIndexToNumericData[i + 3]; + uint EBCDIC = (uint)NameIndexToNumericData[i + 4]; + uint GeoId = (uint)NameIndexToNumericData[i + 5]; + uint DigitList = (uint)NameIndexToNumericData[i + 6]; - int index = s_nameIndexToNumericData[i + 7]; + int index = NameIndexToNumericData[i + 7]; Debug.Assert(index == -1 || index < 0xfff); uint SpecificCultureIndex = index == -1 ? 0xfff: (uint)index; - index = s_nameIndexToNumericData[i + 8]; + index = NameIndexToNumericData[i + 8]; Debug.Assert(index == -1 || index < 0xfff); uint ConsoleLocaleIndex = index == -1 ? 0xfff : (uint)index; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs index 4edc8cbce6f400..0db8614f24858d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs @@ -31,16 +31,6 @@ public class JulianCalendar : Calendar // Number of days in 4 years private const int JulianDaysPer4Years = JulianDaysPerYear * 4 + 1; - private static readonly int[] s_daysToMonth365 = - { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 - }; - - private static readonly int[] s_daysToMonth366 = - { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 - }; - // Gregorian Calendar 9999/12/31 = Julian Calendar 9999/10/19 // keep it as variable field for serialization compat. internal int MaxYear = 9999; @@ -106,7 +96,7 @@ internal static void CheckDayRange(int year, int month, int day) } bool isLeapYear = (year % 4) == 0; - int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = isLeapYear ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365; int monthDays = days[month] - days[month - 1]; if (day < 1 || day > monthDays) { @@ -153,7 +143,7 @@ internal static int GetDatePart(long ticks, int part) // Leap year calculation looks different from IsLeapYear since y1, y4, // and y100 are relative to year 1, not year 0 bool leapYear = (y1 == 3); - int[] days = leapYear ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = leapYear ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month int m = (n >> 5) + 1; @@ -178,7 +168,7 @@ internal static int GetDatePart(long ticks, int part) /// internal static long DateToTicks(int year, int month, int day) { - int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = (year % 4 == 0) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365; int y = year - 1; int n = y * 365 + y / 4 + days[month - 1] + day - 1; // Gregorian 1/1/0001 is Julian 1/3/0001. n * TicksPerDay is the ticks in JulianCalendar. @@ -212,7 +202,7 @@ public override DateTime AddMonths(DateTime time, int months) y += (i - 11) / 12; } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365; int days = daysArray[m] - daysArray[m - 1]; if (d > days) { @@ -245,7 +235,7 @@ public override int GetDaysInMonth(int year, int month, int era) { CheckYearEraRange(year, era); CheckMonthRange(month); - int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = (year % 4 == 0) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365; return days[month] - days[month - 1]; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs index b69ac8e7deb1ed..d4a93276b5159a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs @@ -30,7 +30,7 @@ public class PersianCalendar : Calendar private const int DatePartDay = 3; private const int MonthsPerYear = 12; - private static readonly int[] s_daysToMonth = { 0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 366 }; + private static ReadOnlySpan DaysToMonth => new int[] { 0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 366 }; private const int MaxCalendarYear = 9378; private const int MaxCalendarMonth = 10; @@ -125,7 +125,7 @@ private static int MonthFromOrdinalDay(int ordinalDay) { Debug.Assert(ordinalDay <= 366); int index = 0; - while (ordinalDay > s_daysToMonth[index]) + while (ordinalDay > DaysToMonth[index]) { index++; } @@ -138,7 +138,7 @@ private static int DaysInPreviousMonths(int month) Debug.Assert(1 <= month && month <= 12); // months are one based but for calculations use 0 based --month; - return s_daysToMonth[month]; + return DaysToMonth[month]; } internal int GetDatePart(long ticks, int part) @@ -276,7 +276,7 @@ public override int GetDaysInMonth(int year, int month, int era) return MaxCalendarDay; } - int daysInMonth = s_daysToMonth[month] - s_daysToMonth[month - 1]; + int daysInMonth = DaysToMonth[month] - DaysToMonth[month - 1]; if ((month == MonthsPerYear) && !IsLeapYear(year)) { Debug.Assert(daysInMonth == 30); @@ -291,7 +291,7 @@ public override int GetDaysInYear(int year, int era) CheckYearRange(year, era); if (year == MaxCalendarYear) { - return s_daysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay; + return DaysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay; } return IsLeapYear(year, CurrentEra) ? 366 : 365; diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index c1cb1610c01aaa..5c7252bfefffe3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -38,7 +38,7 @@ public static partial class Math private const double doubleRoundLimit = 1e16d; // This table is required for the Round function which can specify the number of digits to round to - private static readonly double[] roundPower10Double = new double[] { + private static ReadOnlySpan RoundPower10Double => new double[] { 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15 }; @@ -1347,7 +1347,7 @@ public static unsafe double Round(double value, int digits, MidpointRounding mod if (Abs(value) < doubleRoundLimit) { - double power10 = roundPower10Double[digits]; + double power10 = RoundPower10Double[digits]; value *= power10; diff --git a/src/libraries/System.Private.CoreLib/src/System/MathF.cs b/src/libraries/System.Private.CoreLib/src/System/MathF.cs index 90a5f84af6603c..31ae24f93e92d1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MathF.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MathF.cs @@ -31,7 +31,7 @@ public static partial class MathF private const int maxRoundingDigits = 6; // This table is required for the Round function which can specify the number of digits to round to - private static readonly float[] roundPower10Single = new float[] { + private static ReadOnlySpan RoundPower10Single => new float[] { 1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f }; @@ -463,7 +463,7 @@ public static unsafe float Round(float x, int digits, MidpointRounding mode) if (Abs(x) < singleRoundLimit) { - float power10 = roundPower10Single[digits]; + float power10 = RoundPower10Single[digits]; x *= power10; diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs index f7e613f9628298..aba4b814fc399a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs @@ -33,7 +33,7 @@ internal unsafe ref struct BigInteger private const int BitsPerBlock = sizeof(int) * 8; private const int MaxBlockCount = (MaxBits + (BitsPerBlock - 1)) / BitsPerBlock; - private static readonly uint[] s_Pow10UInt32Table = new uint[] + private static ReadOnlySpan Pow10UInt32Table => new uint[] { 1, // 10^0 10, // 10^1 @@ -48,7 +48,7 @@ internal unsafe ref struct BigInteger 1000000000 // 10^9 }; - private static readonly int[] s_Pow10BigNumTableIndices = new int[] + private static ReadOnlySpan Pow10BigNumTableIndices => new int[] { 0, // 10^8 2, // 10^16 @@ -60,7 +60,7 @@ internal unsafe ref struct BigInteger 116, // 10^1024 }; - private static readonly uint[] s_Pow10BigNumTable = new uint[] + private static ReadOnlySpan Pow10BigNumTable => new uint[] { // 10^8 1, // _length @@ -832,37 +832,37 @@ public static void Pow2(uint exponent, out BigInteger result) public static void Pow10(uint exponent, out BigInteger result) { - // We leverage two arrays - s_Pow10UInt32Table and s_Pow10BigNumTable to speed up the Pow10 calculation. + // We leverage two arrays - Pow10UInt32Table and Pow10BigNumTable to speed up the Pow10 calculation. // - // s_Pow10UInt32Table stores the results of 10^0 to 10^7. - // s_Pow10BigNumTable stores the results of 10^8, 10^16, 10^32, 10^64, 10^128, 10^256, and 10^512 + // Pow10UInt32Table stores the results of 10^0 to 10^7. + // Pow10BigNumTable stores the results of 10^8, 10^16, 10^32, 10^64, 10^128, 10^256, and 10^512 // // For example, let's say exp = 0b111111. We can split the exp to two parts, one is small exp, // which 10^smallExp can be represented as uint, another part is 10^bigExp, which must be represented as BigNum. // So the result should be 10^smallExp * 10^bigExp. // - // Calculating 10^smallExp is simple, we just lookup the 10^smallExp from s_Pow10UInt32Table. + // Calculating 10^smallExp is simple, we just lookup the 10^smallExp from Pow10UInt32Table. // But here's a bad news: although uint can represent 10^9, exp 9's binary representation is 1001. // That means 10^(1011), 10^(1101), 10^(1111) all cannot be stored as uint, we cannot easily say something like: - // "Any bits <= 3 is small exp, any bits > 3 is big exp". So instead of involving 10^8, 10^9 to s_Pow10UInt32Table, - // consider 10^8 and 10^9 as a bigNum, so they fall into s_Pow10BigNumTable. Now we can have a simple rule: + // "Any bits <= 3 is small exp, any bits > 3 is big exp". So instead of involving 10^8, 10^9 to Pow10UInt32Table, + // consider 10^8 and 10^9 as a bigNum, so they fall into Pow10BigNumTable. Now we can have a simple rule: // "Any bits <= 3 is small exp, any bits > 3 is big exp". // // For 0b111111, we first calculate 10^(smallExp), which is 10^(7), now we can shift right 3 bits, prepare to calculate the bigExp part, // the exp now becomes 0b000111. // - // Apparently the lowest bit of bigExp should represent 10^8 because we have already shifted 3 bits for smallExp, so s_Pow10BigNumTable[0] = 10^8. + // Apparently the lowest bit of bigExp should represent 10^8 because we have already shifted 3 bits for smallExp, so Pow10BigNumTable[0] = 10^8. // Now let's shift exp right 1 bit, the lowest bit should represent 10^(8 * 2) = 10^16, and so on... // - // That's why we just need the values of s_Pow10BigNumTable be power of 2. + // That's why we just need the values of Pow10BigNumTable be power of 2. // // More details of this implementation can be found at: https://github.com/dotnet/coreclr/pull/12894#discussion_r128890596 - // Validate that `s_Pow10BigNumTable` has exactly enough trailing elements to fill a BigInteger (which contains MaxBlockCount + 1 elements) + // Validate that `Pow10BigNumTable` has exactly enough trailing elements to fill a BigInteger (which contains MaxBlockCount + 1 elements) // We validate here, since this is the only current consumer of the array - Debug.Assert((s_Pow10BigNumTableIndices[^1] + MaxBlockCount + 2) == s_Pow10BigNumTable.Length); + Debug.Assert((Pow10BigNumTableIndices[^1] + MaxBlockCount + 2) == Pow10BigNumTable.Length); - SetUInt32(out BigInteger temp1, s_Pow10UInt32Table[exponent & 0x7]); + SetUInt32(out BigInteger temp1, Pow10UInt32Table[(int)(exponent & 0x7)]); ref BigInteger lhs = ref temp1; SetZero(out BigInteger temp2); @@ -877,7 +877,7 @@ public static void Pow10(uint exponent, out BigInteger result) if ((exponent & 1) != 0) { // Multiply into the next temporary - fixed (uint* pBigNumEntry = &s_Pow10BigNumTable[s_Pow10BigNumTableIndices[index]]) + fixed (uint* pBigNumEntry = &Pow10BigNumTable[Pow10BigNumTableIndices[(int)index]]) { ref BigInteger rhs = ref *(BigInteger*)(pBigNumEntry); Multiply(ref lhs, ref rhs, out product); @@ -1084,7 +1084,7 @@ public void MultiplyPow10(uint exponent) { if (exponent <= 9) { - Multiply(s_Pow10UInt32Table[exponent]); + Multiply(Pow10UInt32Table[(int)exponent]); } else if (!IsZero()) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Grisu3.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Grisu3.cs index 2ff9d28e868572..b12e4a42263b29 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Grisu3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Grisu3.cs @@ -34,7 +34,7 @@ internal static class Grisu3 private const int MaximalTargetExponent = -32; private const int MinimalTargetExponent = -60; - private static readonly short[] s_CachedPowersBinaryExponent = new short[] + private static ReadOnlySpan CachedPowersBinaryExponent => new short[] { -1220, -1193, @@ -125,7 +125,7 @@ internal static class Grisu3 1066, }; - private static readonly short[] s_CachedPowersDecimalExponent = new short[] + private static ReadOnlySpan CachedPowersDecimalExponent => new short[] { CachedPowersMinDecimalExponent, -340, @@ -216,7 +216,7 @@ internal static class Grisu3 CachedPowersPowerMaxDecimalExponent, }; - private static readonly ulong[] s_CachedPowersSignificand = new ulong[] + private static ReadOnlySpan CachedPowersSignificand => new ulong[] { 0xFA8FD5A0081C0288, 0xBAAEE17FA23EBF76, @@ -307,7 +307,7 @@ internal static class Grisu3 0xAF87023B9BF0EE6B, }; - private static readonly uint[] s_SmallPowersOfTen = new uint[] + private static ReadOnlySpan SmallPowersOfTen => new uint[] { 1, // 10^0 10, // 10^1 @@ -540,15 +540,15 @@ private static uint BiggestPowerTen(uint number, int numberBits, out int exponen // 1233/4096 is approximately 1/log2(10) int exponentGuess = ((numberBits + 1) * 1233) >> 12; - Debug.Assert((uint)(exponentGuess) < s_SmallPowersOfTen.Length); + Debug.Assert((uint)(exponentGuess) < SmallPowersOfTen.Length); - uint power = s_SmallPowersOfTen[exponentGuess]; + uint power = SmallPowersOfTen[exponentGuess]; // We don't have any guarantees that 2^numberBits <= number if (number < power) { exponentGuess--; - power = s_SmallPowersOfTen[exponentGuess]; + power = SmallPowersOfTen[exponentGuess]; } exponentPlusOne = exponentGuess + 1; @@ -606,7 +606,7 @@ private static bool TryDigitGenCounted(in DiyFp w, int requestedDigits, Span= 11, integrals is not able to exhaust the count by itself since 10^(11 -1) > uint.MaxValue >= integrals. // If integrals < 10^(requestedDigits - 1), integrals cannot exhaust the count. // Otherwise, integrals might be able to exhaust the count and we need to execute the rest of the code. - if ((fractionals == 0) && ((requestedDigits >= 11) || (integrals < s_SmallPowersOfTen[requestedDigits - 1]))) + if ((fractionals == 0) && ((requestedDigits >= 11) || (integrals < SmallPowersOfTen[requestedDigits - 1]))) { Debug.Assert(buffer[0] == '\0'); length = 0; @@ -884,19 +884,19 @@ private static bool TryDigitGenShortest(in DiyFp low, in DiyFp w, in DiyFp high, // Returns a cached power-of-ten with a binary exponent in the range [minExponent; maxExponent] (boundaries included). private static DiyFp GetCachedPowerForBinaryExponentRange(int minExponent, int maxExponent, out int decimalExponent) { - Debug.Assert(s_CachedPowersSignificand.Length == s_CachedPowersBinaryExponent.Length); - Debug.Assert(s_CachedPowersSignificand.Length == s_CachedPowersDecimalExponent.Length); + Debug.Assert(CachedPowersSignificand.Length == CachedPowersBinaryExponent.Length); + Debug.Assert(CachedPowersSignificand.Length == CachedPowersDecimalExponent.Length); double k = Math.Ceiling((minExponent + DiyFp.SignificandSize - 1) * D1Log210); int index = ((CachedPowersOffset + (int)(k) - 1) / CachedPowersDecimalExponentDistance) + 1; - Debug.Assert((uint)(index) < s_CachedPowersSignificand.Length); + Debug.Assert((uint)(index) < CachedPowersSignificand.Length); - Debug.Assert(minExponent <= s_CachedPowersBinaryExponent[index]); - Debug.Assert(s_CachedPowersBinaryExponent[index] <= maxExponent); + Debug.Assert(minExponent <= CachedPowersBinaryExponent[index]); + Debug.Assert(CachedPowersBinaryExponent[index] <= maxExponent); - decimalExponent = s_CachedPowersDecimalExponent[index]; - return new DiyFp(s_CachedPowersSignificand[index], s_CachedPowersBinaryExponent[index]); + decimalExponent = CachedPowersDecimalExponent[index]; + return new DiyFp(CachedPowersSignificand[index], CachedPowersBinaryExponent[index]); } // Rounds the buffer upwards if the result is closer to v by possibly adding 1 to the buffer. diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs index bec85ff737bab6..58bb1ebfc57240 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs @@ -140,7 +140,7 @@ public FloatingPointInfo(ushort denormalMantissaBits, ushort exponentBits, int m /// Normalized 128 bits values for powers of 5^q for q in range [-342, 308] /// stored as 2 64-bits integers for convenience /// - private static readonly ulong[] s_Pow5128Table = { + private static ReadOnlySpan Pow5128Table => new ulong[] { 0xeef453d6923bd65a, 0x113faa2906a13b3f, 0x9558b4661b6565f8, 0x4ac7ca59a424c507, 0xbaaee17fa23ebf76, 0x5d79bcf00d2df649, @@ -1647,13 +1647,13 @@ private static (ulong high, ulong low) ComputeProductApproximation(int bitPrecis int index = 2 * (int)(q - -342); // For small values of q, e.g., q in [0,27], the answer is always exact because // Math.BigMul gives the exact answer. - ulong high = Math.BigMul(w, s_Pow5128Table[index], out ulong low); + ulong high = Math.BigMul(w, Pow5128Table[index], out ulong low); ulong precisionMask = (bitPrecision < 64) ? (0xFFFFFFFFFFFFFFFFUL >> bitPrecision) : 0xFFFFFFFFFFFFFFFFUL; if ((high & precisionMask) == precisionMask) { // could further guard with (lower + w < lower) // regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed. - ulong high2 = Math.BigMul(w, s_Pow5128Table[index + 1], out ulong _); + ulong high2 = Math.BigMul(w, Pow5128Table[index + 1], out ulong _); low += high2; if (high2 > low) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.Data.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.Data.cs index c110074189c19e..fe856d6148225b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.Data.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.Data.cs @@ -6,7 +6,7 @@ namespace System.Text internal sealed partial class EncoderLatin1BestFitFallbackBuffer { // Best fit for ASCII, and since it works for ASCII, we use it for latin1 as well. - private static readonly char[] s_arrayCharBestFit = + private static ReadOnlySpan ArrayCharBestFit => new char[] { // The first many are in case you wanted to use this for ASCIIEncoding, which we don't need to do any more. // (char)0x00a0, (char)0x0020, // No-Break Space -> Space diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.cs index 8fb9515001842a..d9ceb1178643e0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.cs @@ -123,8 +123,7 @@ private static char TryBestFit(char cUnknown) { // Need to figure out our best fit character, low is beginning of array, high is 1 AFTER end of array int lowBound = 0; - Debug.Assert(s_arrayCharBestFit != null); - int highBound = s_arrayCharBestFit.Length; + int highBound = ArrayCharBestFit.Length; int index; // Binary search the array @@ -136,13 +135,13 @@ private static char TryBestFit(char cUnknown) // Also note that index can never == highBound (because diff is rounded down) index = ((iDiff / 2) + lowBound) & 0xFFFE; - char cTest = s_arrayCharBestFit[index]; + char cTest = ArrayCharBestFit[index]; if (cTest == cUnknown) { // We found it - Debug.Assert(index + 1 < s_arrayCharBestFit.Length, + Debug.Assert(index + 1 < ArrayCharBestFit.Length, "[EncoderLatin1BestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array"); - return s_arrayCharBestFit[index + 1]; + return ArrayCharBestFit[index + 1]; } else if (cTest < cUnknown) { @@ -158,12 +157,12 @@ private static char TryBestFit(char cUnknown) for (index = lowBound; index < highBound; index += 2) { - if (s_arrayCharBestFit[index] == cUnknown) + if (ArrayCharBestFit[index] == cUnknown) { // We found it - Debug.Assert(index + 1 < s_arrayCharBestFit.Length, + Debug.Assert(index + 1 < ArrayCharBestFit.Length, "[EncoderLatin1BestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array"); - return s_arrayCharBestFit[index + 1]; + return ArrayCharBestFit[index + 1]; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs index 992891ff088368..2b621d6bce9fe1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs @@ -9,14 +9,14 @@ namespace System.Text internal static partial class EncodingTable { // - // s_encodingNames is the concatenation of all supported IANA names for each codepage. + // EncodingNames is the concatenation of all supported IANA names for each codepage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - // Using indices from s_encodingNamesIndices, we binary search this string when mapping + // Using indices from EncodingNamesIndices, we binary search this string when mapping // an encoding name to a codepage. Note that these names are all lowercase and are // sorted alphabetically. // - private const string s_encodingNames = + private const string EncodingNames = "ansi_x3.4-1968" + // 20127 "ansi_x3.4-1986" + // 20127 "ascii" + // 20127 @@ -61,11 +61,11 @@ internal static partial class EncodingTable "x-unicode-2-0-utf-8"; // 65001 // - // s_encodingNameIndices contains the start index of every encoding name in the string - // s_encodingNames. We infer the length of each string by looking at the start index + // EncodingNameIndices contains the start index of every encoding name in the string + // EncodingNames. We infer the length of each string by looking at the start index // of the next string. // - private static readonly int[] s_encodingNameIndices = new int[] + private static ReadOnlySpan EncodingNameIndices => new int[] { 0, // ansi_x3.4-1968 (20127) 14, // ansi_x3.4-1986 (20127) @@ -113,13 +113,13 @@ internal static partial class EncodingTable }; // - // s_codePagesByName contains the list of supported codepages which match the encoding - // names listed in s_encodingNames. The way mapping works is we binary search - // s_encodingNames using s_encodingNamesIndices until we find a match for a given name. - // The index of the entry in s_encodingNamesIndices will be the index of codepage in - // s_codePagesByName. + // CodePagesByName contains the list of supported codepages which match the encoding + // names listed in EncodingNames. The way mapping works is we binary search + // EncodingNames using EncodingNamesIndices until we find a match for a given name. + // The index of the entry in EncodingNamesIndices will be the index of codepage in + // CodePagesByName. // - private static readonly ushort[] s_codePagesByName = new ushort[] + private static ReadOnlySpan CodePagesByName => new ushort[] { 20127, // ansi_x3.4-1968 20127, // ansi_x3.4-1986 @@ -168,14 +168,14 @@ internal static partial class EncodingTable // // When retrieving the value for System.Text.Encoding.WebName or // System.Text.Encoding.EncodingName given System.Text.Encoding.CodePage, - // we perform a linear search on s_mappedCodePages to find the index of the + // we perform a linear search on MappedCodePages to find the index of the // given codepage. This is used to index WebNameIndices to get the start // index of the web name in the string WebNames, and to index - // s_englishNameIndices to get the start of the English name in - // s_englishNames. In addition, this arrays indices correspond to the indices - // into s_uiFamilyCodePages and s_flags. + // EnglishNameIndices to get the start of the English name in + // EnglishNames. In addition, this arrays indices correspond to the indices + // into UiFamilyCodePages and Flags. // - private static readonly ushort[] s_mappedCodePages = new ushort[] + private static ReadOnlySpan MappedCodePages => new ushort[] { 1200, // utf-16 1201, // utf-16be @@ -188,9 +188,9 @@ internal static partial class EncodingTable }; // - // s_uiFamilyCodePages is indexed by the corresponding index in s_mappedCodePages. + // UiFamilyCodePages is indexed by the corresponding index in MappedCodePages. // - private static readonly int[] s_uiFamilyCodePages = new int[] + private static ReadOnlySpan UiFamilyCodePages => new int[] { 1200, 1200, @@ -203,13 +203,13 @@ internal static partial class EncodingTable }; // - // s_webNames is a concatenation of the default encoding names + // WebNames is a concatenation of the default encoding names // for each code page. It is used in retrieving the value for // System.Text.Encoding.WebName given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. // - private const string s_webNames = + private const string WebNames = "utf-16" + // 1200 "utf-16BE" + // 1201 "utf-32" + // 12000 @@ -220,11 +220,11 @@ internal static partial class EncodingTable "utf-8"; // 65001 // - // s_webNameIndices contains the start index of each code page's default - // web name in the string s_webNames. It is indexed by an index into - // s_mappedCodePages. + // WebNameIndices contains the start index of each code page's default + // web name in the string WebNames. It is indexed by an index into + // MappedCodePages. // - private static readonly int[] s_webNameIndices = new int[] + private static ReadOnlySpan WebNameIndices => new int[] { 0, // utf-16 (1200) 6, // utf-16be (1201) @@ -238,13 +238,13 @@ internal static partial class EncodingTable }; // - // s_englishNames is the concatenation of the English names for each codepage. + // EnglishNames is the concatenation of the English names for each codepage. // It is used in retrieving the value for System.Text.Encoding.EncodingName // given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. // - private const string s_englishNames = + private const string EnglishNames = "Unicode" + // 1200 "Unicode (Big-Endian)" + // 1201 "Unicode (UTF-32)" + // 12000 @@ -255,11 +255,11 @@ internal static partial class EncodingTable "Unicode (UTF-8)"; // 65001 // - // s_englishNameIndices contains the start index of each code page's English - // name in the string s_englishNames. It is indexed by an index into - // s_mappedCodePages. + // EnglishNameIndices contains the start index of each code page's English + // name in the string EnglishNames. It is indexed by an index into + // MappedCodePages. // - private static readonly int[] s_englishNameIndices = new int[] + private static ReadOnlySpan EnglishNameIndices => new int[] { 0, // Unicode (1200) 7, // Unicode (Big-Endian) (1201) @@ -278,8 +278,8 @@ internal static partial class EncodingTable private const uint MIMECONTF_SAVABLE_MAILNEWS = Encoding.MIMECONTF_SAVABLE_MAILNEWS; private const uint MIMECONTF_SAVABLE_BROWSER = Encoding.MIMECONTF_SAVABLE_BROWSER; - // s_flags is indexed by the corresponding index in s_mappedCodePages. - private static readonly uint[] s_flags = new uint[] + // Flags is indexed by the corresponding index in MappedCodePages. + private static ReadOnlySpan Flags => new uint[] { MIMECONTF_SAVABLE_BROWSER, 0, diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs index ded8d29edc76c4..e404065b099bb9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs @@ -50,12 +50,12 @@ internal static int GetCodePageFromName(string name) private static int InternalGetCodePageFromName(string name) { int left = 0; - int right = s_encodingNameIndices.Length - 2; + int right = EncodingNameIndices.Length - 2; int index; int result; - Debug.Assert(s_encodingNameIndices.Length == s_codePagesByName.Length + 1); - Debug.Assert(s_encodingNameIndices[^1] == s_encodingNames.Length); + Debug.Assert(EncodingNameIndices.Length == CodePagesByName.Length + 1); + Debug.Assert(EncodingNameIndices[^1] == EncodingNames.Length); ReadOnlySpan invariantName = name.ToLowerInvariant().AsSpan(); @@ -65,13 +65,13 @@ private static int InternalGetCodePageFromName(string name) { index = ((right - left) / 2) + left; - Debug.Assert(index < s_encodingNameIndices.Length - 1); - result = string.CompareOrdinal(invariantName, s_encodingNames.AsSpan(s_encodingNameIndices[index], s_encodingNameIndices[index + 1] - s_encodingNameIndices[index])); + Debug.Assert(index < EncodingNameIndices.Length - 1); + result = string.CompareOrdinal(invariantName, EncodingNames.AsSpan(EncodingNameIndices[index], EncodingNameIndices[index + 1] - EncodingNameIndices[index])); if (result == 0) { // We found the item, return the associated codePage. - return s_codePagesByName[index]; + return CodePagesByName[index]; } else if (result < 0) { @@ -88,10 +88,10 @@ private static int InternalGetCodePageFromName(string name) // Walk the remaining elements (it'll be 3 or fewer). for (; left <= right; left++) { - Debug.Assert(left < s_encodingNameIndices.Length - 1); - if (string.CompareOrdinal(invariantName, s_encodingNames.AsSpan(s_encodingNameIndices[left], s_encodingNameIndices[left + 1] - s_encodingNameIndices[left])) == 0) + Debug.Assert(left < EncodingNameIndices.Length - 1); + if (string.CompareOrdinal(invariantName, EncodingNames.AsSpan(EncodingNameIndices[left], EncodingNameIndices[left + 1] - EncodingNameIndices[left])) == 0) { - return s_codePagesByName[left]; + return CodePagesByName[left]; } } @@ -107,10 +107,10 @@ internal static EncodingInfo[] GetEncodings() // If UTF-7 encoding is not enabled, we adjust the return array length by -1 // to account for the skipped EncodingInfo element. - ushort[] mappedCodePages = s_mappedCodePages; + ReadOnlySpan mappedCodePages = MappedCodePages; EncodingInfo[] arrayEncodingInfo = new EncodingInfo[(LocalAppContextSwitches.EnableUnsafeUTF7Encoding) ? mappedCodePages.Length : (mappedCodePages.Length - 1)]; - string webNames = s_webNames; - int[] webNameIndices = s_webNameIndices; + string webNames = WebNames; + ReadOnlySpan webNameIndices = WebNameIndices; int arrayEncodingInfoIdx = 0; for (int i = 0; i < mappedCodePages.Length; i++) @@ -135,9 +135,9 @@ internal static EncodingInfo[] GetEncodings() internal static EncodingInfo[] GetEncodings(Dictionary encodingInfoList) { Debug.Assert(encodingInfoList != null); - ushort[] mappedCodePages = s_mappedCodePages; - string webNames = s_webNames; - int[] webNameIndices = s_webNameIndices; + ReadOnlySpan mappedCodePages = MappedCodePages; + string webNames = WebNames; + ReadOnlySpan webNameIndices = WebNameIndices; for (int i = 0; i < mappedCodePages.Length; i++) { @@ -177,10 +177,10 @@ internal static EncodingInfo[] GetEncodings(Dictionary encodi { if (s_codePageToCodePageData == null) { - Interlocked.CompareExchange(ref s_codePageToCodePageData, new CodePageDataItem[s_mappedCodePages.Length], null); + Interlocked.CompareExchange(ref s_codePageToCodePageData, new CodePageDataItem[MappedCodePages.Length], null); } - // Keep in sync with s_mappedCodePages + // Keep in sync with MappedCodePages int index; switch (codePage) { @@ -224,13 +224,13 @@ internal static EncodingInfo[] GetEncodings(Dictionary encodi private static CodePageDataItem InternalGetCodePageDataItem(int codePage, int index) { - int uiFamilyCodePage = s_uiFamilyCodePages[index]; - string webName = s_webNames[s_webNameIndices[index]..s_webNameIndices[index + 1]]; + int uiFamilyCodePage = UiFamilyCodePages[index]; + string webName = WebNames[WebNameIndices[index]..WebNameIndices[index + 1]]; // All supported code pages have identical header names, and body names. string headerName = webName; string bodyName = webName; string displayName = GetDisplayName(codePage, index); - uint flags = s_flags[index]; + uint flags = Flags[index]; return new CodePageDataItem(uiFamilyCodePage, webName, headerName, bodyName, displayName, flags); } @@ -239,7 +239,7 @@ private static string GetDisplayName(int codePage, int englishNameIndex) { string? displayName = SR.GetResourceString("Globalization_cp_" + codePage.ToString()); if (string.IsNullOrEmpty(displayName)) - displayName = s_englishNames[s_englishNameIndices[englishNameIndex]..s_englishNameIndices[englishNameIndex + 1]]; + displayName = EnglishNames[EnglishNameIndices[englishNameIndex]..EnglishNameIndices[englishNameIndex + 1]]; return displayName; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs index e4c4e3457008ff..b618734d401e6a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs @@ -13,19 +13,6 @@ namespace System.Text { public class UTF7Encoding : Encoding { - private const string base64Chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - // 0123456789111111111122222222223333333333444444444455555555556666 - // 012345678901234567890123456789012345678901234567890123 - - // These are the characters that can be directly encoded in UTF7. - private const string directChars = - "\t\n\r '(),-./0123456789:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - // These are the characters that can be optionally directly encoded in UTF7. - private const string optionalChars = - "!\"#$%&*;<=>@[]^_`{|}"; - #pragma warning disable SYSLIB0001 // Used by Encoding.UTF7 for lazy initialization // The initialization code will not be run until a static member of the class is referenced @@ -70,24 +57,30 @@ public UTF7Encoding(bool allowOptionals) private void MakeTables() { // Build our tables - _base64Bytes = new byte[64]; - for (int i = 0; i < 64; i++) _base64Bytes[i] = (byte)base64Chars[i]; + + _base64Bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"u8.ToArray(); + Debug.Assert(_base64Bytes.Length == 64); + _base64Values = new sbyte[128]; for (int i = 0; i < 128; i++) _base64Values[i] = -1; for (int i = 0; i < 64; i++) _base64Values[_base64Bytes[i]] = (sbyte)i; + + // These are the characters that can be directly encoded in UTF7. + ReadOnlySpan directChars = "\t\n\r '(),-./0123456789:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"u8; _directEncode = new bool[128]; - int count = directChars.Length; - for (int i = 0; i < count; i++) + foreach (byte c in directChars) { - _directEncode[directChars[i]] = true; + _directEncode[c] = true; } if (_allowOptionals) { - count = optionalChars.Length; - for (int i = 0; i < count; i++) + // These are the characters that can be optionally directly encoded in UTF7. + ReadOnlySpan optionalChars = "!\"#$%&*;<=>@[]^_`{|}"u8; + + foreach (byte c in optionalChars) { - _directEncode[optionalChars[i]] = true; + _directEncode[c] = true; } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs index daeb79990449a1..84c261c0cdb54a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs @@ -912,7 +912,7 @@ private static void TZif_ParseJulianDay(ReadOnlySpan date, out int month, index++; } while ((uint)index < (uint)date.Length && char.IsAsciiDigit(date[index])); - int[] days = GregorianCalendarHelper.DaysToMonth365; + ReadOnlySpan days = GregorianCalendar.DaysToMonth365; if (julianDay == 0 || julianDay > days[days.Length - 1]) { diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ObjectToIdCache.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ObjectToIdCache.cs index b1cb4458d86b99..9bc1ae31a159a7 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ObjectToIdCache.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ObjectToIdCache.cs @@ -161,24 +161,26 @@ private void Rehash() private static int GetPrime(int min) { - for (int i = 0; i < primes.Length; i++) + ReadOnlySpan primes = new int[] { - int prime = primes[i]; - if (prime >= min) return prime; + 3, 7, 17, 37, 89, 197, 431, 919, 1931, 4049, 8419, 17519, 36353, + 75431, 156437, 324449, 672827, 1395263, 2893249, 5999471, + 11998949, 23997907, 47995853, 95991737, 191983481, 383966977, 767933981, 1535867969, + 2146435069, 0x7FFFFFC7 + // 0x7FFFFFC7 == Array.MaxLength is not prime, but it is the largest possible array size. + // There's nowhere to go from here. Using a const rather than the MaxLength property + // so that the array contains only const values. + }; + + foreach (int prime in primes) + { + if (prime >= min) + { + return prime; + } } return min; } - - internal static readonly int[] primes = - { - 3, 7, 17, 37, 89, 197, 431, 919, 1931, 4049, 8419, 17519, 36353, - 75431, 156437, 324449, 672827, 1395263, 2893249, 5999471, - 11998949, 23997907, 47995853, 95991737, 191983481, 383966977, 767933981, 1535867969, - 2146435069, 0x7FFFFFC7 - // 0x7FFFFFC7 == Array.MaxLength is not prime, but it is the largest possible array size. - // There's nowhere to go from here. Using a const rather than the MaxLength property - // so that the array contains only const values. - }; } } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs index 4bc3d0702bd859..dbda45dc02d7a9 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs @@ -13,7 +13,7 @@ public class UniqueId private const int guidLength = 16; private const int uuidLength = 45; - private static readonly short[] s_char2val = new short[256] + private static ReadOnlySpan Char2val => new short[256] { /* 0-15 */ 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, @@ -162,7 +162,7 @@ private unsafe void UnsafeParse(char* chars, int charCount) int i = 0; int j = 0; - fixed (short* ps = &s_char2val[0]) + fixed (short* ps = &Char2val[0]) { short* _char2val = ps; diff --git a/src/libraries/System.Private.Xml.Linq/src/System/Xml/XPath/XNodeNavigator.cs b/src/libraries/System.Private.Xml.Linq/src/System/Xml/XPath/XNodeNavigator.cs index de86a3abaf022d..8bf77baf64a427 100644 --- a/src/libraries/System.Private.Xml.Linq/src/System/Xml/XPath/XNodeNavigator.cs +++ b/src/libraries/System.Private.Xml.Linq/src/System/Xml/XPath/XNodeNavigator.cs @@ -16,7 +16,7 @@ internal sealed class XNodeNavigator : XPathNavigator, IXmlLineInfo (1 << (int)XmlNodeType.Element) | (1 << (int)XmlNodeType.ProcessingInstruction) | (1 << (int)XmlNodeType.Comment); - private static readonly int[] s_ElementContentMasks = { + private static ReadOnlySpan ElementContentMasks => new int[] { 0, // Root (1 << (int)XmlNodeType.Element), // Element 0, // Attribute @@ -765,7 +765,7 @@ private static bool IsXmlNamespaceDeclaration(XAttribute a) private static int GetElementContentMask(XPathNodeType type) { - return s_ElementContentMasks[(int)type]; + return ElementContentMasks[(int)type]; } private static XAttribute? GetFirstNamespaceDeclarationGlobal(XElement e) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Base64Decoder.cs b/src/libraries/System.Private.Xml/src/System/Xml/Base64Decoder.cs index bb8dbbd5f63a59..3c421935931a40 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Base64Decoder.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Base64Decoder.cs @@ -18,7 +18,6 @@ internal sealed class Base64Decoder : IncrementalReadDecoder private int _bits; private int _bitsFilled; - private const string CharsBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; private static readonly byte[] s_mapBase64 = ConstructMapBase64(); private const int MaxValidChar = (int)'z'; private const byte Invalid = unchecked((byte)-1); @@ -106,14 +105,14 @@ internal override void SetNextOutputBuffer(Array buffer, int index, int count) private static byte[] ConstructMapBase64() { byte[] mapBase64 = new byte[MaxValidChar + 1]; - for (int i = 0; i < mapBase64.Length; i++) - { - mapBase64[i] = Invalid; - } - for (int i = 0; i < CharsBase64.Length; i++) + Array.Fill(mapBase64, Invalid); + + ReadOnlySpan charsBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"u8; + for (int i = 0; i < charsBase64.Length; i++) { - mapBase64[(int)CharsBase64[i]] = (byte)i; + mapBase64[charsBase64[i]] = (byte)i; } + return mapBase64; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdBuilder.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdBuilder.cs index 7d148ecfabcc88..f237a4608c7799 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdBuilder.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdBuilder.cs @@ -598,7 +598,7 @@ public BuilderNamespaceManager(XmlNamespaceManager nsMgr, XmlReader reader) // // for 'block' and 'final' attribute values // - private static readonly int[] s_derivationMethodValues = { + private static ReadOnlySpan DerivationMethodValues => new int[] { (int)XmlSchemaDerivationMethod.Substitution, (int)XmlSchemaDerivationMethod.Extension, (int)XmlSchemaDerivationMethod.Restriction, @@ -2525,12 +2525,12 @@ private int ParseBlockFinalEnum(string value, string attributeName) { if (stringValues[i] == s_derivationMethodStrings[j]) { - if ((r & s_derivationMethodValues[j]) != 0 && (r & s_derivationMethodValues[j]) != s_derivationMethodValues[j]) + if ((r & DerivationMethodValues[j]) != 0 && (r & DerivationMethodValues[j]) != DerivationMethodValues[j]) { SendValidationEvent(SR.Sch_InvalidXsdAttributeValue, attributeName, value, null); return 0; } - r |= s_derivationMethodValues[j]; + r |= DerivationMethodValues[j]; matched = true; break; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs index c8110320f51898..f82937036093f0 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs @@ -82,8 +82,8 @@ private enum XsdDateTimeKind private const int ZoneHourShift = 8; // Maximum number of fraction digits; - private const short maxFractionDigits = 7; - private const int ticksToFractionDivisor = 10000000; + private const short MaxFractionDigits = 7; + private const int TicksToFractionDivisor = 10000000; private static readonly int s_lzyyyy = "yyyy".Length; private static readonly int s_lzyyyy_ = "yyyy-".Length; @@ -127,9 +127,9 @@ private enum XsdDateTimeKind // Number of days in 400 years private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097 - private static readonly int[] DaysToMonth365 = { + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; - private static readonly int[] DaysToMonth366 = { + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; /// @@ -329,7 +329,7 @@ public int Second /// public int Fraction { - get { return (int)(_dt.Ticks % ticksToFractionDivisor); } + get { return (int)(_dt.Ticks % TicksToFractionDivisor); } } /// @@ -592,7 +592,7 @@ private void GetYearMonthDay(out int year, out int month, out int day) // Leap year calculation looks different from IsLeapYear since y1, y4, // and y100 are relative to year 1, not year 0 bool leapYear = y1 == 3 && (y4 != 24 || y100 == 3); - int[] days = leapYear ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = leapYear ? DaysToMonth366 : DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month month = (n >> 5) + 1; @@ -615,7 +615,7 @@ private void PrintTime(ref ValueStringBuilder vsb) int fraction = Fraction; if (fraction != 0) { - int fractionDigits = maxFractionDigits; + int fractionDigits = MaxFractionDigits; while (fraction % 10 == 0) { fractionDigits--; @@ -910,7 +910,7 @@ private bool ParseTimeAndWhitespace(int start) return false; } - private static readonly int[] s_power10 = new int[maxFractionDigits] { -1, 10, 100, 1000, 10000, 100000, 1000000 }; + private static ReadOnlySpan Power10 => new int[MaxFractionDigits] { -1, 10, 100, 1000, 10000, 100000, 1000000 }; private bool ParseTime(ref int start) { if ( @@ -936,11 +936,11 @@ private bool ParseTime(ref int start) { // d < 0 || 9 < d break; } - if (fractionDigits < maxFractionDigits) + if (fractionDigits < MaxFractionDigits) { this.fraction = (this.fraction * 10) + d; } - else if (fractionDigits == maxFractionDigits) + else if (fractionDigits == MaxFractionDigits) { if (5 < d) { @@ -957,13 +957,13 @@ private bool ParseTime(ref int start) } fractionDigits++; } - if (fractionDigits < maxFractionDigits) + if (fractionDigits < MaxFractionDigits) { if (fractionDigits == 0) { return false; // cannot end with . } - fraction *= s_power10[maxFractionDigits - fractionDigits]; + fraction *= Power10[MaxFractionDigits - fractionDigits]; } else { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/NumberFormatter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/NumberFormatter.cs index d749d8ec9feac2..8079d606ffe69a 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/NumberFormatter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/NumberFormatter.cs @@ -99,9 +99,6 @@ public static void ConvertToAlphabetic(StringBuilder sb, double val, char firstC private const string RomanDigitsUC = "IIVIXXLXCCDCM"; private const string RomanDigitsLC = "iivixxlxccdcm"; - // RomanDigit = { I IV V IX X XL L XC C CD D CM M } - private static readonly int[] s_romanDigitValue = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 }; - public static void ConvertToRoman(StringBuilder sb, double val, bool upperCase) { Debug.Assert(1 <= val && val <= MaxRomanValue); @@ -109,11 +106,14 @@ public static void ConvertToRoman(StringBuilder sb, double val, bool upperCase) int number = (int)val; string digits = upperCase ? RomanDigitsUC : RomanDigitsLC; - for (int idx = s_romanDigitValue.Length; idx-- != 0;) + // RomanDigit = { I IV V IX X XL L XC C CD D CM M } + ReadOnlySpan RomanDigitValue = new int[] { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 }; + + for (int idx = RomanDigitValue.Length; idx-- != 0;) { - while (number >= s_romanDigitValue[idx]) + while (number >= RomanDigitValue[idx]) { - number -= s_romanDigitValue[idx]; + number -= RomanDigitValue[idx]; sb.Append(digits, idx, 1 + (idx & 1)); } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs index 2e111fd63e84a7..14496cdc081885 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs @@ -89,7 +89,7 @@ public static double Pred(double x) // Small powers of ten. These are all the powers of ten that have an exact // representation in IEEE double precision format. - public static readonly double[] C10toN = { + public static ReadOnlySpan C10toN => new double[] { 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs index 83fad3f14b8894..16aa8dafdd69a3 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs @@ -287,7 +287,8 @@ internal static class BigNumber | NumberStyles.AllowThousands | NumberStyles.AllowExponent | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowHexSpecifier); - private static readonly uint[] s_uint32PowersOfTen = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + private static ReadOnlySpan UInt32PowersOfTen => new uint[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + internal enum ParsingStatus { OK, @@ -579,7 +580,7 @@ ParsingStatus Naive(ref BigNumberBuffer number, out BigInteger result) if (partialDigitCount > 0) { - MultiplyAdd(ref currentBuffer, s_uint32PowersOfTen[partialDigitCount], partialValue); + MultiplyAdd(ref currentBuffer, UInt32PowersOfTen[partialDigitCount], partialValue); } result = NumberBufferToBigInteger(currentBuffer, number.sign); @@ -817,7 +818,7 @@ BigInteger NumberBufferToBigInteger(Span currentBuffer, bool signa) if (trailingZeroCount > 0) { - MultiplyAdd(ref currentBuffer, s_uint32PowersOfTen[trailingZeroCount], 0); + MultiplyAdd(ref currentBuffer, UInt32PowersOfTen[trailingZeroCount], 0); } int sign; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHAHashProvider.Browser.Managed.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHAHashProvider.Browser.Managed.cs index cfa39e599f7d53..ca61f24b0f7f6f 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHAHashProvider.Browser.Managed.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHAHashProvider.Browser.Managed.cs @@ -244,7 +244,7 @@ public override byte[] HashFinal() return hash; } - private static readonly uint[] _K = { + private static ReadOnlySpan _K => new uint[] { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -522,7 +522,7 @@ public override byte[] HashFinal() return hash; } - private static readonly ulong[] _K = { + private static ReadOnlySpan _K => new ulong[] { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, @@ -810,7 +810,7 @@ public override byte[] HashFinal() return hash; } - private static readonly ulong[] _K = { + private static ReadOnlySpan _K => new ulong[] { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, diff --git a/src/libraries/System.Text.Encoding.CodePages/src/Data/Tools/EncodingDataGenerator.cs b/src/libraries/System.Text.Encoding.CodePages/src/Data/Tools/EncodingDataGenerator.cs index 4bce132659d533..b920563ecda986 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/Data/Tools/EncodingDataGenerator.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/Data/Tools/EncodingDataGenerator.cs @@ -319,13 +319,13 @@ internal static partial class {3} // Ordered by alphabetized IANA name private const string EncodingNames = @" - // s_encodingNames is the concatenation of all supported IANA names for each codepage. + // EncodingNames is the concatenation of all supported IANA names for each codepage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - // Using indices from s_encodingNamesIndices, we binary search this string when mapping + // Using indices from EncodingNamesIndices, we binary search this string when mapping // an encoding name to a codepage. Note that these names are all lowercase and are // sorted alphabetically. - private const string s_encodingNames =| + private const string EncodingNames =| ""{0}"" + // {1:D}| """"; "; @@ -338,10 +338,10 @@ internal static partial class {3} // Ordered by alphabetized IANA name private const string EncodingNameIndices = @" - // s_encodingNameIndices contains the start index of every encoding name in the string - // s_encodingNames. We infer the length of each string by looking at the start index + // EncodingNameIndices contains the start index of every encoding name in the string + // EncodingNames. We infer the length of each string by looking at the start index // of the next string. - private static readonly int[] s_encodingNameIndices = new int[] + private static ReadOnlySpan EncodingNameIndices => new int[] { 0|, // {0} ({1:D}) {2:D}| @@ -354,11 +354,11 @@ internal static partial class {3} // Ordered by alphabetized IANA name private const string CodePagesByName = @" - // s_codePagesByName contains the list of supported codepages which match the encoding - // names listed in s_encodingNames. The way mapping works is we binary search - // s_encodingNames using s_encodingNamesIndices until we find a match for a given name. - // The index of the entry in s_encodingNamesIndices will be the index of codepage in s_codePagesByName. - private static readonly ushort[] s_codePagesByName = new ushort[] + // CodePagesByName contains the list of supported codepages which match the encoding + // names listed in EncodingNames. The way mapping works is we binary search + // EncodingNames using EncodingNamesIndices until we find a match for a given name. + // The index of the entry in EncodingNamesIndices will be the index of codepage in CodePagesByName. + private static ReadOnlySpan CodePagesByName => new ushort[] {| {0:D}, // {1}| }; @@ -375,8 +375,8 @@ internal static partial class {3} // we perform a linear search on s_mappedCodePages to find the index of the // given codepage. This is used to index WebNameIndices to get the start // index of the web name in the string WebNames, and to index - // s_englishNameIndices to get the start of the English name in s_englishNames. - private static readonly ushort[] s_mappedCodePages = new ushort[] + // EnglishNameIndices to get the start of the English name in EnglishNames. + private static ReadOnlySpan s_mappedCodePages => new ushort[] {| {0:D}, // {1}| }; @@ -388,12 +388,12 @@ internal static partial class {3} // Ordered by codepage private const string WebNames = @" - // s_webNames is a concatenation of the default encoding names + // WebNames is a concatenation of the default encoding names // for each code page. It is used in retrieving the value for // System.Text.Encoding.WebName given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - private const string s_webNames =| + private const string WebNames =| ""{0}"" + // {1:D}| """"; "; @@ -406,10 +406,10 @@ internal static partial class {3} // Ordered by codepage private const string WebNameIndices = @" - // s_webNameIndices contains the start index of each code page's default - // web name in the string s_webNames. It is indexed by an index into + // WebNameIndices contains the start index of each code page's default + // web name in the string WebNames. It is indexed by an index into // s_mappedCodePages. - private static readonly int[] s_webNameIndices = new int[] + private static ReadOnlySpan WebNameIndices => new int[] { 0|, // {0} ({1:D}) {2:D}| @@ -422,12 +422,12 @@ internal static partial class {3} // Ordered by codepage private const string EnglishNames = @" - // s_englishNames is the concatenation of the English names for each codepage. + // EnglishNames is the concatenation of the English names for each codepage. // It is used in retrieving the value for System.Text.Encoding.EncodingName // given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - private const string s_englishNames =| + private const string EnglishNames =| ""{0}"" + // {1:D}| """"; "; @@ -440,9 +440,9 @@ internal static partial class {3} // Ordered by codepage private const string EnglishNameIndices = @" - // s_englishNameIndices contains the start index of each code page's English - // name in the string s_englishNames. It is indexed by an index into s_mappedCodePages. - private static readonly int[] s_englishNameIndices = new int[] + // EnglishNameIndices contains the start index of each code page's English + // name in the string EnglishNames. It is indexed by an index into s_mappedCodePages. + private static ReadOnlySpan EnglishNameIndices => new int[] { 0|, // {0} ({1:D}) {2:D}| diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.Data.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.Data.cs index 9382494e564aa7..72ff6d8f7cbbbd 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.Data.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.Data.cs @@ -18,7 +18,7 @@ internal static partial class EncodingTable // Using indices from s_encodingNamesIndices, we binary search this string when mapping // an encoding name to a codepage. Note that these names are all lowercase and are // sorted alphabetically. - private const string s_encodingNames = + private const string EncodingNames = "437" + // 437 "arabic" + // 28596 "asmo-708" + // 708 @@ -388,7 +388,7 @@ internal static partial class EncodingTable // s_encodingNameIndices contains the start index of every encoding name in the string // s_encodingNames. We infer the length of each string by looking at the start index // of the next string. - private static readonly int[] s_encodingNameIndices = new int[] + private static ReadOnlySpan EncodingNameIndices => new int[] { 0, // 437 (437) 3, // arabic (28596) @@ -761,7 +761,7 @@ internal static partial class EncodingTable // names listed in s_encodingNames. The way mapping works is we binary search // s_encodingNames using s_encodingNamesIndices until we find a match for a given name. // The index of the entry in s_encodingNamesIndices will be the index of codepage in s_codePagesByName. - private static readonly ushort[] s_codePagesByName = new ushort[] + private static ReadOnlySpan CodePagesByName => new ushort[] { 437, // 437 28596, // arabic @@ -1135,7 +1135,7 @@ internal static partial class EncodingTable // given codepage. This is used to index WebNameIndices to get the start // index of the web name in the string WebNames, and to index // s_englishNameIndices to get the start of the English name in s_englishNames. - private static readonly ushort[] s_mappedCodePages = new ushort[] + private static ReadOnlySpan MappedCodePages => new ushort[] { 37, // ibm037 437, // ibm437 @@ -1276,7 +1276,7 @@ internal static partial class EncodingTable // System.Text.Encoding.WebName given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - private const string s_webNames = + private const string WebNames = "ibm037" + // 37 "ibm437" + // 437 "ibm500" + // 500 @@ -1414,7 +1414,7 @@ internal static partial class EncodingTable // s_webNameIndices contains the start index of each code page's default // web name in the string s_webNames. It is indexed by an index into // s_mappedCodePages. - private static readonly int[] s_webNameIndices = new int[] + private static ReadOnlySpan WebNameIndices => new int[] { 0, // ibm037 (37) 6, // ibm437 (437) @@ -1556,7 +1556,7 @@ internal static partial class EncodingTable // given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - private const string s_englishNames = + private const string EnglishNames = "IBM EBCDIC (US-Canada)" + // 37 "OEM United States" + // 437 "IBM EBCDIC (International)" + // 500 @@ -1693,7 +1693,7 @@ internal static partial class EncodingTable // s_englishNameIndices contains the start index of each code page's English // name in the string s_englishNames. It is indexed by an index into s_mappedCodePages. - private static readonly int[] s_englishNameIndices = new int[] + private static ReadOnlySpan EnglishNameIndices => new int[] { 0, // IBM EBCDIC (US-Canada) (37) 22, // OEM United States (437) diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.cs index c0ad4ece91f89d..f177657428cf6b 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; @@ -62,13 +61,15 @@ internal static int GetCodePageFromName(string name) private static int InternalGetCodePageFromName(string name) { + ReadOnlySpan encodingNameIndices = EncodingNameIndices; + int left = 0; - int right = s_encodingNameIndices.Length - 2; + int right = encodingNameIndices.Length - 2; int index; int result; - Debug.Assert(s_encodingNameIndices.Length == s_codePagesByName.Length + 1); - Debug.Assert(s_encodingNameIndices[s_encodingNameIndices.Length - 1] == s_encodingNames.Length); + Debug.Assert(encodingNameIndices.Length == CodePagesByName.Length + 1); + Debug.Assert(encodingNameIndices[encodingNameIndices.Length - 1] == EncodingNames.Length); name = name.ToLowerInvariant(); @@ -78,12 +79,12 @@ private static int InternalGetCodePageFromName(string name) { index = ((right - left) / 2) + left; - Debug.Assert(index < s_encodingNameIndices.Length - 1); - result = CompareOrdinal(name, s_encodingNames, s_encodingNameIndices[index], s_encodingNameIndices[index + 1] - s_encodingNameIndices[index]); + Debug.Assert(index < encodingNameIndices.Length - 1); + result = CompareOrdinal(name, EncodingNames, encodingNameIndices[index], encodingNameIndices[index + 1] - encodingNameIndices[index]); if (result == 0) { //We found the item, return the associated codePage. - return (s_codePagesByName[index]); + return CodePagesByName[index]; } else if (result < 0) { @@ -100,10 +101,10 @@ private static int InternalGetCodePageFromName(string name) //Walk the remaining elements (it'll be 3 or fewer). for (; left <= right; left++) { - Debug.Assert(left < s_encodingNameIndices.Length - 1); - if (CompareOrdinal(name, s_encodingNames, s_encodingNameIndices[left], s_encodingNameIndices[left + 1] - s_encodingNameIndices[left]) == 0) + Debug.Assert(left < encodingNameIndices.Length - 1); + if (CompareOrdinal(name, EncodingNames, encodingNameIndices[left], encodingNameIndices[left + 1] - encodingNameIndices[left]) == 0) { - return (s_codePagesByName[left]); + return CodePagesByName[left]; } } @@ -129,19 +130,19 @@ private static int CompareOrdinal(string s1, string s2, int index, int length) internal static string? GetWebNameFromCodePage(int codePage) { - return GetNameFromCodePage(codePage, s_webNames, s_webNameIndices, s_codePageToWebNameCache); + return GetNameFromCodePage(codePage, WebNames, WebNameIndices, s_codePageToWebNameCache); } internal static string? GetEnglishNameFromCodePage(int codePage) { - return GetNameFromCodePage(codePage, s_englishNames, s_englishNameIndices, s_codePageToEnglishNameCache); + return GetNameFromCodePage(codePage, EnglishNames, EnglishNameIndices, s_codePageToEnglishNameCache); } - private static string? GetNameFromCodePage(int codePage, string names, int[] indices, Dictionary cache) + private static string? GetNameFromCodePage(int codePage, string names, ReadOnlySpan indices, Dictionary cache) { string? name; - Debug.Assert(s_mappedCodePages.Length + 1 == indices.Length); + Debug.Assert(MappedCodePages.Length + 1 == indices.Length); Debug.Assert(indices[indices.Length - 1] == names.Length); if ((uint)codePage > ushort.MaxValue) @@ -150,7 +151,7 @@ private static int CompareOrdinal(string s1, string s2, int index, int length) } //This is a linear search, but we probably won't be doing it very often. - int i = Array.IndexOf(s_mappedCodePages, (ushort)codePage); + int i = MappedCodePages.IndexOf((ushort)codePage); if (i < 0) { // Didn't find it. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs index 4c277685b6d7e1..09a69634bfa880 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs @@ -538,7 +538,7 @@ private static bool TryCreateDateTime(DateTimeParseData parseData, DateTimeKind Debug.Assert(parseData.Fraction >= 0 && parseData.Fraction <= JsonConstants.MaxDateTimeFraction); // All of our callers to date parse the fraction from fixed 7-digit fields so this value is trusted. - int[] days = DateTime.IsLeapYear(parseData.Year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = DateTime.IsLeapYear(parseData.Year) ? DaysToMonth366 : DaysToMonth365; int yearMinusOne = parseData.Year - 1; int totalDays = (yearMinusOne * 365) + (yearMinusOne / 4) - (yearMinusOne / 100) + (yearMinusOne / 400) + days[parseData.Month - 1] + parseData.Day - 1; long ticks = totalDays * TimeSpan.TicksPerDay; @@ -549,7 +549,7 @@ private static bool TryCreateDateTime(DateTimeParseData parseData, DateTimeKind return true; } - private static readonly int[] s_daysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly int[] s_daysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; } } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.Data.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.Data.cs index 888d23f524a526..393968ad57e324 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.Data.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.Data.cs @@ -9,7 +9,7 @@ internal static partial class RegexCaseEquivalences // PLEASE DON'T MODIFY BY HAND // IF YOU NEED TO UPDATE UNICODE VERSION FOLLOW THE GUIDE AT src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md - private static char[] EquivalenceCasingValues { get; } = new char[2336] + private static ReadOnlySpan EquivalenceCasingValues => new char[2336] { '\u0041', '\u0061', '\u0042', '\u0062', '\u0043', '\u0063', '\u0044', '\u0064', '\u0045', '\u0065', '\u0046', '\u0066', '\u0047', '\u0067', '\u0048', '\u0068', '\u0049', '\u0069', '\u004A', '\u006A', '\u004B', '\u006B', '\u212A', '\u004C', '\u006C', '\u004D', '\u006D', '\u004E', '\u006E', '\u004F', '\u006F', '\u0050', @@ -159,7 +159,7 @@ internal static partial class RegexCaseEquivalences '\uFF33', '\uFF53', '\uFF34', '\uFF54', '\uFF35', '\uFF55', '\uFF36', '\uFF56', '\uFF37', '\uFF57', '\uFF38', '\uFF58', '\uFF39', '\uFF59', '\uFF3A', '\uFF5A' }; - private static ushort[] EquivalenceFirstLevelLookup { get; } = new ushort[64] + private static ReadOnlySpan EquivalenceFirstLevelLookup => new ushort[64] { 0x0000, 0x0400, 0xffff, 0xffff, 0x0800, 0xffff, 0xffff, 0x0c00, 0x1000, 0x1400, 0xffff, 0x1800, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, @@ -167,7 +167,7 @@ internal static partial class RegexCaseEquivalences 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x2400 }; - private static ushort[] EquivalenceCasingMap { get; } = new ushort[10240] + private static ReadOnlySpan EquivalenceCasingMap => new ushort[10240] { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs index 72a61998b8ccf0..4367da61026dca 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs @@ -16,11 +16,6 @@ internal static partial class RegexCaseEquivalences { public const int CharactersPerRange = 1024; - private static readonly char[] s_specialCasingSetBehaviors = new char[5] - { - 'I', 'i', '\u0130', 'I', '\u0131' - }; - /// /// Performs a fast lookup which determines if a character is involved in case conversion, as well as /// returns the characters that should be considered equivalent in case it does participate in case conversion. @@ -45,14 +40,14 @@ public static bool TryFindCaseEquivalencesForCharWithIBehavior(char c, CultureIn equivalences = c switch { // Invariant mappings - 'i' or 'I' when mappingBehavior is RegexCaseBehavior.Invariant => s_specialCasingSetBehaviors.AsSpan(0, 2), // 'I' and 'i' + 'i' or 'I' when mappingBehavior is RegexCaseBehavior.Invariant => "Ii".AsSpan(), // Non-Turkish mappings - 'i' or 'I' or '\u0130' when mappingBehavior is RegexCaseBehavior.NonTurkish => s_specialCasingSetBehaviors.AsSpan(0, 3), // 'I', 'i', and '\u0130' + 'i' or 'I' or '\u0130' when mappingBehavior is RegexCaseBehavior.NonTurkish => "Ii\u0130".AsSpan(), // Turkish mappings - 'I' or '\u0131' when mappingBehavior is RegexCaseBehavior.Turkish => s_specialCasingSetBehaviors.AsSpan(3, 2), // 'I' and '\u0131' - 'i' or '\u0130' when mappingBehavior is RegexCaseBehavior.Turkish => s_specialCasingSetBehaviors.AsSpan(1, 2), // 'i' and '\u0130' + 'I' or '\u0131' when mappingBehavior is RegexCaseBehavior.Turkish => "I\u0131".AsSpan(), + 'i' or '\u0130' when mappingBehavior is RegexCaseBehavior.Turkish => "i\u0130".AsSpan(), // Default _ => default @@ -158,7 +153,7 @@ private static bool TryFindCaseEquivalencesForChar(char c, out ReadOnlySpan> 13) & 0b111); ushort index3 = (ushort)(mappingValue & 0x1FFF); - equivalences = EquivalenceCasingValues.AsSpan(index3, count); + equivalences = EquivalenceCasingValues.Slice(index3, count); return true; } diff --git a/src/libraries/System.Text.RegularExpressions/tools/DataTable.cs b/src/libraries/System.Text.RegularExpressions/tools/DataTable.cs index 7185e4a62e7e6c..18a120bbede3a3 100644 --- a/src/libraries/System.Text.RegularExpressions/tools/DataTable.cs +++ b/src/libraries/System.Text.RegularExpressions/tools/DataTable.cs @@ -110,8 +110,10 @@ void EmitFileHeadersAndUsings(StreamWriter writer) void EmitFirstLevelLookupTable(StreamWriter writer) { - var firstLevelLookupTable = FlattenFirstLevelLookupTable(); - writer.Write(" private static ushort[] EquivalenceFirstLevelLookup { get; } = new ushort[" + firstLevelLookupTable.Count + "]\n {\n"); + List firstLevelLookupTable = FlattenFirstLevelLookupTable(); + + writer.Write($" private static ReadOnlySpan EquivalenceFirstLevelLookup => new ushort[{firstLevelLookupTable.Count}]"); + writer.Write(" {"); writer.Write(" 0x{0:x4}", firstLevelLookupTable[0]); for (var i = 1; i < firstLevelLookupTable.Count; i++) @@ -146,8 +148,10 @@ List FlattenFirstLevelLookupTable() void EmitMapArray(StreamWriter writer) { - var flattenedMap = FlattenMapDictionary(); - writer.Write(" private static ushort[] EquivalenceCasingMap { get; } = new ushort[" + flattenedMap.Count + "]\n {\n"); + List flattenedMap = FlattenMapDictionary(); + + writer.Write($" private static ReadOnlySpan EquivalenceCasingMap => new ushort[{flattenedMap.Count}]"); + writer.Write(" {"); writer.Write(" 0x{0:x4}", flattenedMap[0]); for (var i = 1; i < flattenedMap.Count; i++) @@ -189,8 +193,12 @@ List FlattenMapDictionary() void EmitValuesArray(StreamWriter writer) { - var flattenedValues = FlattenValuesDictionary(); - writer.Write(" private static char[] EquivalenceCasingValues { get; } = new char[" + flattenedValues.Count + "]\n {\n"); + List flattenedValues = FlattenValuesDictionary(); + + writer.Write($" private static ReadOnlySpan EquivalenceCasingValues => new char[{flattenedValues.Count}]"); + writer.Write(" {"); + + writer.Write(" private static ReadOnlySpan EquivalenceCasingValues => new char[" + flattenedValues.Count + "]\n {\n"); writer.Write(" \'\\u{0:X4}\'", flattenedValues[0]); for (var i = 1; i < flattenedValues.Count; i++)