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;