Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ZString v2.6.1
BepInEx/core/ZString/netstandard2.1/ZString.dll
Decompiled 2 years ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers; using System.Buffers.Text; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("ConsoleApp, PublicKey=00240000048000009400000006020000002400005253413100040000010001000144ec28f1e9ef7b17dacc47425a7a153aea0a7baa590743a2d1a86f4b3e10a8a12712c6e647966bfd8bd6e830048b23bd42bbc56f179585c15b8c19cf86c0eed1b73c993dd7a93a30051dd50fdda0e4d6b65e6874e30f1c37cf8bcbc7fe02c7f2e6a0a3327c0ccc1631bf645f40732521fa0b41a30c178d08f7dd779d42a1ee")] [assembly: InternalsVisibleTo("ConsoleAppNet472, PublicKey=00240000048000009400000006020000002400005253413100040000010001000144ec28f1e9ef7b17dacc47425a7a153aea0a7baa590743a2d1a86f4b3e10a8a12712c6e647966bfd8bd6e830048b23bd42bbc56f179585c15b8c19cf86c0eed1b73c993dd7a93a30051dd50fdda0e4d6b65e6874e30f1c37cf8bcbc7fe02c7f2e6a0a3327c0ccc1631bf645f40732521fa0b41a30c178d08f7dd779d42a1ee")] [assembly: InternalsVisibleTo("ZString.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001000144ec28f1e9ef7b17dacc47425a7a153aea0a7baa590743a2d1a86f4b3e10a8a12712c6e647966bfd8bd6e830048b23bd42bbc56f179585c15b8c19cf86c0eed1b73c993dd7a93a30051dd50fdda0e4d6b65e6874e30f1c37cf8bcbc7fe02c7f2e6a0a3327c0ccc1631bf645f40732521fa0b41a30c178d08f7dd779d42a1ee")] [assembly: InternalsVisibleTo("ZString.NetCore2Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001000144ec28f1e9ef7b17dacc47425a7a153aea0a7baa590743a2d1a86f4b3e10a8a12712c6e647966bfd8bd6e830048b23bd42bbc56f179585c15b8c19cf86c0eed1b73c993dd7a93a30051dd50fdda0e4d6b65e6874e30f1c37cf8bcbc7fe02c7f2e6a0a3327c0ccc1631bf645f40732521fa0b41a30c178d08f7dd779d42a1ee")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Cysharp")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("© Cysharp, Inc.")] [assembly: AssemblyDescription("Zero allocation StringBuilder for .NET Core and Unity.")] [assembly: AssemblyFileVersion("2.6.0.0")] [assembly: AssemblyInformationalVersion("2.6.0+3156134075b89a162fe95350a2e92a4c85ccca59")] [assembly: AssemblyProduct("ZString")] [assembly: AssemblyTitle("ZString")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Cysharp/ZString")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.6.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace System { internal static class BufferEx { internal unsafe static void ZeroMemory(byte* dest, uint len) { if (len != 0) { for (int i = 0; i < len; i++) { dest[i] = 0; } } } internal unsafe static void Memcpy(byte* dest, byte* src, int len) { if (len != 0) { for (int i = 0; i < len; i++) { dest[i] = src[i]; } } } } internal static class DecimalEx { [StructLayout(LayoutKind.Explicit)] private struct DecimalBits { [FieldOffset(0)] public int flags; [FieldOffset(4)] public int hi; [FieldOffset(8)] public int lo; [FieldOffset(12)] public int mid; } [StructLayout(LayoutKind.Explicit)] private struct DecCalc { private const uint TenToPowerNine = 1000000000u; [FieldOffset(0)] public uint uflags; [FieldOffset(4)] public uint uhi; [FieldOffset(8)] public uint ulo; [FieldOffset(12)] public uint umid; [FieldOffset(8)] private ulong ulomidLE; internal static uint DecDivMod1E9(ref DecCalc value) { ulong num = ((ulong)value.uhi << 32) + value.umid; ulong num2 = num / 1000000000; value.uhi = (uint)(num2 >> 32); value.umid = (uint)num2; ulong num3 = (num - (uint)((int)num2 * 1000000000) << 32) + value.ulo; return (uint)(int)num3 - (value.ulo = (uint)(num3 / 1000000000)) * 1000000000; } } private const int ScaleShift = 16; private static ref DecCalc AsMutable(ref decimal d) { return ref Unsafe.As<decimal, DecCalc>(ref d); } internal static uint High(this decimal value) { return Unsafe.As<decimal, DecCalc>(ref value).uhi; } internal static uint Low(this decimal value) { return Unsafe.As<decimal, DecCalc>(ref value).ulo; } internal static uint Mid(this decimal value) { return Unsafe.As<decimal, DecCalc>(ref value).umid; } internal static bool IsNegative(this decimal value) { return Unsafe.As<decimal, DecimalBits>(ref value).flags < 0; } internal static int Scale(this decimal value) { return (byte)(Unsafe.As<decimal, DecimalBits>(ref value).flags >> 16); } internal static uint DecDivMod1E9(ref decimal value) { return DecCalc.DecDivMod1E9(ref AsMutable(ref value)); } } internal static class FloatEx { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsFinite(double d) { return (BitConverter.DoubleToInt64Bits(d) & 0x7FFFFFFFFFFFFFFFL) < 9218868437227405312L; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNegative(double d) { return BitConverter.DoubleToInt64Bits(d) < 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsFinite(float f) { return (SingleToInt32Bits(f) & 0x7FFFFFFF) < 2139095040; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNegative(float f) { return SingleToInt32Bits(f) < 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int SingleToInt32Bits(float value) { return *(int*)(&value); } } internal struct GuidEx { private int _a; private short _b; private short _c; private byte _d; private byte _e; private byte _f; private byte _g; private byte _h; private byte _i; private byte _j; private byte _k; private unsafe static int HexsToChars(char* guidChars, int a, int b) { *guidChars = System.HexConverter.ToCharLower(a >> 4); guidChars[1] = System.HexConverter.ToCharLower(a); guidChars[2] = System.HexConverter.ToCharLower(b >> 4); guidChars[3] = System.HexConverter.ToCharLower(b); return 4; } private unsafe static int HexsToCharsHexOutput(char* guidChars, int a, int b) { *guidChars = '0'; guidChars[1] = 'x'; guidChars[2] = System.HexConverter.ToCharLower(a >> 4); guidChars[3] = System.HexConverter.ToCharLower(a); guidChars[4] = ','; guidChars[5] = '0'; guidChars[6] = 'x'; guidChars[7] = System.HexConverter.ToCharLower(b >> 4); guidChars[8] = System.HexConverter.ToCharLower(b); return 9; } public unsafe bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default(ReadOnlySpan<char>)) { if (format.Length == 0) { format = "D".AsSpan(); } if (format.Length != 1) { throw new FormatException("InvalidGuidFormatSpecification"); } bool flag = true; bool flag2 = false; int num = 0; int num2; switch (format[0]) { case 'D': case 'd': num2 = 36; break; case 'N': case 'n': flag = false; num2 = 32; break; case 'B': case 'b': num = 8192123; num2 = 38; break; case 'P': case 'p': num = 2687016; num2 = 38; break; case 'X': case 'x': num = 8192123; flag = false; flag2 = true; num2 = 68; break; default: throw new FormatException("InvalidGuidFormatSpecification"); } if (destination.Length < num2) { charsWritten = 0; return false; } fixed (char* ptr = &MemoryMarshal.GetReference(destination)) { char* ptr2 = ptr; if (num != 0) { *(ptr2++) = (char)num; } if (flag2) { *(ptr2++) = '0'; *(ptr2++) = 'x'; ptr2 += HexsToChars(ptr2, _a >> 24, _a >> 16); ptr2 += HexsToChars(ptr2, _a >> 8, _a); *(ptr2++) = ','; *(ptr2++) = '0'; *(ptr2++) = 'x'; ptr2 += HexsToChars(ptr2, _b >> 8, _b); *(ptr2++) = ','; *(ptr2++) = '0'; *(ptr2++) = 'x'; ptr2 += HexsToChars(ptr2, _c >> 8, _c); *(ptr2++) = ','; *(ptr2++) = '{'; ptr2 += HexsToCharsHexOutput(ptr2, _d, _e); *(ptr2++) = ','; ptr2 += HexsToCharsHexOutput(ptr2, _f, _g); *(ptr2++) = ','; ptr2 += HexsToCharsHexOutput(ptr2, _h, _i); *(ptr2++) = ','; ptr2 += HexsToCharsHexOutput(ptr2, _j, _k); *(ptr2++) = '}'; } else { ptr2 += HexsToChars(ptr2, _a >> 24, _a >> 16); ptr2 += HexsToChars(ptr2, _a >> 8, _a); if (flag) { *(ptr2++) = '-'; } ptr2 += HexsToChars(ptr2, _b >> 8, _b); if (flag) { *(ptr2++) = '-'; } ptr2 += HexsToChars(ptr2, _c >> 8, _c); if (flag) { *(ptr2++) = '-'; } ptr2 += HexsToChars(ptr2, _d, _e); if (flag) { *(ptr2++) = '-'; } ptr2 += HexsToChars(ptr2, _f, _g); ptr2 += HexsToChars(ptr2, _h, _i); ptr2 += HexsToChars(ptr2, _j, _k); } if (num != 0) { *(ptr2++) = (char)(num >> 16); } } charsWritten = num2; return true; } } internal static class HexConverter { public enum Casing : uint { Upper = 0u, Lower = 8224u } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToBytesBuffer(byte value, Span<byte> buffer, int startingIndex = 0, Casing casing = Casing.Upper) { uint num = (uint)(((value & 0xF0) << 4) + (value & 0xF) - 35209); uint num2 = ((((0 - num) & 0x7070) >> 4) + num + 47545) | (uint)casing; buffer[startingIndex + 1] = (byte)num2; buffer[startingIndex] = (byte)(num2 >> 8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ToCharsBuffer(byte value, Span<char> buffer, int startingIndex = 0, Casing casing = Casing.Upper) { uint num = (uint)(((value & 0xF0) << 4) + (value & 0xF) - 35209); uint num2 = ((((0 - num) & 0x7070) >> 4) + num + 47545) | (uint)casing; buffer[startingIndex + 1] = (char)(num2 & 0xFFu); buffer[startingIndex] = (char)(num2 >> 8); } public static string ToString(ReadOnlySpan<byte> bytes, Casing casing = Casing.Upper) { Span<char> span = default(Span<char>); span = ((bytes.Length <= 16) ? stackalloc char[bytes.Length * 2] : new char[bytes.Length * 2].AsSpan()); int num = 0; ReadOnlySpan<byte> readOnlySpan = bytes; for (int i = 0; i < readOnlySpan.Length; i++) { ToCharsBuffer(readOnlySpan[i], span, num, casing); num += 2; } return span.ToString(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static char ToCharUpper(int value) { value &= 0xF; value += 48; if (value > 57) { value += 7; } return (char)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static char ToCharLower(int value) { value &= 0xF; value += 48; if (value > 57) { value += 39; } return (char)value; } } internal static class InternalSpanEx { [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> span, ReadOnlySpan<char> value) { if (span.Length != value.Length) { return false; } if (value.Length == 0) { return true; } return EqualsOrdinalIgnoreCase(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), span.Length); } private static bool EqualsOrdinalIgnoreCase(ref char charA, ref char charB, int length) { IntPtr zero = IntPtr.Zero; if (IntPtr.Size == 8) { while ((uint)length >= 4u) { ulong num = Unsafe.ReadUnaligned<ulong>(ref Unsafe.As<char, byte>(ref Unsafe.AddByteOffset(ref charA, zero))); ulong num2 = Unsafe.ReadUnaligned<ulong>(ref Unsafe.As<char, byte>(ref Unsafe.AddByteOffset(ref charB, zero))); ulong num3 = num | num2; if (AllCharsInUInt32AreAscii((uint)((int)num3 | (int)(num3 >> 32)))) { if (!UInt64OrdinalIgnoreCaseAscii(num, num2)) { return false; } zero += 8; length -= 4; continue; } goto IL_0101; } } while (true) { switch (length) { default: { uint num6 = Unsafe.ReadUnaligned<uint>(ref Unsafe.As<char, byte>(ref Unsafe.AddByteOffset(ref charA, zero))); uint num7 = Unsafe.ReadUnaligned<uint>(ref Unsafe.As<char, byte>(ref Unsafe.AddByteOffset(ref charB, zero))); if (AllCharsInUInt32AreAscii(num6 | num7)) { if (UInt32OrdinalIgnoreCaseAscii(num6, num7)) { goto IL_00aa; } return false; } break; } case 1: { uint num4 = Unsafe.AddByteOffset(ref charA, zero); uint num5 = Unsafe.AddByteOffset(ref charB, zero); if ((num4 | num5) <= 127) { if (num4 == num5) { return true; } num4 |= 0x20u; if (num4 - 97 > 25) { return false; } return num4 == (num5 | 0x20); } break; } case 0: return true; } break; IL_00aa: zero += 4; length -= 2; } goto IL_0101; IL_0101: return EqualsOrdinalIgnoreCaseNonAscii(ref Unsafe.AddByteOffset(ref charA, zero), ref Unsafe.AddByteOffset(ref charB, zero), length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool AllCharsInUInt32AreAscii(uint value) { return (value & 0xFF80FF80u) == 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool AllCharsInUInt64AreAscii(ulong value) { return (value & 0xFF80FF80FF80FF80uL) == 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool UInt32OrdinalIgnoreCaseAscii(uint valueA, uint valueB) { uint num = valueA ^ valueB; uint num2 = valueA + 16777472 - 4259905; uint num3 = (valueA | 0x200020) + 8388736 - 8061051; return ((((num2 | num3) >> 2) | 0xFFDFFFDFu) & num) == 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool UInt64OrdinalIgnoreCaseAscii(ulong valueA, ulong valueB) { ulong num = valueA + 36029346783166592L - 18296152663326785L; ulong num2 = (valueA | 0x20002000200020L) + 72058693566333184L - 34621950424449147L; ulong num3 = (0x80008000800080L & num & num2) >> 2; return (valueA | num3) == (valueB | num3); } private static bool EqualsOrdinalIgnoreCaseNonAscii(ref char charA, ref char charB, int length) { IntPtr zero = IntPtr.Zero; while (length != 0) { uint num = Unsafe.AddByteOffset(ref charA, zero); uint num2 = Unsafe.AddByteOffset(ref charB, zero); if (num == num2 || ((num | 0x20) == (num2 | 0x20) && (num | 0x20) - 97 <= 25)) { zero += 2; length--; continue; } return false; } return true; } } internal static class MathEx { public static uint DivRem(uint a, uint b, out uint result) { uint num = a / b; result = a - num * b; return num; } public static ulong DivRem(ulong a, ulong b, out ulong result) { ulong num = a / b; result = a - num * b; return num; } public static int DivRem(int a, int b, out int result) { int num = a / b; result = a - num * b; return num; } public static long DivRem(long a, long b, out long result) { long num = a / b; result = a - num * b; return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte Clamp(byte value, byte min, byte max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static decimal Clamp(decimal value, decimal min, decimal max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Clamp(double value, double min, double max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short Clamp(short value, short min, short max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Clamp(int value, int min, int max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Clamp(long value, long min, long max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static sbyte Clamp(sbyte value, sbyte min, sbyte max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Clamp(float value, float min, float max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ushort Clamp(ushort value, ushort min, ushort max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint Clamp(uint value, uint min, uint max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong Clamp(ulong value, ulong min, ulong max) { if (min > max) { ThrowMinMaxException(min, max); } if (value < min) { return min; } if (value > max) { return max; } return value; } private static void ThrowMinMaxException<T>(T min, T max) { throw new ArgumentException($"Argument_MinMaxValue, min:{min} max:{max}"); } } internal static class Number { [StructLayout(LayoutKind.Sequential, Pack = 1)] internal ref struct BigInteger { private const int BitsForLongestBinaryMantissa = 1074; private const int BitsForLongestDigitSequence = 2552; private const int MaxBits = 3658; private const int BitsPerBlock = 32; private const int MaxBlockCount = 115; private static readonly uint[] s_Pow10UInt32Table = new uint[8] { 1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u, 10000000u }; private static readonly int[] s_Pow10BigNumTableIndices = new int[8] { 0, 2, 5, 10, 18, 33, 61, 116 }; private static readonly uint[] s_Pow10BigNumTable = new uint[233] { 1u, 100000000u, 2u, 1874919424u, 2328306u, 4u, 0u, 2242703233u, 762134875u, 1262u, 7u, 0u, 0u, 3211403009u, 1849224548u, 3668416493u, 3913284084u, 1593091u, 14u, 0u, 0u, 0u, 0u, 781532673u, 64985353u, 253049085u, 594863151u, 3553621484u, 3288652808u, 3167596762u, 2788392729u, 3911132675u, 590u, 27u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 2553183233u, 3201533787u, 3638140786u, 303378311u, 1809731782u, 3477761648u, 3583367183u, 649228654u, 2915460784u, 487929380u, 1011012442u, 1677677582u, 3428152256u, 1710878487u, 1438394610u, 2161952759u, 4100910556u, 1608314830u, 349175u, 54u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 4234999809u, 2012377703u, 2408924892u, 1570150255u, 3090844311u, 3273530073u, 1187251475u, 2498123591u, 3364452033u, 1148564857u, 687371067u, 2854068671u, 1883165473u, 505794538u, 2988060450u, 3159489326u, 2531348317u, 3215191468u, 849106862u, 3892080979u, 3288073877u, 2242451748u, 4183778142u, 2995818208u, 2477501924u, 325481258u, 2487842652u, 1774082830u, 1933815724u, 2962865281u, 1168579910u, 2724829000u, 2360374019u, 2315984659u, 2360052375u, 3251779801u, 1664357844u, 28u, 107u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 689565697u, 4116392818u, 1853628763u, 516071302u, 2568769159u, 365238920u, 336250165u, 1283268122u, 3425490969u, 248595470u, 2305176814u, 2111925499u, 507770399u, 2681111421u, 589114268u, 591287751u, 1708941527u, 4098957707u, 475844916u, 3378731398u, 2452339615u, 2817037361u, 2678008327u, 1656645978u, 2383430340u, 73103988u, 448667107u, 2329420453u, 3124020241u, 3625235717u, 3208634035u, 2412059158u, 2981664444u, 4117622508u, 838560765u, 3069470027u, 270153238u, 1802868219u, 3692709886u, 2161737865u, 2159912357u, 2585798786u, 837488486u, 4237238160u, 2540319504u, 3798629246u, 3748148874u, 1021550776u, 2386715342u, 1973637538u, 1823520457u, 1146713475u, 833971519u, 3277251466u, 905620390u, 26278816u, 2680483154u, 2294040859u, 373297482u, 5996609u, 4109575006u, 512575049u, 917036550u, 1942311753u, 2816916778u, 3248920332u, 1192784020u, 3537586671u, 2456567643u, 2925660628u, 759380297u, 888447942u, 3559939476u, 3654687237u, 805u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u }; private int _length; private unsafe fixed uint _blocks[115]; public unsafe static void Add(ref BigInteger lhs, ref BigInteger rhs, out BigInteger result) { ref BigInteger reference = ref lhs._length < rhs._length ? ref rhs : ref lhs; ref BigInteger reference2 = ref lhs._length < rhs._length ? ref lhs : ref rhs; int length = reference._length; int length2 = reference2._length; result._length = length; ulong num = 0uL; int num2 = 0; int num3 = 0; int num4 = 0; while (num3 < length2) { ulong num5 = num + reference._blocks[num2] + reference2._blocks[num3]; num = num5 >> 32; result._blocks[num4] = (uint)num5; num2++; num3++; num4++; } while (num2 < length) { ulong num6 = num + reference._blocks[num2]; num = num6 >> 32; result._blocks[num4] = (uint)num6; num2++; num4++; } if (num != 0L) { result._blocks[num4] = 1u; result._length++; } } public unsafe static int Compare(ref BigInteger lhs, ref BigInteger rhs) { int length = lhs._length; int length2 = rhs._length; int num = length - length2; if (num != 0) { return num; } if (length == 0) { return 0; } for (int num2 = length - 1; num2 >= 0; num2--) { long num3 = (long)lhs._blocks[num2] - (long)rhs._blocks[num2]; if (num3 != 0L) { if (num3 <= 0) { return -1; } return 1; } } return 0; } public static uint CountSignificantBits(uint value) { return (uint)(32 - BitOperations.LeadingZeroCount(value)); } public static uint CountSignificantBits(ulong value) { return (uint)(64 - BitOperations.LeadingZeroCount(value)); } public unsafe static uint CountSignificantBits(ref BigInteger value) { if (value.IsZero()) { return 0u; } uint num = (uint)(value._length - 1); return num * 32 + CountSignificantBits(value._blocks[num]); } public unsafe static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger quo, out BigInteger rem) { if (lhs.IsZero()) { SetZero(out quo); SetZero(out rem); return; } int length = lhs._length; int length2 = rhs._length; if (length == 1 && length2 == 1) { uint result; uint value = MathEx.DivRem(lhs._blocks[0], rhs._blocks[0], out result); SetUInt32(out quo, value); SetUInt32(out rem, result); return; } if (length2 == 1) { int num = length; ulong b = rhs._blocks[0]; ulong result2 = 0uL; for (int num2 = num - 1; num2 >= 0; num2--) { ulong num3 = MathEx.DivRem((result2 << 32) | lhs._blocks[num2], b, out result2); if (num3 == 0L && num2 == num - 1) { num--; } else { quo._blocks[num2] = (uint)num3; } } quo._length = num; SetUInt32(out rem, (uint)result2); return; } if (length2 > length) { SetZero(out quo); SetValue(out rem, ref lhs); return; } int num4 = length - length2 + 1; SetValue(out rem, ref lhs); int num5 = length; uint num6 = rhs._blocks[length2 - 1]; uint num7 = rhs._blocks[length2 - 2]; int num8 = BitOperations.LeadingZeroCount(num6); int num9 = 32 - num8; if (num8 > 0) { num6 = (num6 << num8) | (num7 >> num9); num7 <<= num8; if (length2 > 2) { num7 |= rhs._blocks[length2 - 3] >> num9; } } for (int num10 = length; num10 >= length2; num10--) { int num11 = num10 - length2; uint num12 = ((num10 < length) ? rem._blocks[num10] : 0u); ulong num13 = ((ulong)num12 << 32) | rem._blocks[num10 - 1]; uint num14 = ((num10 > 1) ? rem._blocks[num10 - 2] : 0u); if (num8 > 0) { num13 = (num13 << num8) | (num14 >> num9); num14 <<= num8; if (num10 > 2) { num14 |= rem._blocks[num10 - 3] >> num9; } } ulong num15 = num13 / num6; if (num15 > uint.MaxValue) { num15 = 4294967295uL; } while (DivideGuessTooBig(num15, num13, num14, num6, num7)) { num15--; } if (num15 != 0 && SubtractDivisor(ref rem, num11, ref rhs, num15) != num12) { AddDivisor(ref rem, num11, ref rhs); num15--; } if (num4 != 0) { if (num15 == 0L && num11 == num4 - 1) { num4--; } else { quo._blocks[num11] = (uint)num15; } } if (num10 < num5) { num5--; } } quo._length = num4; for (int num16 = num5 - 1; num16 >= 0; num16--) { if (rem._blocks[num16] == 0) { num5--; } } rem._length = num5; } public unsafe static uint HeuristicDivide(ref BigInteger dividend, ref BigInteger divisor) { int num = divisor._length; if (dividend._length < num) { return 0u; } int num2 = num - 1; uint num3 = dividend._blocks[num2] / (divisor._blocks[num2] + 1); if (num3 != 0) { int num4 = 0; ulong num5 = 0uL; ulong num6 = 0uL; do { ulong num7 = (ulong)((long)divisor._blocks[num4] * (long)num3) + num6; num6 = num7 >> 32; ulong num8 = (ulong)((long)dividend._blocks[num4] - (long)(uint)num7) - num5; num5 = (num8 >> 32) & 1; dividend._blocks[num4] = (uint)num8; num4++; } while (num4 < num); while (num > 0 && dividend._blocks[num - 1] == 0) { num--; } dividend._length = num; } if (Compare(ref dividend, ref divisor) >= 0) { num3++; int num9 = 0; ulong num10 = 0uL; do { ulong num11 = (ulong)((long)dividend._blocks[num9] - (long)divisor._blocks[num9]) - num10; num10 = (num11 >> 32) & 1; dividend._blocks[num9] = (uint)num11; num9++; } while (num9 < num); while (num > 0 && dividend._blocks[num - 1] == 0) { num--; } dividend._length = num; } return num3; } public unsafe static void Multiply(ref BigInteger lhs, uint value, out BigInteger result) { if (!lhs.IsZero()) { switch (value) { case 1u: break; case 0u: SetZero(out result); return; default: { int length = lhs._length; int i = 0; uint num = 0u; for (; i < length; i++) { ulong num2 = (ulong)((long)lhs._blocks[i] * (long)value + num); result._blocks[i] = (uint)num2; num = (uint)(num2 >> 32); } if (num != 0) { result._blocks[i] = num; result._length = length + 1; } else { result._length = length; } return; } } } SetValue(out result, ref lhs); } public unsafe static void Multiply(ref BigInteger lhs, ref BigInteger rhs, out BigInteger result) { if (lhs.IsZero() || rhs.IsOne()) { SetValue(out result, ref lhs); return; } if (rhs.IsZero()) { SetZero(out result); return; } ref BigInteger reference = ref lhs; int length = lhs._length; ref BigInteger reference2 = ref rhs; int length2 = rhs._length; if (length < length2) { reference = ref rhs; length = rhs._length; reference2 = ref lhs; length2 = lhs._length; } int num = (result._length = length2 + length); BufferEx.ZeroMemory((byte*)result.GetBlocksPointer(), (uint)(num * 4)); int num2 = 0; int num3 = 0; while (num2 < length2) { if (reference2._blocks[num2] != 0) { int num4 = 0; int num5 = num3; ulong num6 = 0uL; do { ulong num7 = (ulong)(result._blocks[num5] + (long)reference2._blocks[num2] * (long)reference._blocks[num4]) + num6; num6 = num7 >> 32; result._blocks[num5] = (uint)num7; num5++; num4++; } while (num4 < length); result._blocks[num5] = (uint)num6; } num2++; num3++; } if (num > 0 && result._blocks[num - 1] == 0) { result._length--; } } public unsafe static void Pow2(uint exponent, out BigInteger result) { uint remainder; uint num = DivRem32(exponent, out remainder); result._length = (int)(num + 1); if (num != 0) { BufferEx.ZeroMemory((byte*)result.GetBlocksPointer(), num * 4); } result._blocks[num] = (uint)(1 << (int)remainder); } public unsafe static void Pow10(uint exponent, out BigInteger result) { SetUInt32(out var result2, s_Pow10UInt32Table[exponent & 7]); ref BigInteger reference = ref result2; SetZero(out var result3); ref BigInteger reference2 = ref result3; exponent >>= 3; uint num = 0u; while (exponent != 0) { if ((exponent & (true ? 1u : 0u)) != 0) { fixed (uint* ptr = &s_Pow10BigNumTable[s_Pow10BigNumTableIndices[num]]) { Multiply(ref reference, ref *(BigInteger*)ptr, out reference2); } ref BigInteger reference3 = ref reference2; reference2 = ref reference; reference = ref reference3; } num++; exponent >>= 1; } SetValue(out result, ref reference); } private unsafe static uint AddDivisor(ref BigInteger lhs, int lhsStartIndex, ref BigInteger rhs) { int length = rhs._length; ulong num = 0uL; for (int i = 0; i < length; i++) { ref uint reference = ref lhs._blocks[lhsStartIndex + i]; ulong num2 = reference + num + rhs._blocks[i]; reference = (uint)num2; num = num2 >> 32; } return (uint)num; } private static bool DivideGuessTooBig(ulong q, ulong valHi, uint valLo, uint divHi, uint divLo) { ulong num = divHi * q; ulong num2 = divLo * q; num += num2 >> 32; num2 &= 0xFFFFFFFFu; if (num < valHi) { return false; } if (num > valHi) { return true; } if (num2 < valLo) { return false; } if (num2 > valLo) { return true; } return false; } private unsafe static uint SubtractDivisor(ref BigInteger lhs, int lhsStartIndex, ref BigInteger rhs, ulong q) { int length = rhs._length; ulong num = 0uL; for (int i = 0; i < length; i++) { num += rhs._blocks[i] * q; uint num2 = (uint)num; num >>= 32; ref uint reference = ref lhs._blocks[lhsStartIndex + i]; if (reference < num2) { num++; } reference -= num2; } return (uint)num; } public unsafe void Add(uint value) { int length = _length; if (length == 0) { SetUInt32(out this, value); return; } _blocks[0] += value; if (_blocks[0] >= value) { return; } for (int i = 1; i < length; i++) { ref uint reference = ref _blocks[i]; reference++; if (_blocks[i] != 0) { return; } } _blocks[length] = 1u; _length = length + 1; } public unsafe uint GetBlock(uint index) { return _blocks[index]; } public int GetLength() { return _length; } public unsafe bool IsOne() { if (_length == 1) { return _blocks[0] == 1; } return false; } public bool IsZero() { return _length == 0; } public void Multiply(uint value) { Multiply(ref this, value, out this); } public void Multiply(ref BigInteger value) { SetValue(out var result, ref this); Multiply(ref result, ref value, out this); } public unsafe void Multiply10() { if (!IsZero()) { int i = 0; int length = _length; ulong num = 0uL; for (; i < length; i++) { ulong num2 = _blocks[i]; ulong num3 = (num2 << 3) + (num2 << 1) + num; num = num3 >> 32; _blocks[i] = (uint)num3; } if (num != 0L) { _blocks[i] = (uint)num; _length++; } } } public unsafe void MultiplyPow10(uint exponent) { if (!IsZero()) { Pow10(exponent, out var result); if (result._length == 1) { Multiply(result._blocks[0]); } else { Multiply(ref result); } } } public unsafe static void SetUInt32(out BigInteger result, uint value) { if (value == 0) { SetZero(out result); return; } result._blocks[0] = value; result._length = 1; } public unsafe static void SetUInt64(out BigInteger result, ulong value) { if (value <= uint.MaxValue) { SetUInt32(out result, (uint)value); return; } result._blocks[0] = (uint)value; result._blocks[1] = (uint)(value >> 32); result._length = 2; } public unsafe static void SetValue(out BigInteger result, ref BigInteger value) { BufferEx.Memcpy(len: (result._length = value._length) * 4, dest: (byte*)result.GetBlocksPointer(), src: (byte*)value.GetBlocksPointer()); } public static void SetZero(out BigInteger result) { result._length = 0; } public unsafe void ShiftLeft(uint shift) { int length = _length; if (length == 0 || shift == 0) { return; } uint remainder; uint num = DivRem32(shift, out remainder); int num2 = length - 1; int num3 = num2 + (int)num; if (remainder == 0) { while (num2 >= 0) { _blocks[num3] = _blocks[num2]; num2--; num3--; } _length += (int)num; BufferEx.ZeroMemory((byte*)GetBlocksPointer(), num * 4); return; } num3++; _length = num3 + 1; uint num4 = 32 - remainder; uint num5 = 0u; uint num6 = _blocks[num2]; uint num7 = num6 >> (int)num4; while (num2 > 0) { _blocks[num3] = num5 | num7; num5 = num6 << (int)remainder; num2--; num3--; num6 = _blocks[num2]; num7 = num6 >> (int)num4; } _blocks[num3] = num5 | num7; _blocks[num3 - 1] = num6 << (int)remainder; BufferEx.ZeroMemory((byte*)GetBlocksPointer(), num * 4); if (_blocks[_length - 1] == 0) { _length--; } } public unsafe ulong ToUInt64() { if (_length > 1) { return ((ulong)_blocks[1] << 32) + _blocks[0]; } if (_length > 0) { return _blocks[0]; } return 0uL; } private unsafe uint* GetBlocksPointer() { return (uint*)Unsafe.AsPointer(ref _blocks[0]); } private static uint DivRem32(uint value, out uint remainder) { remainder = value & 0x1Fu; return value >> 5; } } internal readonly ref struct DiyFp { public const int DoubleImplicitBitIndex = 52; public const int SingleImplicitBitIndex = 23; public const int SignificandSize = 64; public readonly ulong f; public readonly int e; public static DiyFp CreateAndGetBoundaries(double value, out DiyFp mMinus, out DiyFp mPlus) { DiyFp result = new DiyFp(value); result.GetBoundaries(52, out mMinus, out mPlus); return result; } public static DiyFp CreateAndGetBoundaries(float value, out DiyFp mMinus, out DiyFp mPlus) { DiyFp result = new DiyFp(value); result.GetBoundaries(23, out mMinus, out mPlus); return result; } public DiyFp(double value) { f = ExtractFractionAndBiasedExponent(value, out e); } public DiyFp(float value) { f = ExtractFractionAndBiasedExponent(value, out e); } public DiyFp(ulong f, int e) { this.f = f; this.e = e; } public DiyFp Multiply(in DiyFp other) { int num = (int)(f >> 32); uint num2 = (uint)f; uint num3 = (uint)(other.f >> 32); uint num4 = (uint)other.f; ulong num5 = (ulong)(uint)num * (ulong)num3; ulong num6 = (ulong)num2 * (ulong)num3; ulong num7 = (ulong)(uint)num * (ulong)num4; ulong num8 = (ulong)(((long)num2 * (long)num4 >>> 32) + (uint)num7 + (uint)num6); num8 += 2147483648u; return new DiyFp(num5 + (num7 >> 32) + (num6 >> 32) + (num8 >> 32), e + other.e + 64); } public DiyFp Normalize() { int num = BitOperations.LeadingZeroCount(f); return new DiyFp(f << num, e - num); } public DiyFp Subtract(in DiyFp other) { return new DiyFp(f - other.f, e); } private void GetBoundaries(int implicitBitIndex, out DiyFp mMinus, out DiyFp mPlus) { mPlus = new DiyFp((f << 1) + 1, e - 1).Normalize(); if (f == (ulong)(1L << implicitBitIndex)) { mMinus = new DiyFp((f << 2) - 1, e - 2); } else { mMinus = new DiyFp((f << 1) - 1, e - 1); } mMinus = new DiyFp(mMinus.f << mMinus.e - mPlus.e, mPlus.e); } } internal static class Grisu3 { private const int CachedPowersDecimalExponentDistance = 8; private const int CachedPowersMinDecimalExponent = -348; private const int CachedPowersPowerMaxDecimalExponent = 340; private const int CachedPowersOffset = 348; private const double D1Log210 = 0.3010299956639812; private const int MaximalTargetExponent = -32; private const int MinimalTargetExponent = -60; private static readonly short[] s_CachedPowersBinaryExponent = new short[87] { -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066 }; private static readonly short[] s_CachedPowersDecimalExponent = new short[87] { -348, -340, -332, -324, -316, -308, -300, -292, -284, -276, -268, -260, -252, -244, -236, -228, -220, -212, -204, -196, -188, -180, -172, -164, -156, -148, -140, -132, -124, -116, -108, -100, -92, -84, -76, -68, -60, -52, -44, -36, -28, -20, -12, -4, 4, 12, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 132, 140, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 228, 236, 244, 252, 260, 268, 276, 284, 292, 300, 308, 316, 324, 332, 340 }; private static readonly ulong[] s_CachedPowersSignificand = new ulong[87] { 18054884314459144840uL, 13451937075301367670uL, 10022474136428063862uL, 14934650266808366570uL, 11127181549972568877uL, 16580792590934885855uL, 12353653155963782858uL, 18408377700990114895uL, 13715310171984221708uL, 10218702384817765436uL, 15227053142812498563uL, 11345038669416679861uL, 16905424996341287883uL, 12595523146049147757uL, 9384396036005875287uL, 13983839803942852151uL, 10418772551374772303uL, 15525180923007089351uL, 11567161174868858868uL, 17236413322193710309uL, 12842128665889583758uL, 9568131466127621947uL, 14257626930069360058uL, 10622759856335341974uL, 15829145694278690180uL, 11793632577567316726uL, 17573882009934360870uL, 13093562431584567480uL, 9755464219737475723uL, 14536774485912137811uL, 10830740992659433045uL, 16139061738043178685uL, 12024538023802026127uL, 17917957937422433684uL, 13349918974505688015uL, 9946464728195732843uL, 14821387422376473014uL, 11042794154864902060uL, 16455045573212060422uL, 12259964326927110867uL, 18268770466636286478uL, 13611294676837538539uL, 10141204801825835212uL, 15111572745182864684uL, 11258999068426240000uL, 16777216000000000000uL, 12500000000000000000uL, 9313225746154785156uL, 13877787807814456755uL, 10339757656912845936uL, 15407439555097886824uL, 11479437019748901445uL, 17105694144590052135uL, 12744735289059618216uL, 9495567745759798747uL, 14149498560666738074uL, 10542197943230523224uL, 15709099088952724970uL, 11704190886730495818uL, 17440603504673385349uL, 12994262207056124023uL, 9681479787123295682uL, 14426529090290212157uL, 10748601772107342003uL, 16016664761464807395uL, 11933345169920330789uL, 17782069995880619868uL, 13248674568444952270uL, 9871031767461413346uL, 14708983551653345445uL, 10959046745042015199uL, 16330252207878254650uL, 12166986024289022870uL, 18130221999122236476uL, 13508068024458167312uL, 10064294952495520794uL, 14996968138956309548uL, 11173611982879273257uL, 16649979327439178909uL, 12405201291620119593uL, 9242595204427927429uL, 13772540099066387757uL, 10261342003245940623uL, 15290591125556738113uL, 11392378155556871081uL, 16975966327722178521uL, 12648080533535911531uL }; private static readonly uint[] s_SmallPowersOfTen = new uint[10] { 1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u, 10000000u, 100000000u, 1000000000u }; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsNegative(double d) { return BitConverter.DoubleToInt64Bits(d) < 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsNegativeInfinity(float f) { return f == float.NegativeInfinity; } public static bool TryRunDouble(double value, int requestedDigits, ref NumberBuffer number) { double value2 = (IsNegative(value) ? (0.0 - value) : value); DiyFp diyFp; bool flag; int length; int decimalExponent; if (requestedDigits == -1) { diyFp = DiyFp.CreateAndGetBoundaries(value2, out var mMinus, out var mPlus); DiyFp w = diyFp.Normalize(); flag = TryRunShortest(in mMinus, in w, in mPlus, number.Digits, out length, out decimalExponent); } else { diyFp = new DiyFp(value2); DiyFp w2 = diyFp.Normalize(); flag = TryRunCounted(in w2, requestedDigits, number.Digits, out length, out decimalExponent); } if (flag) { number.Scale = length + decimalExponent; number.Digits[length] = 0; number.DigitsCount = length; } return flag; } public static bool TryRunSingle(float value, int requestedDigits, ref NumberBuffer number) { float value2 = (IsNegative(value) ? (0f - value) : value); DiyFp diyFp; bool flag; int length; int decimalExponent; if (requestedDigits == -1) { diyFp = DiyFp.CreateAndGetBoundaries(value2, out var mMinus, out var mPlus); DiyFp w = diyFp.Normalize(); flag = TryRunShortest(in mMinus, in w, in mPlus, number.Digits, out length, out decimalExponent); } else { diyFp = new DiyFp(value2); DiyFp w2 = diyFp.Normalize(); flag = TryRunCounted(in w2, requestedDigits, number.Digits, out length, out decimalExponent); } if (flag) { number.Scale = length + decimalExponent; number.Digits[length] = 0; number.DigitsCount = length; } return flag; } private static bool TryRunCounted(in DiyFp w, int requestedDigits, Span<byte> buffer, out int length, out int decimalExponent) { int minExponent = -60 - (w.e + 64); int maxExponent = -32 - (w.e + 64); int decimalExponent2; DiyFp other = GetCachedPowerForBinaryExponentRange(minExponent, maxExponent, out decimalExponent2); DiyFp w2 = w.Multiply(in other); int kappa; bool result = TryDigitGenCounted(in w2, requestedDigits, buffer, out length, out kappa); decimalExponent = -decimalExponent2 + kappa; return result; } private static bool TryRunShortest(in DiyFp boundaryMinus, in DiyFp w, in DiyFp boundaryPlus, Span<byte> buffer, out int length, out int decimalExponent) { int minExponent = -60 - (w.e + 64); int maxExponent = -32 - (w.e + 64); int decimalExponent2; DiyFp other = GetCachedPowerForBinaryExponentRange(minExponent, maxExponent, out decimalExponent2); DiyFp w2 = w.Multiply(in other); DiyFp low = boundaryMinus.Multiply(in other); DiyFp high = boundaryPlus.Multiply(in other); int kappa; bool result = TryDigitGenShortest(in low, in w2, in high, buffer, out length, out kappa); decimalExponent = -decimalExponent2 + kappa; return result; } private static uint BiggestPowerTen(uint number, int numberBits, out int exponentPlusOne) { int num = (numberBits + 1) * 1233 >> 12; uint num2 = s_SmallPowersOfTen[num]; if (number < num2) { num--; num2 = s_SmallPowersOfTen[num]; } exponentPlusOne = num + 1; return num2; } private static bool TryDigitGenCounted(in DiyFp w, int requestedDigits, Span<byte> buffer, out int length, out int kappa) { ulong num = 1uL; DiyFp diyFp = new DiyFp((ulong)(1L << -w.e), w.e); uint result = (uint)(w.f >> -diyFp.e); ulong num2 = w.f & (diyFp.f - 1); if (num2 == 0L && (requestedDigits >= 11 || result < s_SmallPowersOfTen[requestedDigits - 1])) { length = 0; kappa = 0; return false; } uint num3 = BiggestPowerTen(result, 64 - -diyFp.e, out kappa); length = 0; while (kappa > 0) { uint num4 = MathEx.DivRem(result, num3, out result); buffer[length] = (byte)(48 + num4); length++; requestedDigits--; kappa--; if (requestedDigits == 0) { break; } num3 /= 10; } if (requestedDigits == 0) { ulong rest = ((ulong)result << -diyFp.e) + num2; return TryRoundWeedCounted(buffer, length, rest, (ulong)num3 << -diyFp.e, num, ref kappa); } while (requestedDigits > 0 && num2 > num) { num2 *= 10; num *= 10; uint num5 = (uint)(num2 >> -diyFp.e); buffer[length] = (byte)(48 + num5); length++; requestedDigits--; kappa--; num2 &= diyFp.f - 1; } if (requestedDigits != 0) { buffer[0] = 0; length = 0; kappa = 0; return false; } return TryRoundWeedCounted(buffer, length, num2, diyFp.f, num, ref kappa); } private static bool TryDigitGenShortest(in DiyFp low, in DiyFp w, in DiyFp high, Span<byte> buffer, out int length, out int kappa) { ulong num = 1uL; DiyFp other = new DiyFp(low.f - num, low.e); DiyFp diyFp = new DiyFp(high.f + num, high.e); DiyFp diyFp2 = diyFp.Subtract(in other); DiyFp diyFp3 = new DiyFp((ulong)(1L << -w.e), w.e); uint result = (uint)(diyFp.f >> -diyFp3.e); ulong num2 = diyFp.f & (diyFp3.f - 1); uint num3 = BiggestPowerTen(result, 64 - -diyFp3.e, out kappa); length = 0; while (kappa > 0) { uint num4 = MathEx.DivRem(result, num3, out result); buffer[length] = (byte)(48 + num4); length++; kappa--; ulong num5 = ((ulong)result << -diyFp3.e) + num2; if (num5 < diyFp2.f) { return TryRoundWeedShortest(buffer, length, diyFp.Subtract(in w).f, diyFp2.f, num5, (ulong)num3 << -diyFp3.e, num); } num3 /= 10; } do { num2 *= 10; num *= 10; diyFp2 = new DiyFp(diyFp2.f * 10, diyFp2.e); uint num6 = (uint)(num2 >> -diyFp3.e); buffer[length] = (byte)(48 + num6); length++; kappa--; num2 &= diyFp3.f - 1; } while (num2 >= diyFp2.f); return TryRoundWeedShortest(buffer, length, diyFp.Subtract(in w).f * num, diyFp2.f, num2, diyFp3.f, num); } private static DiyFp GetCachedPowerForBinaryExponentRange(int minExponent, int maxExponent, out int decimalExponent) { double num = Math.Ceiling((double)(minExponent + 64 - 1) * 0.3010299956639812); int num2 = (348 + (int)num - 1) / 8 + 1; decimalExponent = s_CachedPowersDecimalExponent[num2]; return new DiyFp(s_CachedPowersSignificand[num2], s_CachedPowersBinaryExponent[num2]); } private static bool TryRoundWeedCounted(Span<byte> buffer, int length, ulong rest, ulong tenKappa, ulong unit, ref int kappa) { if (unit >= tenKappa || tenKappa - unit <= unit) { return false; } if (tenKappa - rest > rest && tenKappa - 2 * rest >= 2 * unit) { return true; } if (rest > unit && (tenKappa <= rest - unit || tenKappa - (rest - unit) <= rest - unit)) { buffer[length - 1]++; int num = length - 1; while (num > 0 && buffer[num] == 58) { buffer[num] = 48; buffer[num - 1]++; num--; } if (buffer[0] == 58) { buffer[0] = 49; kappa++; } return true; } return false; } private static bool TryRoundWeedShortest(Span<byte> buffer, int length, ulong distanceTooHighW, ulong unsafeInterval, ulong rest, ulong tenKappa, ulong unit) { ulong num = distanceTooHighW - unit; ulong num2 = distanceTooHighW + unit; while (rest < num && unsafeInterval - rest >= tenKappa && (rest + tenKappa < num || num - rest >= rest + tenKappa - num)) { buffer[length - 1]--; rest += tenKappa; } if (rest < num2 && unsafeInterval - rest >= tenKappa && (rest + tenKappa < num2 || num2 - rest > rest + tenKappa - num2)) { return false; } if (2 * unit <= rest) { return rest <= unsafeInterval - 4 * unit; } return false; } } internal ref struct NumberBuffer { public int DigitsCount; public int Scale; public bool IsNegative; public bool HasNonZeroTail; public NumberBufferKind Kind; public Span<byte> Digits; public unsafe NumberBuffer(NumberBufferKind kind, byte* digits, int digitsLength) { DigitsCount = 0; Scale = 0; IsNegative = false; HasNonZeroTail = false; Kind = kind; Digits = new Span<byte>(digits, digitsLength); Digits[0] = 0; } [Conditional("DEBUG")] public void CheckConsistency() { } public unsafe byte* GetDigitsPointer() { return (byte*)Unsafe.AsPointer(ref Digits[0]); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append('['); stringBuilder.Append('"'); for (int i = 0; i < Digits.Length; i++) { byte b = Digits[i]; if (b == 0) { break; } stringBuilder.Append((char)b); } stringBuilder.Append('"'); stringBuilder.Append(", Length = ").Append(DigitsCount); stringBuilder.Append(", Scale = ").Append(Scale); stringBuilder.Append(", IsNegative = ").Append(IsNegative); stringBuilder.Append(", HasNonZeroTail = ").Append(HasNonZeroTail); stringBuilder.Append(", Kind = ").Append(Kind); stringBuilder.Append(']'); return stringBuilder.ToString(); } } internal enum NumberBufferKind : byte { Unknown, Integer, Decimal, FloatingPoint } public readonly struct FloatingPointInfo { public static readonly FloatingPointInfo Double = new FloatingPointInfo(52, 11, 1023, 1023, 9218868437227405312uL); public static readonly FloatingPointInfo Single = new FloatingPointInfo(23, 8, 127, 127, 2139095040uL); public ulong ZeroBits { get; } public ulong InfinityBits { get; } public ulong NormalMantissaMask { get; } public ulong DenormalMantissaMask { get; } public int MinBinaryExponent { get; } public int MaxBinaryExponent { get; } public int ExponentBias { get; } public int OverflowDecimalExponent { get; } public ushort NormalMantissaBits { get; } public ushort DenormalMantissaBits { get; } public ushort ExponentBits { get; } public FloatingPointInfo(ushort denormalMantissaBits, ushort exponentBits, int maxBinaryExponent, int exponentBias, ulong infinityBits) { ExponentBits = exponentBits; DenormalMantissaBits = denormalMantissaBits; NormalMantissaBits = (ushort)(denormalMantissaBits + 1); OverflowDecimalExponent = (maxBinaryExponent + 2 * NormalMantissaBits) / 3; ExponentBias = exponentBias; MaxBinaryExponent = maxBinaryExponent; MinBinaryExponent = 1 - maxBinaryExponent; DenormalMantissaMask = (ulong)((1L << (int)denormalMantissaBits) - 1); NormalMantissaMask = (ulong)((1L << (int)NormalMantissaBits) - 1); InfinityBits = infinityBits; ZeroBits = 0uL; } } internal enum ParsingStatus { OK, Failed, Overflow } internal const int DecimalPrecision = 29; private const int SinglePrecision = 9; private const int DoublePrecision = 17; private const int SinglePrecisionCustomFormat = 7; private const int DoublePrecisionCustomFormat = 15; private const int DefaultPrecisionExponentialFormat = 6; private const int MaxUInt32DecDigits = 10; private const int CharStackBufferSize = 32; private const string PosNumberFormat = "#"; private static readonly string[] s_singleDigitStringCache = new string[10] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; private static readonly string[] s_posCurrencyFormats = new string[4] { "$#", "#$", "$ #", "# $" }; private static readonly string[] s_negCurrencyFormats = new string[16] { "($#)", "-$#", "$-#", "$#-", "(#$)", "-#$", "#-$", "#$-", "-# $", "-$ #", "# $-", "$ #-", "$ -#", "#- $", "($ #)", "(# $)" }; private static readonly string[] s_posPercentFormats = new string[4] { "# %", "#%", "%#", "% #" }; private static readonly string[] s_negPercentFormats = new string[12] { "-# %", "-#%", "-%#", "%-#", "%#-", "#-%", "#%-", "-% #", "# %-", "% #-", "% -#", "#- %" }; private static readonly string[] s_negNumberFormats = new string[5] { "(#)", "-#", "- #", "#-", "# -" }; internal const int DecimalNumberBufferLength = 31; internal const int DoubleNumberBufferLength = 769; internal const int Int32NumberBufferLength = 11; internal const int Int64NumberBufferLength = 20; internal const int SingleNumberBufferLength = 114; internal const int UInt32NumberBufferLength = 11; internal const int UInt64NumberBufferLength = 21; private static readonly float[] s_Pow10SingleTable = new float[11] { 1f, 10f, 100f, 1000f, 10000f, 100000f, 1000000f, 10000000f, 100000000f, 1E+09f, 1E+10f }; private static readonly double[] s_Pow10DoubleTable = new double[23] { 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0, 100000000000000.0, 1000000000000000.0, 10000000000000000.0, 1E+17, 1E+18, 1E+19, 1E+20, 1E+21, 1E+22 }; private const int Int32Precision = 10; private const int UInt32Precision = 10; private const int Int64Precision = 19; private const int UInt64Precision = 20; private const int DoubleMaxExponent = 309; private const int DoubleMinExponent = -324; private const int FloatingPointMaxExponent = 309; private const int FloatingPointMinExponent = -324; private const int SingleMaxExponent = 39; private const int SingleMinExponent = -45; internal static ReadOnlySpan<byte> CharToHexLookup => new byte[103] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15 }; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsNegative(double d) { return BitConverter.DoubleToInt64Bits(d) < 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNegativeInfinity(float f) { return f == float.NegativeInfinity; } public static void Dragon4Double(double value, int cutoffNumber, bool isSignificantDigits, ref NumberBuffer number) { IsNegative(value); int exponent; ulong num = ExtractFractionAndBiasedExponent(value, out exponent); bool hasUnequalMargins = false; uint mantissaHighBitIdx; if (num >> 52 != 0L) { mantissaHighBitIdx = 52u; hasUnequalMargins = num == 4503599627370496L; } else { mantissaHighBitIdx = (uint)BitOperations.Log2(num); } int decimalExponent; int num2 = (int)Dragon4(num, exponent, mantissaHighBitIdx, hasUnequalMargins, cutoffNumber, isSignificantDigits, number.Digits, out decimalExponent); number.Scale = decimalExponent + 1; number.Digits[num2] = 0; number.DigitsCount = num2; } public static void Dragon4Single(float value, int cutoffNumber, bool isSignificantDigits, ref NumberBuffer number) { IsNegative(value); int exponent; uint num = ExtractFractionAndBiasedExponent(value, out exponent); bool hasUnequalMargins = false; uint mantissaHighBitIdx; if (num >> 23 != 0) { mantissaHighBitIdx = 23u; hasUnequalMargins = num == 8388608; } else { mantissaHighBitIdx = (uint)BitOperations.Log2(num); } int decimalExponent; int num2 = (int)Dragon4(num, exponent, mantissaHighBitIdx, hasUnequalMargins, cutoffNumber, isSignificantDigits, number.Digits, out decimalExponent); number.Scale = decimalExponent + 1; number.Digits[num2] = 0; number.DigitsCount = num2; } private unsafe static uint Dragon4(ulong mantissa, int exponent, uint mantissaHighBitIdx, bool hasUnequalMargins, int cutoffNumber, bool isSignificantDigits, Span<byte> buffer, out int decimalExponent) { int num = 0; BigInteger result; BigInteger result2; BigInteger result3; BigInteger* ptr; if (hasUnequalMargins) { BigInteger result4; if (exponent > 0) { BigInteger.SetUInt64(out result, 4 * mantissa); result.ShiftLeft((uint)exponent); BigInteger.SetUInt32(out result2, 4u); BigInteger.Pow2((uint)exponent, out result3); BigInteger.Pow2((uint)(exponent + 1), out result4); } else { BigInteger.SetUInt64(out result, 4 * mantissa); BigInteger.Pow2((uint)(-exponent + 2), out result2); BigInteger.SetUInt32(out result3, 1u); BigInteger.SetUInt32(out result4, 2u); } ptr = &result4; } else { if (exponent > 0) { BigInteger.SetUInt64(out result, 2 * mantissa); result.ShiftLeft((uint)exponent); BigInteger.SetUInt32(out result2, 2u); BigInteger.Pow2((uint)exponent, out result3); } else { BigInteger.SetUInt64(out result, 2 * mantissa); BigInteger.Pow2((uint)(-exponent + 1), out result2); BigInteger.SetUInt32(out result3, 1u); } ptr = &result3; } int num2 = (int)Math.Ceiling((double)((int)mantissaHighBitIdx + exponent) * 0.3010299956639812 - 0.69); if (num2 > 0) { result2.MultiplyPow10((uint)num2); } else if (num2 < 0) { BigInteger.Pow10((uint)(-num2), out var result5); result.Multiply(ref result5); result3.Multiply(ref result5); if (ptr != &result3) { BigInteger.Multiply(ref result3, 2u, out *ptr); } } bool flag = mantissa % 2 == 0; bool flag2 = false; if (cutoffNumber == -1) { BigInteger.Add(ref result, ref *ptr, out var result6); int num3 = BigInteger.Compare(ref result6, ref result2); flag2 = (flag ? (num3 >= 0) : (num3 > 0)); } else { flag2 = BigInteger.Compare(ref result, ref result2) >= 0; } if (flag2) { num2++; } else { result.Multiply10(); result3.Multiply10(); if (ptr != &result3) { BigInteger.Multiply(ref result3, 2u, out *ptr); } } int num4 = num2 - buffer.Length; if (cutoffNumber != -1) { int num5 = 0; num5 = ((!isSignificantDigits) ? (-cutoffNumber) : (num2 - cutoffNumber)); if (num5 > num4) { num4 = num5; } } num2 = (decimalExponent = num2 - 1); uint block = result2.GetBlock((uint)(result2.GetLength() - 1)); if (block < 8 || block > 429496729) { uint num6 = (uint)BitOperations.Log2(block); uint shift = (59 - num6) % 32; result2.ShiftLeft(shift); result.ShiftLeft(shift); result3.ShiftLeft(shift); if (ptr != &result3) { BigInteger.Multiply(ref result3, 2u, out *ptr); } } bool flag3; bool flag4; uint num7; if (cutoffNumber == -1) { while (true) { num7 = BigInteger.HeuristicDivide(ref result, ref result2); BigInteger.Add(ref result, ref *ptr, out var result7); int num8 = BigInteger.Compare(ref result, ref result3); int num9 = BigInteger.Compare(ref result7, ref result2); if (flag) { flag3 = num8 <= 0; flag4 = num9 >= 0; } else { flag3 = num8 < 0; flag4 = num9 > 0; } if (flag3 || flag4 || num2 == num4) { break; } buffer[num] = (byte)(48 + num7); num++; result.Multiply10(); result3.Multiply10(); if (ptr != &result3) { BigInteger.Multiply(ref result3, 2u, out *ptr); } num2--; } } else { if (num2 < num4) { num7 = BigInteger.HeuristicDivide(ref result, ref result2); if (num7 > 5 || (num7 == 5 && !result.IsZero())) { decimalExponent++; num7 = 1u; } buffer[num] = (byte)(48 + num7); return (uint)(num + 1); } flag3 = false; flag4 = false; while (true) { num7 = BigInteger.HeuristicDivide(ref result, ref result2); if (result.IsZero() || num2 <= num4) { break; } buffer[num] = (byte)(48 + num7); num++; result.Multiply10(); num2--; } } bool flag5 = flag3; if (flag3 == flag4) { result.ShiftLeft(1u); int num10 = BigInteger.Compare(ref result, ref result2); flag5 = num10 < 0; if (num10 == 0) { flag5 = (num7 & 1) == 0; } } if (flag5) { buffer[num] = (byte)(48 + num7); num++; } else if (num7 == 9) { while (true) { if (num == 0) { buffer[num] = 49; num++; decimalExponent++; break; } num--; if (buffer[num] != 57) { buffer[num]++; num++; break; } } } else { buffer[num] = (byte)(48 + num7 + 1); num++; } return (uint)num; } public unsafe static string FormatDecimal(decimal value, ReadOnlySpan<char> format, NumberFormatInfo info) { int digits; char c = ParseFormatSpecifier(format, out digits); byte* digits2 = stackalloc byte[31]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, digits2, 31); DecimalToNumber(ref value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, info); } else { NumberToStringFormat(ref sb, ref number, format, info); } return sb.ToString(); } public unsafe static bool TryFormatDecimal(decimal value, ReadOnlySpan<char> format, NumberFormatInfo info, Span<char> destination, out int charsWritten) { int digits; char c = ParseFormatSpecifier(format, out digits); byte* digits2 = stackalloc byte[31]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, digits2, 31); DecimalToNumber(ref value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, info); } else { NumberToStringFormat(ref sb, ref number, format, info); } return sb.TryCopyTo(destination, out charsWritten); } internal unsafe static void DecimalToNumber(ref decimal d, ref NumberBuffer number) { byte* digitsPointer = number.GetDigitsPointer(); number.DigitsCount = 29; number.IsNegative = d.IsNegative(); byte* bufferEnd = digitsPointer + 29; while ((d.Mid() | d.High()) != 0) { bufferEnd = UInt32ToDecChars(bufferEnd, DecimalEx.DecDivMod1E9(ref d), 9); } bufferEnd = UInt32ToDecChars(bufferEnd, d.Low(), 0); int num = (number.DigitsCount = (int)(digitsPointer + 29 - bufferEnd)); number.Scale = num - d.Scale(); byte* digitsPointer2 = number.GetDigitsPointer(); while (--num >= 0) { *(digitsPointer2++) = *(bufferEnd++); } *digitsPointer2 = 0; } public static string FormatDouble(double value, string format, NumberFormatInfo info) { Span<char> initialBuffer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(initialBuffer); return FormatDouble(ref sb, value, format.AsSpan(), info) ?? sb.ToString(); } public static bool TryFormatDouble(double value, ReadOnlySpan<char> format, NumberFormatInfo info, Span<char> destination, out int charsWritten) { Span<char> initialBuffer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(initialBuffer); string text = FormatDouble(ref sb, value, format, info); if (text == null) { return sb.TryCopyTo(destination, out charsWritten); } return TryCopyTo(text, destination, out charsWritten); } private static int GetFloatingPointMaxDigitsAndPrecision(char fmt, ref int precision, NumberFormatInfo info, out bool isSignificantDigits) { if (fmt == '\0') { isSignificantDigits = true; return precision; } int result = precision; switch (fmt) { case 'C': case 'c': if (precision == -1) { precision = info.CurrencyDecimalDigits; } isSignificantDigits = false; break; case 'E': case 'e': if (precision == -1) { precision = 6; } precision++; isSignificantDigits = true; break; case 'F': case 'N': case 'f': case 'n': if (precision == -1) { precision = info.NumberDecimalDigits; } isSignificantDigits = false; break; case 'G': case 'g': if (precision == 0) { precision = -1; } isSignificantDigits = true; break; case 'P': case 'p': if (precision == -1) { precision = info.PercentDecimalDigits; } precision += 2; isSignificantDigits = false; break; case 'R': case 'r': precision = -1; isSignificantDigits = true; break; default: throw new FormatException("SR.Argument_BadFormatSpecifier"); } return result; } private unsafe static string FormatDouble(ref System.Text.ValueStringBuilder sb, double value, ReadOnlySpan<char> format, NumberFormatInfo info) { if (!FloatEx.IsFinite(value)) { if (double.IsNaN(value)) { return info.NaNSymbol; } if (!FloatEx.IsNegative(value)) { return info.PositiveInfinitySymbol; } return info.NegativeInfinitySymbol; } int digits; char c = ParseFormatSpecifier(format, out digits); byte* digits2 = stackalloc byte[769]; if (c == '\0') { digits = 15; } NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, digits2, 769); number.IsNegative = FloatEx.IsNegative(value); bool isSignificantDigits; int nMaxDigits = GetFloatingPointMaxDigitsAndPrecision(c, ref digits, info, out isSignificantDigits); if (value != 0.0 && (!isSignificantDigits || !Grisu3.TryRunDouble(value, digits, ref number))) { Dragon4Double(value, digits, isSignificantDigits, ref number); } if (c != 0) { if (digits == -1) { nMaxDigits = Math.Max(number.DigitsCount, 17); } NumberToString(ref sb, ref number, c, nMaxDigits, info); } else { NumberToStringFormat(ref sb, ref number, format, info); } return null; } public static string FormatSingle(float value, string format, NumberFormatInfo info) { Span<char> initialBuffer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(initialBuffer); return FormatSingle(ref sb, value, format.AsSpan(), info) ?? sb.ToString(); } public static bool TryFormatSingle(float value, ReadOnlySpan<char> format, NumberFormatInfo info, Span<char> destination, out int charsWritten) { Span<char> initialBuffer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(initialBuffer); string text = FormatSingle(ref sb, value, format, info); if (text == null) { return sb.TryCopyTo(destination, out charsWritten); } return TryCopyTo(text, destination, out charsWritten); } private unsafe static string FormatSingle(ref System.Text.ValueStringBuilder sb, float value, ReadOnlySpan<char> format, NumberFormatInfo info) { if (!FloatEx.IsFinite(value)) { if (float.IsNaN(value)) { return info.NaNSymbol; } if (!FloatEx.IsNegative(value)) { return info.PositiveInfinitySymbol; } return info.NegativeInfinitySymbol; } int digits; char c = ParseFormatSpecifier(format, out digits); byte* digits2 = stackalloc byte[114]; if (c == '\0') { digits = 7; } NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, digits2, 114); number.IsNegative = FloatEx.IsNegative(value); bool isSignificantDigits; int nMaxDigits = GetFloatingPointMaxDigitsAndPrecision(c, ref digits, info, out isSignificantDigits); if (value != 0f && (!isSignificantDigits || !Grisu3.TryRunSingle(value, digits, ref number))) { Dragon4Single(value, digits, isSignificantDigits, ref number); } if (c != 0) { if (digits == -1) { nMaxDigits = Math.Max(number.DigitsCount, 9); } NumberToString(ref sb, ref number, c, nMaxDigits, info); } else { NumberToStringFormat(ref sb, ref number, format, info); } return null; } private static bool TryCopyTo(string source, Span<char> destination, out int charsWritten) { if (source.AsSpan().TryCopyTo(destination)) { charsWritten = source.Length; return true; } charsWritten = 0; return false; } public unsafe static string FormatInt32(int value, ReadOnlySpan<char> format, IFormatProvider provider) { if (value >= 0 && format.Length == 0) { return UInt32ToDecStr((uint)value, -1); } int digits; char c = ParseFormatSpecifier(format, out digits); char c2 = (char)(c & 0xFFDFu); if (c2 != 'G' || digits >= 1) { switch (c2) { case 'D': break; case 'X': return Int32ToHexStr(value, (char)(c - 33), digits); default: { NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider); byte* digits2 = stackalloc byte[11]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, digits2, 11); Int32ToNumber(value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, instance); } else { NumberToStringFormat(ref sb, ref number, format, instance); } return sb.ToString(); } } } if (value < 0) { return NegativeInt32ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign); } return UInt32ToDecStr((uint)value, digits); } public unsafe static bool TryFormatInt32(int value, ReadOnlySpan<char> format, IFormatProvider provider, Span<char> destination, out int charsWritten) { if (value >= 0 && format.Length == 0) { return TryUInt32ToDecStr((uint)value, -1, destination, out charsWritten); } int digits; char c = ParseFormatSpecifier(format, out digits); char c2 = (char)(c & 0xFFDFu); if (c2 != 'G' || digits >= 1) { switch (c2) { case 'D': break; case 'X': return TryInt32ToHexStr(value, (char)(c - 33), digits, destination, out charsWritten); default: { NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider); byte* digits2 = stackalloc byte[11]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, digits2, 11); Int32ToNumber(value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, instance); } else { NumberToStringFormat(ref sb, ref number, format, instance); } return sb.TryCopyTo(destination, out charsWritten); } } } if (value < 0) { return TryNegativeInt32ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign, destination, out charsWritten); } return TryUInt32ToDecStr((uint)value, digits, destination, out charsWritten); } public unsafe static string FormatUInt32(uint value, ReadOnlySpan<char> format, IFormatProvider provider) { if (format.Length == 0) { return UInt32ToDecStr(value, -1); } int digits; char c = ParseFormatSpecifier(format, out digits); char c2 = (char)(c & 0xFFDFu); if (c2 != 'G' || digits >= 1) { switch (c2) { case 'D': break; case 'X': return Int32ToHexStr((int)value, (char)(c - 33), digits); default: { NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider); byte* digits2 = stackalloc byte[11]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, digits2, 11); UInt32ToNumber(value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, instance); } else { NumberToStringFormat(ref sb, ref number, format, instance); } return sb.ToString(); } } } return UInt32ToDecStr(value, digits); } public unsafe static bool TryFormatUInt32(uint value, ReadOnlySpan<char> format, IFormatProvider provider, Span<char> destination, out int charsWritten) { if (format.Length == 0) { return TryUInt32ToDecStr(value, -1, destination, out charsWritten); } int digits; char c = ParseFormatSpecifier(format, out digits); char c2 = (char)(c & 0xFFDFu); if (c2 != 'G' || digits >= 1) { switch (c2) { case 'D': break; case 'X': return TryInt32ToHexStr((int)value, (char)(c - 33), digits, destination, out charsWritten); default: { NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider); byte* digits2 = stackalloc byte[11]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, digits2, 11); UInt32ToNumber(value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, instance); } else { NumberToStringFormat(ref sb, ref number, format, instance); } return sb.TryCopyTo(destination, out charsWritten); } } } return TryUInt32ToDecStr(value, digits, destination, out charsWritten); } public unsafe static string FormatInt64(long value, ReadOnlySpan<char> format, IFormatProvider provider) { if (value >= 0 && format.Length == 0) { return UInt64ToDecStr((ulong)value, -1); } int digits; char c = ParseFormatSpecifier(format, out digits); char c2 = (char)(c & 0xFFDFu); if (c2 != 'G' || digits >= 1) { switch (c2) { case 'D': break; case 'X': return Int64ToHexStr(value, (char)(c - 33), digits); default: { NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider); byte* digits2 = stackalloc byte[20]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, digits2, 20); Int64ToNumber(value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, instance); } else { NumberToStringFormat(ref sb, ref number, format, instance); } return sb.ToString(); } } } if (value < 0) { return NegativeInt64ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign); } return UInt64ToDecStr((ulong)value, digits); } public unsafe static bool TryFormatInt64(long value, ReadOnlySpan<char> format, IFormatProvider provider, Span<char> destination, out int charsWritten) { if (value >= 0 && format.Length == 0) { return TryUInt64ToDecStr((ulong)value, -1, destination, out charsWritten); } int digits; char c = ParseFormatSpecifier(format, out digits); char c2 = (char)(c & 0xFFDFu); if (c2 != 'G' || digits >= 1) { switch (c2) { case 'D': break; case 'X': return TryInt64ToHexStr(value, (char)(c - 33), digits, destination, out charsWritten); default: { NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider); byte* digits2 = stackalloc byte[20]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, digits2, 20); Int64ToNumber(value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, instance); } else { NumberToStringFormat(ref sb, ref number, format, instance); } return sb.TryCopyTo(destination, out charsWritten); } } } if (value < 0) { return TryNegativeInt64ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign, destination, out charsWritten); } return TryUInt64ToDecStr((ulong)value, digits, destination, out charsWritten); } public unsafe static string FormatUInt64(ulong value, ReadOnlySpan<char> format, IFormatProvider provider) { if (format.Length == 0) { return UInt64ToDecStr(value, -1); } int digits; char c = ParseFormatSpecifier(format, out digits); char c2 = (char)(c & 0xFFDFu); if (c2 != 'G' || digits >= 1) { switch (c2) { case 'D': break; case 'X': return Int64ToHexStr((long)value, (char)(c - 33), digits); default: { NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider); byte* digits2 = stackalloc byte[21]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, digits2, 21); UInt64ToNumber(value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, instance); } else { NumberToStringFormat(ref sb, ref number, format, instance); } return sb.ToString(); } } } return UInt64ToDecStr(value, digits); } public unsafe static bool TryFormatUInt64(ulong value, ReadOnlySpan<char> format, IFormatProvider provider, Span<char> destination, out int charsWritten) { if (format.Length == 0) { return TryUInt64ToDecStr(value, -1, destination, out charsWritten); } int digits; char c = ParseFormatSpecifier(format, out digits); char c2 = (char)(c & 0xFFDFu); if (c2 != 'G' || digits >= 1) { switch (c2) { case 'D': break; case 'X': return TryInt64ToHexStr((long)value, (char)(c - 33), digits, destination, out charsWritten); default: { NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider); byte* digits2 = stackalloc byte[21]; NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, digits2, 21); UInt64ToNumber(value, ref number); char* pointer = stackalloc char[32]; System.Text.ValueStringBuilder sb = new System.Text.ValueStringBuilder(new Span<char>(pointer, 32)); if (c != 0) { NumberToString(ref sb, ref number, c, digits, instance); } else { NumberToStringFormat(ref sb, ref number, format, instance); } return sb.TryCopyTo(destination, out charsWritten); } } } return TryUInt64ToDecStr(value, digits, destination, out charsWritten); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private unsafe static void Int32ToNumber(int value, ref NumberBuffer number) { number.DigitsCount = 10; if (value >= 0) { number.IsNegative = false; } else { number.IsNegative = true; value = -value; } byte* digitsPointer = number.GetDigitsPointer(); byte* ptr = UInt32ToDecChars(digitsPointer + 10, (uint)value, 0); int num = (number.Scale = (number.DigitsCount = (int)(digitsPointer + 10 - ptr))); byte* digitsPointer2 = number.GetDigitsPointer(); while (--num >= 0) { *(digitsPointer2++) = *(ptr++); } *digitsPointer2 = 0; } private unsafe static string NegativeInt32ToDecStr(int value, int digits, string sNegative) { if (digits < 1) { digits = 1; } int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountDigits((uint)(-value))) + sNegative.Length; string text = FastAllocateString(num); fixed (char* ptr = text) { char* ptr2 = UInt32ToDecChars(ptr + num, (uint)(-value), digits); for (int num2 = sNegative.Length - 1; num2 >= 0; num2--) { *(--ptr2) = sNegative[num2]; } } return text; } private unsafe static bool TryNegativeInt32ToDecStr(int value, int digits, string sNegative, Span<char> destination, out int charsWritten) { if (digits < 1) { digits = 1; } int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountDigits((uint)(-value))) + sNegative.Length; if (num > destination.Length) { charsWritten = 0; return false; } charsWritten = num; fixed (char* ptr = &MemoryMarshal.GetReference(destination)) { char* ptr2 = UInt32ToDecChars(ptr + num, (uint)(-value), digits); for (int num2 = sNegative.Length - 1; num2 >= 0; num2--) { *(--ptr2) = sNegative[num2]; } } return true; } private unsafe static string Int32ToHexStr(int value, char hexBase, int digits) { if (digits < 1) { digits = 1; } int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountHexDigits((uint)value)); string text = FastAllocateString(num); fixed (char* ptr = text) { Int32ToHexChars(ptr + num, (uint)value, hexBase, digits); } return text; } private unsafe static bool TryInt32ToHexStr(int value, char hexBase, int digits, Span<char> destination, out int charsWritten) { if (digits < 1) { digits = 1; } int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountHexDigits((uint)value)); if (num > destination.Length) { charsWritten = 0; return false; } charsWritten = num; fixed (char* ptr = &MemoryMarshal.GetReference(destination)) { Int32ToHexChars(ptr + num, (uint)value, hexBase, digits); } return true; } private unsafe static char* Int32ToHexChars(char* buffer, uint value, int hexBase, int digits) { while (--digits >= 0 || value != 0) { byte b = (byte)(value & 0xFu); *(--buffer) = (char)(b + ((b < 10) ? 48 : hexBase)); value >>= 4; } return buffer; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private unsafe static void UInt32ToNumber(uint value, ref NumberBuffer number) { number.DigitsCount = 10; number.IsNegative = false; byte* digitsPointer = number.GetDigitsPointer(); byte* ptr = UInt32ToDecChars(digitsPointer + 10, value, 0); int num = (number.Scale = (number.DigitsCount = (int)(digitsPointer + 10 - ptr))); byte* digitsPointer2 = number.GetDigitsPointer(); while (--num >= 0) { *(digitsPointer2++) = *(ptr++); } *digitsPointer2 = 0; } internal unsafe static byte* UInt32ToDecChars(byte* bufferEnd, uint value, int digits) { while (--digits >= 0 || value != 0) { value = MathEx.DivRem(value, 10u, out var result); *(--bufferEnd) = (byte)(result + 48); } return bufferEnd; } internal unsafe static char* UInt32ToDecChars(char* bufferEnd, uint value, int digits) { while (--digits >= 0 || value != 0) { value = MathEx.DivRem(value, 10u, out var result); *(--bufferEnd) = (char)(result + 48); } return bufferEnd; } internal unsafe static string UInt32ToDecStr(uint value, int digits) { int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountDigits(value)); if (num == 1) { return s_singleDigitStringCache[value]; } string text = FastAllocateString(num); fixed (char* ptr = text) { char* ptr2 = ptr + num; if (digits <= 1) { do { value = MathEx.DivRem(value, 10u, out var result); *(--ptr2) = (char)(result + 48); } while (value != 0); } else { ptr2 = UInt32ToDecChars(ptr2, value, digits); } } return text; } private unsafe static bool TryUInt32ToDecStr(uint value, int digits, Span<char> destination, out int charsWritten) { int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountDigits(value)); if (num > destination.Length) { charsWritten = 0; return false; } charsWritten = num; fixed (char* ptr = &MemoryMarshal.GetReference(destination)) { char* ptr2 = ptr + num; if (digits <= 1) { do { value = MathEx.DivRem(value, 10u, out var result); *(--ptr2) = (char)(result + 48); } while (value != 0); } else { ptr2 = UInt32ToDecChars(ptr2, value, digits); } } return true; } private unsafe static void Int64ToNumber(long input, ref NumberBuffer number) { ulong value = (ulong)input; number.IsNegative = input < 0; number.DigitsCount = 19; if (number.IsNegative) { value = (ulong)(-input); } byte* digitsPointer = number.GetDigitsPointer(); byte* bufferEnd = digitsPointer + 19; while (High32(value) != 0) { bufferEnd = UInt32ToDecChars(bufferEnd, Int64DivMod1E9(ref value), 9); } bufferEnd = UInt32ToDecChars(bufferEnd, Low32(value), 0); int num = (number.Scale = (number.DigitsCount = (int)(digitsPointer + 19 - bufferEnd))); byte* digitsPointer2 = number.GetDigitsPointer(); while (--num >= 0) { *(digitsPointer2++) = *(bufferEnd++); } *digitsPointer2 = 0; } private unsafe static string NegativeInt64ToDecStr(long input, int digits, string sNegative) { if (digits < 1) { digits = 1; } ulong value = (ulong)(-input); int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountDigits(value)) + sNegative.Length; string text = FastAllocateString(num); fixed (char* ptr = text) { char* bufferEnd = ptr + num; while (High32(value) != 0) { bufferEnd = UInt32ToDecChars(bufferEnd, Int64DivMod1E9(ref value), 9); digits -= 9; } bufferEnd = UInt32ToDecChars(bufferEnd, Low32(value), digits); for (int num2 = sNegative.Length - 1; num2 >= 0; num2--) { *(--bufferEnd) = sNegative[num2]; } } return text; } private unsafe static bool TryNegativeInt64ToDecStr(long input, int digits, string sNegative, Span<char> destination, out int charsWritten) { if (digits < 1) { digits = 1; } ulong value = (ulong)(-input); int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountDigits((ulong)(-input))) + sNegative.Length; if (num > destination.Length) { charsWritten = 0; return false; } charsWritten = num; fixed (char* ptr = &MemoryMarshal.GetReference(destination)) { char* bufferEnd = ptr + num; while (High32(value) != 0) { bufferEnd = UInt32ToDecChars(bufferEnd, Int64DivMod1E9(ref value), 9); digits -= 9; } bufferEnd = UInt32ToDecChars(bufferEnd, Low32(value), digits); for (int num2 = sNegative.Length - 1; num2 >= 0; num2--) { *(--bufferEnd) = sNegative[num2]; } } return true; } private unsafe static string Int64ToHexStr(long value, char hexBase, int digits) { int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountHexDigits((ulong)value)); string text = FastAllocateString(num); fixed (char* ptr = text) { char* buffer = ptr + num; if (High32((ulong)value) != 0) { buffer = Int32ToHexChars(buffer, Low32((ulong)value), hexBase, 8); buffer = Int32ToHexChars(buffer, High32((ulong)value), hexBase, digits - 8); } else { buffer = Int32ToHexChars(buffer, Low32((ulong)value), hexBase, Math.Max(digits, 1)); } } return text; } private unsafe static bool TryInt64ToHexStr(long value, char hexBase, int digits, Span<char> destination, out int charsWritten) { int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountHexDigits((ulong)value)); if (num > destination.Length) { charsWritten = 0; return false; } charsWritten = num; fixed (char* ptr = &MemoryMarshal.GetReference(destination)) { char* buffer = ptr + num; if (High32((ulong)value) != 0) { buffer = Int32ToHexChars(buffer, Low32((ulong)value), hexBase, 8); buffer = Int32ToHexChars(buffer, High32((ulong)value), hexBase, digits - 8); } else { buffer = Int32ToHexChars(buffer, Low32((ulong)value), hexBase, Math.Max(digits, 1)); } } return true; } private unsafe static void UInt64ToNumber(ulong value, ref NumberBuffer number) { number.DigitsCount = 20; number.IsNegative = false; byte* digitsPointer = number.GetDigitsPointer(); byte* bufferEnd = digitsPointer + 20; while (High32(value) != 0) { bufferEnd = UInt32ToDecChars(bufferEnd, Int64DivMod1E9(ref value), 9); } bufferEnd = UInt32ToDecChars(bufferEnd, Low32(value), 0); int num = (number.Scale = (number.DigitsCount = (int)(digitsPointer + 20 - bufferEnd))); byte* digitsPointer2 = number.GetDigitsPointer(); while (--num >= 0) { *(digitsPointer2++) = *(bufferEnd++); } *digitsPointer2 = 0; } internal unsafe static string UInt64ToDecStr(ulong value, int digits) { if (digits < 1) { digits = 1; } int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountDigits(value)); if (num == 1) { return s_singleDigitStringCache[value]; } string text = FastAllocateString(num); fixed (char* ptr = text) { char* bufferEnd = ptr + num; while (High32(value) != 0) { bufferEnd = UInt32ToDecChars(bufferEnd, Int64DivMod1E9(ref value), 9); digits -= 9; } bufferEnd = UInt32ToDecChars(bufferEnd, Low32(value), digits); } return text; } private unsafe static bool TryUInt64ToDecStr(ulong value, int digits, Span<char> destination, out int charsWritten) { if (digits < 1) { digits = 1; } int num = Math.Max(digits, System.Buffers.Text.FormattingHelpers.CountDigits(value)); if (num > destination.Length) { charsWritten = 0; return false; } charsWritten = num; fixed (char* ptr = &MemoryMarshal.GetReference(destination)) { char* bufferEnd = ptr + num; while (High32(value) != 0) { bufferEnd = UInt32ToDecChars(bufferEnd, Int64DivMod1E9(ref value), 9); digits -= 9; } bufferEnd = UInt32ToDecChars(bufferEnd, Low32(value), digits); } return true; } internal static char ParseFormatSpecifier(ReadOnlySpan<char> format, out int digits) { char c = '\0'; if (format.Length > 0) { c = format[0]; if ((uint)(c - 65) <= 25u || (uint)(c - 97) <= 25u) { if (format.Length == 1) { digits = -1; return c; } if (format.Length == 2) { int num = format[1] - 48; if ((uint)num < 10u) { digits = num; return c; } } else if (format.Length == 3) { int num2 = format[1] - 48; int num3 = format[2] - 48; if ((uint)num2 < 10u && (uint)num3 < 10u) { digits = num2 * 10 + num3; return c; } } int num4 = 0; int num5 = 1; while (num5 < format.Length && (uint)(format[num5] - 48) < 10u && num4 < 10) { num4 = num4 * 10 + format[num5++] - 48; } if (num5 == format.Length || format[num5] == '\0') { digits = num4; return c; } } } digits = -1; if (format.Length != 0 && c != 0) { return '\0'; } return 'G'; } internal static void NumberToString(ref System.Text.ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info) { bool isCorrectlyRounded = number.Kind == NumberBufferKind.FloatingPoint; bool bSuppressScientific; switch (format) { case 'C': case 'c': if (nMaxDigits < 0) { nMaxDigits = info.CurrencyDecimalDigits; } RoundNumber(ref number, number.Scale + nMaxDigits, isCorrectlyRounded); FormatCurrency(ref sb, ref number, nMaxDigits, info); return; case 'F': case 'f': if (nMaxDigits < 0) { nMaxDigits = info.NumberDecimalDigits; } RoundNumber(ref number, number.Scale + nMaxDigits, isCorrectlyRounded); if (number.IsNegative) { sb.Append(info.NegativeSign); } FormatFixed(ref sb, ref number, nMaxDigits, null, info.NumberDecimalSeparator, null); return; case 'N': case 'n': if (nMaxDigits < 0) { nMaxDigits = info.NumberDecimalDigits; } RoundNumber(ref number, number.Scale + nMaxDigits, isCorrectlyRounded); FormatNumber(ref sb, ref number, nMaxDigits, info); return; case 'E': case 'e': if (nMaxDigits < 0) { nMaxDigits = 6; } nMaxDigits++; RoundNumber(ref number, nMaxDigits, isCorrectlyRounded); if (number.IsNegative) { sb.Append(info.NegativeSign); } FormatScientific(ref sb, ref number, nMaxDigits, info, format); return; case 'G': case 'g': bSuppressScientific = false; if (nMaxDigits < 1) { if (number.Kind == NumberBufferKind.Decimal && nMaxDigits == -1) { bSuppressScientific = true; if (number.Digits[0] != 0) { goto IL_0189; } goto IL_019e; } nMaxDigits = number.DigitsCount; } RoundNumber(ref number, nMaxDigits, isCorrectlyRounded); goto IL_0189; case 'P': case 'p': if (nMaxDigits < 0) { nMaxDigits = info.PercentDecimalDigits; } number.Scale += 2; RoundNumber(ref number, number.Scale + nMaxDigits, isCorrectlyRounded); FormatPercent(ref sb, ref number, nMaxDigits, info); return; case 'R': case 'r': { if (number.Kind != NumberBufferKind.FloatingPoint) { break; } format = (char)(format - 11); goto case 'G'; } IL_0189: if (number.IsNegative) { sb.Append(info.NegativeSign); } goto IL_019e; IL_019e: FormatGeneral(ref sb, ref number, nMaxDigits, info, (char)(format - 2), bSuppressScientific); return; } throw new FormatException("SR.Argument_BadFormatSpecifier"); } internal unsafe static void NumberToStringFormat(ref System.Text.ValueStringBuilder sb, ref NumberBuffer number, ReadOnlySpan<char> format, NumberFormatInfo info) { int num = 0; byte* digitsPointer = number.GetDigitsPointer(); int num2 = FindSection(format, (*digitsPointer == 0) ? 2 : (number.IsNegative ? 1 : 0)); int num3; int num4; bool flag; bool flag2; int num5; int num6; int num9; while (true) { num3 = 0; num4 = -1; num5 = int.MaxValue; num6 = 0; flag = false; int num7 = -1; flag2 = false; int num8 = 0; num9 = num2; fixed (char* ptr = &MemoryMarshal.GetReference(format)) { char c; while (num9 < format.Length && (c = ptr[num9++]) != 0) { switch (c) { case ';': break; case '#': num3++; continue; case '0': if (num5 == int.MaxValue) { num5 = num3; } num3++; num6 = num3; continue; case '.': if (num4 < 0) { num4 = num3; } continue; case ',': if (num3 <= 0 || num4 >= 0) { continue; } if (num7 >= 0) { if (num7 == num3) { num++; continue; } flag2 = true; } num7 = num3; num = 1; continue; case '%': num8 += 2; continue; case '‰': num8 += 3; continue; case '"': case '\'': while (num9 < format.Length && ptr[num9] != 0 && ptr[num9++] != c) { } continue; case '\\': if (num9 < format.Length && ptr[num9] != 0) { num9++; } continue; case 'E': case 'e': if ((num9 < format.Length && ptr[num9] == '0') || (num9 + 1 < format.Length && (ptr[num9] == '+' || ptr[num9] == '-') && ptr[num9 + 1] == '0')) { while (++num9 < format.Length && ptr[num9] == '0') { } flag = true; } continue; default: continue; } break; } } if (num4 < 0) { num4 = num3; } if (num7 >= 0) { if (num7 == num4) { num8 -= num * 3; } else { flag2 = true; } } if (*digitsPointer != 0) { number.Scale += num8; int pos = (flag ? num3 : (number.Scale + num3 - num4)); RoundNumber(ref number, pos, isCorrectlyRounded: false); if (*digitsPointer != 0) { break; } num9 = FindSection(format, 2); if (num9 == num2) { break; } num2 = num9; continue; } if (number.Kind != NumberBufferKind.FloatingPoint) { number.IsNegative = false; } number.Scale = 0; break; } num5 = ((num5 < num4) ? (num4 - num5) : 0); num6 = ((num6 > num4) ? (num4 - num6) : 0); int num10; int num11; if (flag) { num10 = num4; num11 = 0; } else { num10 = ((number.Scale > num4) ? number.Scale : num4); num11 = number.Scale - num4; } num9 = num2; Span<int> span = stackalloc int[4]; int num12 = -1; if (flag2 && info.NumberGroupSeparator.Length > 0) { int[] numberGroupSizes = info.NumberGroupSizes; int num13 = 0; int i = 0; int num14 = numberGroupSizes.Length; if (num14 != 0) { i = numberGroupSizes[num13]; } int num15 = i; int num16 = num10 + ((num11 < 0) ? num11 : 0); for (int num17 = ((num5 > num16) ? num5 : num16); num17 > i; i += num15) { if (num15 == 0) { break; } num12++; if (num12 >= span.Length) { int[] array = new int[span.Length * 2]; span.CopyTo(array); span = array; } span[num12] = i; if (num13 < num14 - 1) { num13++; num15 = numberGroupSizes[num13]; } } } if (number.IsNegative && num2 == 0 && number.Scale != 0) { sb.Append(info.NegativeSign); } bool flag3 = false;