// Decompiled with JetBrains decompiler
// Type: System.Number
// Assembly: System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
// MVID: C43E8601-FD84-4F10-B809-6918FE95DD59
// Assembly location: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.11\System.Private.CoreLib.dll

using Internal.Runtime.CompilerServices;
using System.Buffers.Text;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;

namespace System
{
  internal static class Number
  {
    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 DecimalPrecision = 29;

    [MethodImpl(MethodImplOptions.InternalCall)]
    public static extern void DoubleToNumber(
      double value,
      int precision,
      ref Number.NumberBuffer number);

    [MethodImpl(MethodImplOptions.InternalCall)]
    public static extern double NumberToDouble(ref Number.NumberBuffer number);

    [MethodImpl(MethodImplOptions.InternalCall)]
    public static extern bool NumberBufferToDecimal(
      ref Number.NumberBuffer number,
      ref Decimal value);

    public static unsafe string FormatDecimal(
      Decimal value,
      ReadOnlySpan<char> format,
      NumberFormatInfo info)
    {
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.DecimalToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, info, true);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, info);
      return sb.ToString();
    }

    public static unsafe bool TryFormatDecimal(
      Decimal value,
      ReadOnlySpan<char> format,
      NumberFormatInfo info,
      Span<char> destination,
      out int charsWritten)
    {
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.DecimalToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, info, true);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, info);
      return sb.TryCopyTo(destination, out charsWritten);
    }

    private static unsafe void DecimalToNumber(Decimal value, ref Number.NumberBuffer number)
    {
      Decimal num1 = value;
      char* digits1 = number.digits;
      number.precision = 29;
      number.sign = num1.IsNegative;
      char* bufferEnd = digits1 + 29;
      while (((int) num1.Mid | (int) num1.High) != 0)
        bufferEnd = Number.UInt32ToDecChars(bufferEnd, Decimal.DecDivMod1E9(ref num1), 9);
      char* decChars = Number.UInt32ToDecChars(bufferEnd, num1.Low, 0);
      int num2 = (int) (digits1 + 29 - decChars);
      number.scale = num2 - num1.Scale;
      char* digits2 = number.digits;
      while (--num2 >= 0)
        *digits2++ = *decChars++;
      *digits2 = char.MinValue;
    }

    public static unsafe string FormatDouble(double value, string format, NumberFormatInfo info)
    {
      int length = 32;
      // ISSUE: untyped stack allocation
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) __untypedstackalloc(checked (unchecked ((IntPtr) (uint) length) * 2)), length));
      return Number.FormatDouble(ref sb, value, (ReadOnlySpan<char>) format, info) ?? sb.ToString();
    }

    public static unsafe bool TryFormatDouble(
      double value,
      ReadOnlySpan<char> format,
      NumberFormatInfo info,
      Span<char> destination,
      out int charsWritten)
    {
      int length = 32;
      // ISSUE: untyped stack allocation
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) __untypedstackalloc(checked (unchecked ((IntPtr) (uint) length) * 2)), length));
      string source = Number.FormatDouble(ref sb, value, format, info);
      if (source == null)
        return sb.TryCopyTo(destination, out charsWritten);
      return Number.TryCopyTo(source, destination, out charsWritten);
    }

    private static string FormatDouble(
      ref ValueStringBuilder sb,
      double value,
      ReadOnlySpan<char> format,
      NumberFormatInfo info)
    {
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      int precision = 15;
      Number.NumberBuffer number = new Number.NumberBuffer();
      switch (formatSpecifier)
      {
        case 'E':
        case 'e':
          if (digits > 14)
          {
            precision = 17;
            break;
          }
          break;
        case 'G':
        case 'g':
          if (digits > 15)
          {
            precision = 17;
            break;
          }
          break;
        case 'R':
        case 'r':
          Number.DoubleToNumber(value, 15, ref number);
          if (number.scale == int.MinValue)
            return info.NaNSymbol;
          if (number.scale == int.MaxValue)
          {
            if (!number.sign)
              return info.PositiveInfinitySymbol;
            return info.NegativeInfinitySymbol;
          }
          if (Number.NumberToDouble(ref number) == value)
          {
            Number.NumberToString(ref sb, ref number, 'G', 15, info, false);
          }
          else
          {
            Number.DoubleToNumber(value, 17, ref number);
            Number.NumberToString(ref sb, ref number, 'G', 17, info, false);
          }
          return (string) null;
      }
      Number.DoubleToNumber(value, precision, ref number);
      if (number.scale == int.MinValue)
        return info.NaNSymbol;
      if (number.scale == int.MaxValue)
      {
        if (!number.sign)
          return info.PositiveInfinitySymbol;
        return info.NegativeInfinitySymbol;
      }
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, info, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, info);
      return (string) null;
    }

    public static unsafe string FormatSingle(float value, string format, NumberFormatInfo info)
    {
      int length = 32;
      // ISSUE: untyped stack allocation
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) __untypedstackalloc(checked (unchecked ((IntPtr) (uint) length) * 2)), length));
      return Number.FormatSingle(ref sb, value, (ReadOnlySpan<char>) format, info) ?? sb.ToString();
    }

    public static unsafe bool TryFormatSingle(
      float value,
      ReadOnlySpan<char> format,
      NumberFormatInfo info,
      Span<char> destination,
      out int charsWritten)
    {
      int length = 32;
      // ISSUE: untyped stack allocation
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) __untypedstackalloc(checked (unchecked ((IntPtr) (uint) length) * 2)), length));
      string source = Number.FormatSingle(ref sb, value, format, info);
      if (source == null)
        return sb.TryCopyTo(destination, out charsWritten);
      return Number.TryCopyTo(source, destination, out charsWritten);
    }

    private static string FormatSingle(
      ref ValueStringBuilder sb,
      float value,
      ReadOnlySpan<char> format,
      NumberFormatInfo info)
    {
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      int precision = 7;
      Number.NumberBuffer number = new Number.NumberBuffer();
      switch (formatSpecifier)
      {
        case 'E':
        case 'e':
          if (digits > 6)
          {
            precision = 9;
            break;
          }
          break;
        case 'G':
        case 'g':
          if (digits > 7)
          {
            precision = 9;
            break;
          }
          break;
        case 'R':
        case 'r':
          Number.DoubleToNumber((double) value, 7, ref number);
          if (number.scale == int.MinValue)
            return info.NaNSymbol;
          if (number.scale == int.MaxValue)
          {
            if (!number.sign)
              return info.PositiveInfinitySymbol;
            return info.NegativeInfinitySymbol;
          }
          if (Number.NumberToDouble(ref number) == (double) value)
          {
            Number.NumberToString(ref sb, ref number, 'G', 7, info, false);
          }
          else
          {
            Number.DoubleToNumber((double) value, 9, ref number);
            Number.NumberToString(ref sb, ref number, 'G', 9, info, false);
          }
          return (string) null;
      }
      Number.DoubleToNumber((double) value, precision, ref number);
      if (number.scale == int.MinValue)
        return info.NaNSymbol;
      if (number.scale == int.MaxValue)
      {
        if (!number.sign)
          return info.PositiveInfinitySymbol;
        return info.NegativeInfinitySymbol;
      }
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, info, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, info);
      return (string) 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 static unsafe string FormatInt32(
      int value,
      ReadOnlySpan<char> format,
      IFormatProvider provider)
    {
      if (value >= 0 && format.Length == 0)
        return Number.UInt32ToDecStr((uint) value, -1);
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
      char ch = (char) ((uint) formatSpecifier & 65503U);
      if (ch == 'G' && digits < 1 || ch == 'D')
      {
        if (value < 0)
          return Number.NegativeInt32ToDecStr(value, digits, instance.NegativeSign);
        return Number.UInt32ToDecStr((uint) value, digits);
      }
      if (ch == 'X')
        return Number.Int32ToHexStr(value, (char) ((uint) formatSpecifier - 33U), digits);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.Int32ToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, instance, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, instance);
      return sb.ToString();
    }

    public static unsafe bool TryFormatInt32(
      int value,
      ReadOnlySpan<char> format,
      IFormatProvider provider,
      Span<char> destination,
      out int charsWritten)
    {
      if (value >= 0 && format.Length == 0)
        return Number.TryUInt32ToDecStr((uint) value, -1, destination, out charsWritten);
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
      char ch = (char) ((uint) formatSpecifier & 65503U);
      if (ch == 'G' && digits < 1 || ch == 'D')
      {
        if (value < 0)
          return Number.TryNegativeInt32ToDecStr(value, digits, instance.NegativeSign, destination, out charsWritten);
        return Number.TryUInt32ToDecStr((uint) value, digits, destination, out charsWritten);
      }
      if (ch == 'X')
        return Number.TryInt32ToHexStr(value, (char) ((uint) formatSpecifier - 33U), digits, destination, out charsWritten);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.Int32ToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, instance, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, instance);
      return sb.TryCopyTo(destination, out charsWritten);
    }

    public static unsafe string FormatUInt32(
      uint value,
      ReadOnlySpan<char> format,
      IFormatProvider provider)
    {
      if (format.Length == 0)
        return Number.UInt32ToDecStr(value, -1);
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
      char ch = (char) ((uint) formatSpecifier & 65503U);
      if (ch == 'G' && digits < 1 || ch == 'D')
        return Number.UInt32ToDecStr(value, digits);
      if (ch == 'X')
        return Number.Int32ToHexStr((int) value, (char) ((uint) formatSpecifier - 33U), digits);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.UInt32ToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, instance, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, instance);
      return sb.ToString();
    }

    public static unsafe bool TryFormatUInt32(
      uint value,
      ReadOnlySpan<char> format,
      IFormatProvider provider,
      Span<char> destination,
      out int charsWritten)
    {
      if (format.Length == 0)
        return Number.TryUInt32ToDecStr(value, -1, destination, out charsWritten);
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
      char ch = (char) ((uint) formatSpecifier & 65503U);
      if (ch == 'G' && digits < 1 || ch == 'D')
        return Number.TryUInt32ToDecStr(value, digits, destination, out charsWritten);
      if (ch == 'X')
        return Number.TryInt32ToHexStr((int) value, (char) ((uint) formatSpecifier - 33U), digits, destination, out charsWritten);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.UInt32ToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, instance, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, instance);
      return sb.TryCopyTo(destination, out charsWritten);
    }

    public static unsafe string FormatInt64(
      long value,
      ReadOnlySpan<char> format,
      IFormatProvider provider)
    {
      if (value >= 0L && format.Length == 0)
        return Number.UInt64ToDecStr((ulong) value, -1);
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
      char ch = (char) ((uint) formatSpecifier & 65503U);
      if (ch == 'G' && digits < 1 || ch == 'D')
      {
        if (value < 0L)
          return Number.NegativeInt64ToDecStr(value, digits, instance.NegativeSign);
        return Number.UInt64ToDecStr((ulong) value, digits);
      }
      if (ch == 'X')
        return Number.Int64ToHexStr(value, (char) ((uint) formatSpecifier - 33U), digits);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.Int64ToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, instance, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, instance);
      return sb.ToString();
    }

    public static unsafe bool TryFormatInt64(
      long value,
      ReadOnlySpan<char> format,
      IFormatProvider provider,
      Span<char> destination,
      out int charsWritten)
    {
      if (value >= 0L && format.Length == 0)
        return Number.TryUInt64ToDecStr((ulong) value, -1, destination, out charsWritten);
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
      char ch = (char) ((uint) formatSpecifier & 65503U);
      if (ch == 'G' && digits < 1 || ch == 'D')
      {
        if (value < 0L)
          return Number.TryNegativeInt64ToDecStr(value, digits, instance.NegativeSign, destination, out charsWritten);
        return Number.TryUInt64ToDecStr((ulong) value, digits, destination, out charsWritten);
      }
      if (ch == 'X')
        return Number.TryInt64ToHexStr(value, (char) ((uint) formatSpecifier - 33U), digits, destination, out charsWritten);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.Int64ToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, instance, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, instance);
      return sb.TryCopyTo(destination, out charsWritten);
    }

    public static unsafe string FormatUInt64(
      ulong value,
      ReadOnlySpan<char> format,
      IFormatProvider provider)
    {
      if (format.Length == 0)
        return Number.UInt64ToDecStr(value, -1);
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
      char ch = (char) ((uint) formatSpecifier & 65503U);
      if (ch == 'G' && digits < 1 || ch == 'D')
        return Number.UInt64ToDecStr(value, digits);
      if (ch == 'X')
        return Number.Int64ToHexStr((long) value, (char) ((uint) formatSpecifier - 33U), digits);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.UInt64ToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, instance, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, instance);
      return sb.ToString();
    }

    public static unsafe bool TryFormatUInt64(
      ulong value,
      ReadOnlySpan<char> format,
      IFormatProvider provider,
      Span<char> destination,
      out int charsWritten)
    {
      if (format.Length == 0)
        return Number.TryUInt64ToDecStr(value, -1, destination, out charsWritten);
      int digits;
      char formatSpecifier = Number.ParseFormatSpecifier(format, out digits);
      NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
      char ch = (char) ((uint) formatSpecifier & 65503U);
      if (ch == 'G' && digits < 1 || ch == 'D')
        return Number.TryUInt64ToDecStr(value, digits, destination, out charsWritten);
      if (ch == 'X')
        return Number.TryInt64ToHexStr((long) value, (char) ((uint) formatSpecifier - 33U), digits, destination, out charsWritten);
      Number.NumberBuffer number = new Number.NumberBuffer();
      Number.UInt64ToNumber(value, ref number);
      char* chPtr = stackalloc char[32];
      ValueStringBuilder sb = new ValueStringBuilder(new Span<char>((void*) chPtr, 32));
      if (formatSpecifier != char.MinValue)
        Number.NumberToString(ref sb, ref number, formatSpecifier, digits, instance, false);
      else
        Number.NumberToStringFormat(ref sb, ref number, format, instance);
      return sb.TryCopyTo(destination, out charsWritten);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static unsafe void Int32ToNumber(int value, ref Number.NumberBuffer number)
    {
      number.precision = 10;
      if (value >= 0)
      {
        number.sign = false;
      }
      else
      {
        number.sign = true;
        value = -value;
      }
      char* digits1 = number.digits;
      char* decChars = Number.UInt32ToDecChars(digits1 + 10, (uint) value, 0);
      int num = (int) (digits1 + 10 - decChars);
      number.scale = num;
      char* digits2 = number.digits;
      while (--num >= 0)
        *digits2++ = *decChars++;
      *digits2 = char.MinValue;
    }

    private static unsafe string NegativeInt32ToDecStr(int value, int digits, string sNegative)
    {
      if (digits < 1)
        digits = 1;
      int length = Math.Max(digits, FormattingHelpers.CountDigits((uint) -value)) + sNegative.Length;
      string str = string.FastAllocateString(length);
      fixed (char* chPtr = str)
      {
        char* decChars = Number.UInt32ToDecChars(chPtr + length, (uint) -value, digits);
        for (int index = sNegative.Length - 1; index >= 0; --index)
          *--decChars = sNegative[index];
      }
      return str;
    }

    private static unsafe bool TryNegativeInt32ToDecStr(
      int value,
      int digits,
      string sNegative,
      Span<char> destination,
      out int charsWritten)
    {
      if (digits < 1)
        digits = 1;
      int num = Math.Max(digits, FormattingHelpers.CountDigits((uint) -value)) + sNegative.Length;
      if (num > destination.Length)
      {
        charsWritten = 0;
        return false;
      }
      charsWritten = num;
      fixed (char* chPtr = &MemoryMarshal.GetReference<char>(destination))
      {
        char* decChars = Number.UInt32ToDecChars(chPtr + num, (uint) -value, digits);
        for (int index = sNegative.Length - 1; index >= 0; --index)
          *--decChars = sNegative[index];
      }
      return true;
    }

    private static unsafe string Int32ToHexStr(int value, char hexBase, int digits)
    {
      if (digits < 1)
        digits = 1;
      int length = Math.Max(digits, FormattingHelpers.CountHexDigits((ulong) (uint) value));
      string str = string.FastAllocateString(length);
      fixed (char* chPtr = str)
        Number.Int32ToHexChars(chPtr + length, (uint) value, (int) hexBase, digits);
      return str;
    }

    private static unsafe bool TryInt32ToHexStr(
      int value,
      char hexBase,
      int digits,
      Span<char> destination,
      out int charsWritten)
    {
      if (digits < 1)
        digits = 1;
      int num = Math.Max(digits, FormattingHelpers.CountHexDigits((ulong) (uint) value));
      if (num > destination.Length)
      {
        charsWritten = 0;
        return false;
      }
      charsWritten = num;
      fixed (char* chPtr = &MemoryMarshal.GetReference<char>(destination))
        Number.Int32ToHexChars(chPtr + num, (uint) value, (int) hexBase, digits);
      return true;
    }

    private static unsafe char* Int32ToHexChars(char* buffer, uint value, int hexBase, int digits)
    {
      for (; --digits >= 0 || value != 0U; value >>= 4)
      {
        byte num = (byte) (value & 15U);
        *--buffer = (char) ((int) num + (num < (byte) 10 ? 48 : hexBase));
      }
      return buffer;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static unsafe void UInt32ToNumber(uint value, ref Number.NumberBuffer number)
    {
      number.precision = 10;
      number.sign = false;
      char* digits1 = number.digits;
      char* decChars = Number.UInt32ToDecChars(digits1 + 10, value, 0);
      int num = (int) (digits1 + 10 - decChars);
      number.scale = num;
      char* digits2 = number.digits;
      while (--num >= 0)
        *digits2++ = *decChars++;
      *digits2 = char.MinValue;
    }

    internal static unsafe char* UInt32ToDecChars(char* bufferEnd, uint value, int digits)
    {
      uint num;
      for (; --digits >= 0 || value != 0U; value = num)
      {
        num = value / 10U;
        *--bufferEnd = (char) ((int) value - (int) num * 10 + 48);
      }
      return bufferEnd;
    }

    private static unsafe string UInt32ToDecStr(uint value, int digits)
    {
      int length = Math.Max(digits, FormattingHelpers.CountDigits(value));
      string str = string.FastAllocateString(length);
      fixed (char* chPtr = str)
      {
        char* bufferEnd = chPtr + length;
        if (digits <= 1)
        {
          do
          {
            uint num = value / 10U;
            *--bufferEnd = (char) (48 + (int) value - (int) num * 10);
            value = num;
          }
          while (value != 0U);
        }
        else
          Number.UInt32ToDecChars(bufferEnd, value, digits);
      }
      return str;
    }

    private static unsafe bool TryUInt32ToDecStr(
      uint value,
      int digits,
      Span<char> destination,
      out int charsWritten)
    {
      int num1 = Math.Max(digits, FormattingHelpers.CountDigits(value));
      if (num1 > destination.Length)
      {
        charsWritten = 0;
        return false;
      }
      charsWritten = num1;
      fixed (char* chPtr = &MemoryMarshal.GetReference<char>(destination))
      {
        char* bufferEnd = chPtr + num1;
        if (digits <= 1)
        {
          do
          {
            uint num2 = value / 10U;
            *--bufferEnd = (char) (48 + (int) value - (int) num2 * 10);
            value = num2;
          }
          while (value != 0U);
        }
        else
          Number.UInt32ToDecChars(bufferEnd, value, digits);
      }
      return true;
    }

    private static unsafe void Int64ToNumber(long input, ref Number.NumberBuffer number)
    {
      ulong num1 = (ulong) input;
      number.sign = input < 0L;
      number.precision = 19;
      if (number.sign)
        num1 = (ulong) -input;
      char* digits1 = number.digits;
      char* bufferEnd = digits1 + 19;
      while (Number.High32(num1) != 0U)
        bufferEnd = Number.UInt32ToDecChars(bufferEnd, Number.Int64DivMod1E9(ref num1), 9);
      char* decChars = Number.UInt32ToDecChars(bufferEnd, Number.Low32(num1), 0);
      int num2 = (int) (digits1 + 19 - decChars);
      number.scale = num2;
      char* digits2 = number.digits;
      while (--num2 >= 0)
        *digits2++ = *decChars++;
      *digits2 = char.MinValue;
    }

    private static unsafe string NegativeInt64ToDecStr(long input, int digits, string sNegative)
    {
      if (digits < 1)
        digits = 1;
      ulong num = (ulong) -input;
      int length = Math.Max(digits, FormattingHelpers.CountDigits(num)) + sNegative.Length;
      string str = string.FastAllocateString(length);
      fixed (char* chPtr = str)
      {
        char* bufferEnd = chPtr + length;
        while (Number.High32(num) != 0U)
        {
          bufferEnd = Number.UInt32ToDecChars(bufferEnd, Number.Int64DivMod1E9(ref num), 9);
          digits -= 9;
        }
        char* decChars = Number.UInt32ToDecChars(bufferEnd, Number.Low32(num), digits);
        for (int index = sNegative.Length - 1; index >= 0; --index)
          *--decChars = sNegative[index];
      }
      return str;
    }

    private static unsafe bool TryNegativeInt64ToDecStr(
      long input,
      int digits,
      string sNegative,
      Span<char> destination,
      out int charsWritten)
    {
      if (digits < 1)
        digits = 1;
      ulong num1 = (ulong) -input;
      int num2 = Math.Max(digits, FormattingHelpers.CountDigits((ulong) -input)) + sNegative.Length;
      if (num2 > destination.Length)
      {
        charsWritten = 0;
        return false;
      }
      charsWritten = num2;
      fixed (char* chPtr = &MemoryMarshal.GetReference<char>(destination))
      {
        char* bufferEnd = chPtr + num2;
        while (Number.High32(num1) != 0U)
        {
          bufferEnd = Number.UInt32ToDecChars(bufferEnd, Number.Int64DivMod1E9(ref num1), 9);
          digits -= 9;
        }
        char* decChars = Number.UInt32ToDecChars(bufferEnd, Number.Low32(num1), digits);
        for (int index = sNegative.Length - 1; index >= 0; --index)
          *--decChars = sNegative[index];
      }
      return true;
    }

    private static unsafe string Int64ToHexStr(long value, char hexBase, int digits)
    {
      int length = Math.Max(digits, FormattingHelpers.CountHexDigits((ulong) value));
      string str = string.FastAllocateString(length);
      fixed (char* chPtr1 = str)
      {
        char* buffer = chPtr1 + length;
        char* chPtr2 = Number.High32((ulong) value) == 0U ? Number.Int32ToHexChars(buffer, Number.Low32((ulong) value), (int) hexBase, Math.Max(digits, 1)) : Number.Int32ToHexChars(Number.Int32ToHexChars(buffer, Number.Low32((ulong) value), (int) hexBase, 8), Number.High32((ulong) value), (int) hexBase, digits - 8);
      }
      return str;
    }

    private static unsafe bool TryInt64ToHexStr(
      long value,
      char hexBase,
      int digits,
      Span<char> destination,
      out int charsWritten)
    {
      int num = Math.Max(digits, FormattingHelpers.CountHexDigits((ulong) value));
      if (num > destination.Length)
      {
        charsWritten = 0;
        return false;
      }
      charsWritten = num;
      fixed (char* chPtr1 = &MemoryMarshal.GetReference<char>(destination))
      {
        char* buffer = chPtr1 + num;
        char* chPtr2 = Number.High32((ulong) value) == 0U ? Number.Int32ToHexChars(buffer, Number.Low32((ulong) value), (int) hexBase, Math.Max(digits, 1)) : Number.Int32ToHexChars(Number.Int32ToHexChars(buffer, Number.Low32((ulong) value), (int) hexBase, 8), Number.High32((ulong) value), (int) hexBase, digits - 8);
      }
      return true;
    }

    private static unsafe void UInt64ToNumber(ulong value, ref Number.NumberBuffer number)
    {
      number.precision = 20;
      number.sign = false;
      char* digits1 = number.digits;
      char* bufferEnd = digits1 + 20;
      while (Number.High32(value) != 0U)
        bufferEnd = Number.UInt32ToDecChars(bufferEnd, Number.Int64DivMod1E9(ref value), 9);
      char* decChars = Number.UInt32ToDecChars(bufferEnd, Number.Low32(value), 0);
      int num = (int) (digits1 + 20 - decChars);
      number.scale = num;
      char* digits2 = number.digits;
      while (--num >= 0)
        *digits2++ = *decChars++;
      *digits2 = char.MinValue;
    }

    private static unsafe string UInt64ToDecStr(ulong value, int digits)
    {
      if (digits < 1)
        digits = 1;
      int length = Math.Max(digits, FormattingHelpers.CountDigits(value));
      string str = string.FastAllocateString(length);
      fixed (char* chPtr = str)
      {
        char* bufferEnd = chPtr + length;
        while (Number.High32(value) != 0U)
        {
          bufferEnd = Number.UInt32ToDecChars(bufferEnd, Number.Int64DivMod1E9(ref value), 9);
          digits -= 9;
        }
        Number.UInt32ToDecChars(bufferEnd, Number.Low32(value), digits);
      }
      return str;
    }

    private static unsafe bool TryUInt64ToDecStr(
      ulong value,
      int digits,
      Span<char> destination,
      out int charsWritten)
    {
      if (digits < 1)
        digits = 1;
      int num = Math.Max(digits, FormattingHelpers.CountDigits(value));
      if (num > destination.Length)
      {
        charsWritten = 0;
        return false;
      }
      charsWritten = num;
      fixed (char* chPtr = &MemoryMarshal.GetReference<char>(destination))
      {
        char* bufferEnd = chPtr + num;
        while (Number.High32(value) != 0U)
        {
          bufferEnd = Number.UInt32ToDecChars(bufferEnd, Number.Int64DivMod1E9(ref value), 9);
          digits -= 9;
        }
        Number.UInt32ToDecChars(bufferEnd, Number.Low32(value), digits);
      }
      return true;
    }

    internal static char ParseFormatSpecifier(ReadOnlySpan<char> format, out int digits)
    {
      char ch = char.MinValue;
      if (format.Length > 0)
      {
        ch = format[0];
        if ((uint) ch - 65U <= 25U || (uint) ch - 97U <= 25U)
        {
          if (format.Length == 1)
          {
            digits = -1;
            return ch;
          }
          if (format.Length == 2)
          {
            int num = (int) format[1] - 48;
            if ((uint) num < 10U)
            {
              digits = num;
              return ch;
            }
          }
          else if (format.Length == 3)
          {
            int num1 = (int) format[1] - 48;
            int num2 = (int) format[2] - 48;
            if ((uint) num1 < 10U && (uint) num2 < 10U)
            {
              digits = num1 * 10 + num2;
              return ch;
            }
          }
          int num3 = 0;
          int index = 1;
          while (index < format.Length && (uint) format[index] - 48U < 10U && num3 < 10)
            num3 = num3 * 10 + (int) format[index++] - 48;
          if (index == format.Length || format[index] == char.MinValue)
          {
            digits = num3;
            return ch;
          }
        }
      }
      digits = -1;
      return format.Length != 0 && ch != char.MinValue ? char.MinValue : 'G';
    }

    internal static unsafe void NumberToString(
      ref ValueStringBuilder sb,
      ref Number.NumberBuffer number,
      char format,
      int nMaxDigits,
      NumberFormatInfo info,
      bool isDecimal)
    {
      switch (format)
      {
        case 'C':
        case 'c':
          int nMinDigits1 = nMaxDigits >= 0 ? nMaxDigits : info.CurrencyDecimalDigits;
          if (nMaxDigits < 0)
            nMaxDigits = info.CurrencyDecimalDigits;
          Number.RoundNumber(ref number, number.scale + nMaxDigits);
          Number.FormatCurrency(ref sb, ref number, nMinDigits1, nMaxDigits, info);
          break;
        case 'E':
        case 'e':
          int nMinDigits2;
          if (nMaxDigits < 0)
            nMaxDigits = nMinDigits2 = 6;
          else
            nMinDigits2 = nMaxDigits;
          ++nMaxDigits;
          Number.RoundNumber(ref number, nMaxDigits);
          if (number.sign)
            sb.Append(info.NegativeSign);
          Number.FormatScientific(ref sb, ref number, nMinDigits2, nMaxDigits, info, format);
          break;
        case 'F':
        case 'f':
          int nMinDigits3;
          if (nMaxDigits < 0)
            nMaxDigits = nMinDigits3 = info.NumberDecimalDigits;
          else
            nMinDigits3 = nMaxDigits;
          Number.RoundNumber(ref number, number.scale + nMaxDigits);
          if (number.sign)
            sb.Append(info.NegativeSign);
          Number.FormatFixed(ref sb, ref number, nMinDigits3, nMaxDigits, info, (int[]) null, info.NumberDecimalSeparator, (string) null);
          break;
        case 'G':
        case 'g':
          bool flag = true;
          int nMinDigits4;
          if (nMaxDigits < 1)
          {
            if (isDecimal && nMaxDigits == -1)
            {
              nMaxDigits = nMinDigits4 = 29;
              flag = false;
            }
            else
              nMaxDigits = nMinDigits4 = number.precision;
          }
          else
            nMinDigits4 = nMaxDigits;
          if (flag)
            Number.RoundNumber(ref number, nMaxDigits);
          else if (isDecimal && *number.digits == char.MinValue)
            number.sign = false;
          if (number.sign)
            sb.Append(info.NegativeSign);
          Number.FormatGeneral(ref sb, ref number, nMinDigits4, nMaxDigits, info, (char) ((uint) format - 2U), !flag);
          break;
        case 'N':
        case 'n':
          int nMinDigits5;
          if (nMaxDigits < 0)
            nMaxDigits = nMinDigits5 = info.NumberDecimalDigits;
          else
            nMinDigits5 = nMaxDigits;
          Number.RoundNumber(ref number, number.scale + nMaxDigits);
          Number.FormatNumber(ref sb, ref number, nMinDigits5, nMaxDigits, info);
          break;
        case 'P':
        case 'p':
          int nMinDigits6;
          if (nMaxDigits < 0)
            nMaxDigits = nMinDigits6 = info.PercentDecimalDigits;
          else
            nMinDigits6 = nMaxDigits;
          number.scale += 2;
          Number.RoundNumber(ref number, number.scale + nMaxDigits);
          Number.FormatPercent(ref sb, ref number, nMinDigits6, nMaxDigits, info);
          break;
        default:
          throw new FormatException(SR.Argument_BadFormatSpecifier);
      }
    }

    internal static unsafe void NumberToStringFormat(
      ref ValueStringBuilder sb,
      ref Number.NumberBuffer number,
      ReadOnlySpan<char> format,
      NumberFormatInfo info)
    {
      int num1 = 0;
      char* digits = number.digits;
      int num2 = Number.FindSection(format, *digits == char.MinValue ? 2 : (number.sign ? 1 : 0));
      int num3;
      int num4;
      int num5;
      int num6;
      bool flag1;
      bool flag2;
      while (true)
      {
        num3 = 0;
        num4 = -1;
        num5 = int.MaxValue;
        num6 = 0;
        flag1 = false;
        int num7 = -1;
        flag2 = false;
        int num8 = 0;
        int index = num2;
        fixed (char* chPtr1 = &MemoryMarshal.GetReference<char>(format))
        {
          while (index < format.Length)
          {
            char* chPtr2 = chPtr1;
            IntPtr num9 = (IntPtr) index++ * 2;
            char ch;
            if ((ch = (char) *(ushort*) ((IntPtr) chPtr2 + num9)) != char.MinValue)
            {
              switch (ch)
              {
                case '"':
                case '\'':
                  do
                    ;
                  while (index < format.Length && chPtr1[index] != char.MinValue && (int) chPtr1[index++] != (int) ch);
                  continue;
                case '#':
                  ++num3;
                  continue;
                case '%':
                  num8 += 2;
                  continue;
                case ',':
                  if (num3 > 0 && num4 < 0)
                  {
                    if (num7 >= 0)
                    {
                      if (num7 == num3)
                      {
                        ++num1;
                        continue;
                      }
                      flag2 = true;
                    }
                    num7 = num3;
                    num1 = 1;
                    continue;
                  }
                  continue;
                case '.':
                  if (num4 < 0)
                  {
                    num4 = num3;
                    continue;
                  }
                  continue;
                case '0':
                  if (num5 == int.MaxValue)
                    num5 = num3;
                  ++num3;
                  num6 = num3;
                  continue;
                case ';':
                  goto label_25;
                case 'E':
                case 'e':
                  if (index < format.Length && chPtr1[index] == '0' || index + 1 < format.Length && (chPtr1[index] == '+' || chPtr1[index] == '-') && chPtr1[index + 1] == '0')
                  {
                    do
                      ;
                    while (++index < format.Length && chPtr1[index] == '0');
                    flag1 = true;
                    continue;
                  }
                  continue;
                case '\\':
                  if (index < format.Length && chPtr1[index] != char.MinValue)
                  {
                    ++index;
                    continue;
                  }
                  continue;
                case '‰':
                  num8 += 3;
                  continue;
                default:
                  continue;
              }
            }
            else
              break;
          }
label_25:;
        }
        if (num4 < 0)
          num4 = num3;
        if (num7 >= 0)
        {
          if (num7 == num4)
            num8 -= num1 * 3;
          else
            flag2 = true;
        }
        if (*digits != char.MinValue)
        {
          number.scale += num8;
          int pos = flag1 ? num3 : number.scale + num3 - num4;
          Number.RoundNumber(ref number, pos);
          if (*digits == char.MinValue)
          {
            int section = Number.FindSection(format, 2);
            if (section != num2)
              num2 = section;
            else
              goto label_36;
          }
          else
            goto label_36;
        }
        else
          break;
      }
      number.sign = false;
      number.scale = 0;
label_36:
      int num10 = num5 < num4 ? num4 - num5 : 0;
      int num11 = num6 > num4 ? num4 - num6 : 0;
      int num12;
      int num13;
      if (flag1)
      {
        num12 = num4;
        num13 = 0;
      }
      else
      {
        num12 = number.scale > num4 ? number.scale : num4;
        num13 = number.scale - num4;
      }
      int index1 = num2;
      int length1 = 4;
      // ISSUE: untyped stack allocation
      Span<int> span = new Span<int>((void*) __untypedstackalloc(checked (unchecked ((IntPtr) (uint) length1) * 4)), length1);
      int index2 = -1;
      if (flag2 && info.NumberGroupSeparator.Length > 0)
      {
        int[] numberGroupSizes = info.numberGroupSizes;
        int index3 = 0;
        int num7 = 0;
        int length2 = numberGroupSizes.Length;
        if (length2 != 0)
          num7 = numberGroupSizes[index3];
        int num8 = num7;
        int num9 = num12 + (num13 < 0 ? num13 : 0);
        for (int index4 = num10 > num9 ? num10 : num9; index4 > num7 && num8 != 0; num7 += num8)
        {
          ++index2;
          if (index2 >= span.Length)
          {
            int[] numArray = new int[span.Length * 2];
            span.CopyTo((Span<int>) numArray);
            span = (Span<int>) numArray;
          }
          span[index2] = num7;
          if (index3 < length2 - 1)
          {
            ++index3;
            num8 = numberGroupSizes[index3];
          }
        }
      }
      if (number.sign && num2 == 0)
        sb.Append(info.NegativeSign);
      bool flag3 = false;
      fixed (char* chPtr1 = &MemoryMarshal.GetReference<char>(format))
      {
        char* chPtr2 = digits;
label_93:
        while (index1 < format.Length)
        {
          char* chPtr3 = chPtr1;
          IntPtr num7 = (IntPtr) index1++ * 2;
          char ch;
          if ((ch = (char) *(ushort*) ((IntPtr) chPtr3 + num7)) != char.MinValue && ch != ';')
          {
            if (num13 > 0 && (ch == '#' || ch == '.' || ch == '0'))
            {
              for (; num13 > 0; --num13)
              {
                sb.Append(*chPtr2 != char.MinValue ? *chPtr2++ : '0');
                if (flag2 && num12 > 1 && (index2 >= 0 && num12 == span[index2] + 1))
                {
                  sb.Append(info.NumberGroupSeparator);
                  --index2;
                }
                --num12;
              }
            }
            switch (ch)
            {
              case '"':
              case '\'':
                while (index1 < format.Length && chPtr1[index1] != char.MinValue && (int) chPtr1[index1] != (int) ch)
                  sb.Append(chPtr1[index1++]);
                if (index1 < format.Length && chPtr1[index1] != char.MinValue)
                {
                  ++index1;
                  continue;
                }
                continue;
              case '#':
              case '0':
                char c;
                if (num13 < 0)
                {
                  ++num13;
                  c = num12 <= num10 ? '0' : char.MinValue;
                }
                else
                  c = *chPtr2 != char.MinValue ? *chPtr2++ : (num12 > num11 ? '0' : char.MinValue);
                if (c != char.MinValue)
                {
                  sb.Append(c);
                  if (flag2 && num12 > 1 && (index2 >= 0 && num12 == span[index2] + 1))
                  {
                    sb.Append(info.NumberGroupSeparator);
                    --index2;
                  }
                }
                --num12;
                continue;
              case '%':
                sb.Append(info.PercentSymbol);
                continue;
              case ',':
                continue;
              case '.':
                if (!((uint) num12 > 0U | flag3) && (num11 < 0 || num4 < num3 && *chPtr2 != char.MinValue))
                {
                  sb.Append(info.NumberDecimalSeparator);
                  flag3 = true;
                  continue;
                }
                continue;
              case 'E':
              case 'e':
                bool positiveSign = false;
                int minDigits = 0;
                if (flag1)
                {
                  if (index1 < format.Length && chPtr1[index1] == '0')
                    ++minDigits;
                  else if (index1 + 1 < format.Length && chPtr1[index1] == '+' && chPtr1[index1 + 1] == '0')
                    positiveSign = true;
                  else if (index1 + 1 >= format.Length || chPtr1[index1] != '-' || chPtr1[index1 + 1] != '0')
                  {
                    sb.Append(ch);
                    continue;
                  }
                  while (++index1 < format.Length && chPtr1[index1] == '0')
                    ++minDigits;
                  if (minDigits > 10)
                    minDigits = 10;
                  int num8 = *digits == char.MinValue ? 0 : number.scale - num4;
                  Number.FormatExponent(ref sb, info, num8, ch, minDigits, positiveSign);
                  flag1 = false;
                  continue;
                }
                sb.Append(ch);
                if (index1 < format.Length)
                {
                  if (chPtr1[index1] == '+' || chPtr1[index1] == '-')
                    sb.Append(chPtr1[index1++]);
                  while (true)
                  {
                    if (index1 < format.Length && chPtr1[index1] == '0')
                      sb.Append(chPtr1[index1++]);
                    else
                      goto label_93;
                  }
                }
                else
                  continue;
              case '\\':
                if (index1 < format.Length && chPtr1[index1] != char.MinValue)
                {
                  sb.Append(chPtr1[index1++]);
                  continue;
                }
                continue;
              case '‰':
                sb.Append(info.PerMilleSymbol);
                continue;
              default:
                sb.Append(ch);
                continue;
            }
          }
          else
            break;
        }
      }
    }

    private static void FormatCurrency(
      ref ValueStringBuilder sb,
      ref Number.NumberBuffer number,
      int nMinDigits,
      int nMaxDigits,
      NumberFormatInfo info)
    {
      foreach (char c in number.sign ? Number.s_negCurrencyFormats[info.CurrencyNegativePattern] : Number.s_posCurrencyFormats[info.CurrencyPositivePattern])
      {
        switch (c)
        {
          case '#':
            Number.FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.currencyGroupSizes, info.CurrencyDecimalSeparator, info.CurrencyGroupSeparator);
            break;
          case '$':
            sb.Append(info.CurrencySymbol);
            break;
          case '-':
            sb.Append(info.NegativeSign);
            break;
          default:
            sb.Append(c);
            break;
        }
      }
    }

    private static unsafe void FormatFixed(
      ref ValueStringBuilder sb,
      ref Number.NumberBuffer number,
      int nMinDigits,
      int nMaxDigits,
      NumberFormatInfo info,
      int[] groupDigits,
      string sDecimal,
      string sGroup)
    {
      int scale = number.scale;
      char* digits = number.digits;
      if (scale > 0)
      {
        if (groupDigits != null)
        {
          int index1 = 0;
          int length = scale;
          int num1 = 0;
          if (groupDigits.Length != 0)
          {
            int groupDigit = groupDigits[index1];
            while (scale > groupDigit && groupDigits[index1] != 0)
            {
              length += sGroup.Length;
              if (index1 < groupDigits.Length - 1)
                ++index1;
              groupDigit += groupDigits[index1];
              if (groupDigit < 0 || length < 0)
                throw new ArgumentOutOfRangeException();
            }
            num1 = groupDigit == 0 ? 0 : groupDigits[0];
          }
          int index2 = 0;
          int num2 = 0;
          int num3 = string.wcslen(digits);
          int num4 = scale < num3 ? scale : num3;
          fixed (char* chPtr1 = &MemoryMarshal.GetReference<char>(sb.AppendSpan(length)))
          {
            char* chPtr2 = chPtr1 + length - 1;
            for (int index3 = scale - 1; index3 >= 0; --index3)
            {
              *chPtr2-- = index3 < num4 ? digits[index3] : '0';
              if (num1 > 0)
              {
                ++num2;
                if (num2 == num1 && index3 != 0)
                {
                  for (int index4 = sGroup.Length - 1; index4 >= 0; --index4)
                    *chPtr2-- = sGroup[index4];
                  if (index2 < groupDigits.Length - 1)
                  {
                    ++index2;
                    num1 = groupDigits[index2];
                  }
                  num2 = 0;
                }
              }
            }
            digits += num4;
          }
        }
        else
        {
          do
          {
            sb.Append(*digits != char.MinValue ? *digits++ : '0');
          }
          while (--scale > 0);
        }
      }
      else
        sb.Append('0');
      if (nMaxDigits <= 0)
        return;
      sb.Append(sDecimal);
      if (scale < 0 && nMaxDigits > 0)
      {
        int count = Math.Min(-scale, nMaxDigits);
        sb.Append('0', count);
        int num = scale + count;
        nMaxDigits -= count;
      }
      for (; nMaxDigits > 0; --nMaxDigits)
        sb.Append(*digits != char.MinValue ? *digits++ : '0');
    }

    private static void FormatNumber(
      ref ValueStringBuilder sb,
      ref Number.NumberBuffer number,
      int nMinDigits,
      int nMaxDigits,
      NumberFormatInfo info)
    {
      foreach (char c in number.sign ? Number.s_negNumberFormats[info.NumberNegativePattern] : "#")
      {
        switch (c)
        {
          case '#':
            Number.FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.numberGroupSizes, info.NumberDecimalSeparator, info.NumberGroupSeparator);
            break;
          case '-':
            sb.Append(info.NegativeSign);
            break;
          default:
            sb.Append(c);
            break;
        }
      }
    }

    private static unsafe void FormatScientific(
      ref ValueStringBuilder sb,
      ref Number.NumberBuffer number,
      int nMinDigits,
      int nMaxDigits,
      NumberFormatInfo info,
      char expChar)
    {
      char* digits = number.digits;
      sb.Append(*digits != char.MinValue ? *digits++ : '0');
      if (nMaxDigits != 1)
        sb.Append(info.NumberDecimalSeparator);
      while (--nMaxDigits > 0)
        sb.Append(*digits != char.MinValue ? *digits++ : '0');
      int num = *number.digits == char.MinValue ? 0 : number.scale - 1;
      Number.FormatExponent(ref sb, info, num, expChar, 3, true);
    }

    private static unsafe void FormatExponent(
      ref ValueStringBuilder sb,
      NumberFormatInfo info,
      int value,
      char expChar,
      int minDigits,
      bool positiveSign)
    {
      sb.Append(expChar);
      if (value < 0)
      {
        sb.Append(info.NegativeSign);
        value = -value;
      }
      else if (positiveSign)
        sb.Append(info.PositiveSign);
      char* chPtr = stackalloc char[10];
      char* decChars = Number.UInt32ToDecChars(chPtr + 10, (uint) value, minDigits);
      int num = (int) (chPtr + 10 - decChars);
      sb.Append(decChars, (int) (chPtr + 10 - decChars));
    }

    private static unsafe void FormatGeneral(
      ref ValueStringBuilder sb,
      ref Number.NumberBuffer number,
      int nMinDigits,
      int nMaxDigits,
      NumberFormatInfo info,
      char expChar,
      bool bSuppressScientific)
    {
      int num = number.scale;
      bool flag = false;
      if (!bSuppressScientific && (num > nMaxDigits || num < -3))
      {
        num = 1;
        flag = true;
      }
      char* digits = number.digits;
      if (num > 0)
      {
        do
        {
          sb.Append(*digits != char.MinValue ? *digits++ : '0');
        }
        while (--num > 0);
      }
      else
        sb.Append('0');
      if (*digits != char.MinValue || num < 0)
      {
        sb.Append(info.NumberDecimalSeparator);
        for (; num < 0; ++num)
          sb.Append('0');
        while (*digits != char.MinValue)
          sb.Append(*digits++);
      }
      if (!flag)
        return;
      Number.FormatExponent(ref sb, info, number.scale - 1, expChar, 2, true);
    }

    private static void FormatPercent(
      ref ValueStringBuilder sb,
      ref Number.NumberBuffer number,
      int nMinDigits,
      int nMaxDigits,
      NumberFormatInfo info)
    {
      foreach (char c in number.sign ? Number.s_negPercentFormats[info.PercentNegativePattern] : Number.s_posPercentFormats[info.PercentPositivePattern])
      {
        switch (c)
        {
          case '#':
            Number.FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.percentGroupSizes, info.PercentDecimalSeparator, info.PercentGroupSeparator);
            break;
          case '%':
            sb.Append(info.PercentSymbol);
            break;
          case '-':
            sb.Append(info.NegativeSign);
            break;
          default:
            sb.Append(c);
            break;
        }
      }
    }

    private static unsafe void RoundNumber(ref Number.NumberBuffer number, int pos)
    {
      char* digits = number.digits;
      int index = 0;
      while (index < pos && digits[index] != char.MinValue)
        ++index;
      if (index == pos && digits[index] >= '5')
      {
        while (index > 0 && digits[index - 1] == '9')
          --index;
        if (index > 0)
        {
          char* chPtr = digits + (index - 1);
          *chPtr = (char) ((uint) *chPtr + 1U);
        }
        else
        {
          ++number.scale;
          *digits = '1';
          index = 1;
        }
      }
      else
      {
        while (index > 0 && digits[index - 1] == '0')
          --index;
      }
      if (index == 0)
      {
        number.scale = 0;
        number.sign = false;
      }
      digits[index] = char.MinValue;
    }

    private static unsafe int FindSection(ReadOnlySpan<char> format, int section)
    {
      if (section == 0)
        return 0;
      fixed (char* chPtr1 = &MemoryMarshal.GetReference<char>(format))
      {
        int index = 0;
        while (index < format.Length)
        {
          char* chPtr2 = chPtr1;
          IntPtr num = (IntPtr) index++ * 2;
          char ch;
          switch (ch = (char) *(ushort*) ((IntPtr) chPtr2 + num))
          {
            case char.MinValue:
              return 0;
            case '"':
            case '\'':
              do
                ;
              while (index < format.Length && chPtr1[index] != char.MinValue && (int) chPtr1[index++] != (int) ch);
              continue;
            case ';':
              if (--section == 0)
              {
                if (index < format.Length && chPtr1[index] != char.MinValue && chPtr1[index] != ';')
                  return index;
                goto case '\0';
              }
              else
                continue;
            case '\\':
              if (index < format.Length && chPtr1[index] != char.MinValue)
              {
                ++index;
                continue;
              }
              continue;
            default:
              continue;
          }
        }
        return 0;
      }
    }

    private static uint Low32(ulong value)
    {
      return (uint) value;
    }

    private static uint High32(ulong value)
    {
      return (uint) ((value & 18446744069414584320UL) >> 32);
    }

    private static uint Int64DivMod1E9(ref ulong value)
    {
      uint num = (uint) (value % 1000000000UL);
      value /= 1000000000UL;
      return num;
    }

    private static bool HexNumberToInt32(ref Number.NumberBuffer number, ref int value)
    {
      uint num = 0;
      bool uint32 = Number.HexNumberToUInt32(ref number, ref num);
      value = (int) num;
      return uint32;
    }

    private static bool HexNumberToInt64(ref Number.NumberBuffer number, ref long value)
    {
      ulong num = 0;
      bool uint64 = Number.HexNumberToUInt64(ref number, ref num);
      value = (long) num;
      return uint64;
    }

    private static unsafe bool HexNumberToUInt32(ref Number.NumberBuffer number, ref uint value)
    {
      int scale = number.scale;
      if (scale > 10 || scale < number.precision)
        return false;
      char* digits = number.digits;
      uint num1 = 0;
      while (--scale >= 0)
      {
        if (num1 > 268435455U)
          return false;
        num1 *= 16U;
        if (*digits != char.MinValue)
        {
          uint num2 = num1;
          if (*digits != char.MinValue)
          {
            if (*digits >= '0' && *digits <= '9')
              num2 += (uint) *digits - 48U;
            else if (*digits >= 'A' && *digits <= 'F')
              num2 += (uint) ((int) *digits - 65 + 10);
            else
              num2 += (uint) ((int) *digits - 97 + 10);
            ++digits;
          }
          if (num2 < num1)
            return false;
          num1 = num2;
        }
      }
      value = num1;
      return true;
    }

    private static unsafe bool HexNumberToUInt64(ref Number.NumberBuffer number, ref ulong value)
    {
      int scale = number.scale;
      if (scale > 20 || scale < number.precision)
        return false;
      char* digits = number.digits;
      ulong num1 = 0;
      while (--scale >= 0)
      {
        if (num1 > 1152921504606846975UL)
          return false;
        num1 *= 16UL;
        if (*digits != char.MinValue)
        {
          ulong num2 = num1;
          if (*digits != char.MinValue)
          {
            if (*digits >= '0' && *digits <= '9')
              num2 += (ulong) ((int) *digits - 48);
            else if (*digits >= 'A' && *digits <= 'F')
              num2 += (ulong) ((int) *digits - 65 + 10);
            else
              num2 += (ulong) ((int) *digits - 97 + 10);
            ++digits;
          }
          if (num2 < num1)
            return false;
          num1 = num2;
        }
      }
      value = num1;
      return true;
    }

    private static unsafe bool NumberToInt32(ref Number.NumberBuffer number, ref int value)
    {
      int scale = number.scale;
      if (scale > 10 || scale < number.precision)
        return false;
      char* digits = number.digits;
      int num = 0;
      while (--scale >= 0)
      {
        if ((uint) num > 214748364U)
          return false;
        num *= 10;
        if (*digits != char.MinValue)
          num += (int) *digits++ - 48;
      }
      if (number.sign)
      {
        num = -num;
        if (num > 0)
          return false;
      }
      else if (num < 0)
        return false;
      value = num;
      return true;
    }

    private static unsafe bool NumberToInt64(ref Number.NumberBuffer number, ref long value)
    {
      int scale = number.scale;
      if (scale > 19 || scale < number.precision)
        return false;
      char* digits = number.digits;
      long num = 0;
      while (--scale >= 0)
      {
        if ((ulong) num > 922337203685477580UL)
          return false;
        num *= 10L;
        if (*digits != char.MinValue)
          num += (long) ((int) *digits++ - 48);
      }
      if (number.sign)
      {
        num = -num;
        if (num > 0L)
          return false;
      }
      else if (num < 0L)
        return false;
      value = num;
      return true;
    }

    private static unsafe bool NumberToUInt32(ref Number.NumberBuffer number, ref uint value)
    {
      int scale = number.scale;
      if (scale > 10 || scale < number.precision || number.sign)
        return false;
      char* digits = number.digits;
      uint num1 = 0;
      while (--scale >= 0)
      {
        if (num1 > 429496729U)
          return false;
        num1 *= 10U;
        if (*digits != char.MinValue)
        {
          uint num2 = num1 + ((uint) *digits++ - 48U);
          if (num2 < num1)
            return false;
          num1 = num2;
        }
      }
      value = num1;
      return true;
    }

    private static unsafe bool NumberToUInt64(ref Number.NumberBuffer number, ref ulong value)
    {
      int scale = number.scale;
      if (scale > 20 || scale < number.precision || number.sign)
        return false;
      char* digits = number.digits;
      ulong num1 = 0;
      while (--scale >= 0)
      {
        if (num1 > 1844674407370955161UL)
          return false;
        num1 *= 10UL;
        if (*digits != char.MinValue)
        {
          ulong num2 = num1 + (ulong) ((int) *digits++ - 48);
          if (num2 < num1)
            return false;
          num1 = num2;
        }
      }
      value = num1;
      return true;
    }

    internal static int ParseInt32(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      int num = 0;
      Number.StringToNumber(s, style, ref number, info, false);
      if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
      {
        if (!Number.HexNumberToInt32(ref number, ref num))
          throw new OverflowException(SR.Overflow_Int32);
      }
      else if (!Number.NumberToInt32(ref number, ref num))
        throw new OverflowException(SR.Overflow_Int32);
      return num;
    }

    internal static long ParseInt64(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      long num = 0;
      Number.StringToNumber(value, options, ref number, numfmt, false);
      if ((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
      {
        if (!Number.HexNumberToInt64(ref number, ref num))
          throw new OverflowException(SR.Overflow_Int64);
      }
      else if (!Number.NumberToInt64(ref number, ref num))
        throw new OverflowException(SR.Overflow_Int64);
      return num;
    }

    internal static uint ParseUInt32(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      uint num = 0;
      Number.StringToNumber(value, options, ref number, numfmt, false);
      if ((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
      {
        if (!Number.HexNumberToUInt32(ref number, ref num))
          throw new OverflowException(SR.Overflow_UInt32);
      }
      else if (!Number.NumberToUInt32(ref number, ref num))
        throw new OverflowException(SR.Overflow_UInt32);
      return num;
    }

    internal static ulong ParseUInt64(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      ulong num = 0;
      Number.StringToNumber(value, options, ref number, numfmt, false);
      if ((options & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
      {
        if (!Number.HexNumberToUInt64(ref number, ref num))
          throw new OverflowException(SR.Overflow_UInt64);
      }
      else if (!Number.NumberToUInt64(ref number, ref num))
        throw new OverflowException(SR.Overflow_UInt64);
      return num;
    }

    private static unsafe bool ParseNumber(
      ref char* str,
      char* strEnd,
      NumberStyles options,
      ref Number.NumberBuffer number,
      NumberFormatInfo numfmt,
      bool parseDecimal)
    {
      number.scale = 0;
      number.sign = false;
      string str1 = (string) null;
      bool flag1 = false;
      string decimalSeparator;
      string str2;
      if ((options & NumberStyles.AllowCurrencySymbol) != NumberStyles.None)
      {
        str1 = numfmt.CurrencySymbol;
        decimalSeparator = numfmt.CurrencyDecimalSeparator;
        str2 = numfmt.CurrencyGroupSeparator;
        flag1 = true;
      }
      else
      {
        decimalSeparator = numfmt.NumberDecimalSeparator;
        str2 = numfmt.NumberGroupSeparator;
      }
      int num1 = 0;
      char* p = str;
      char ch = p < strEnd ? *p : char.MinValue;
      while (true)
      {
        if (!Number.IsWhite(ch) || (options & NumberStyles.AllowLeadingWhite) == NumberStyles.None || (num1 & 1) != 0 && (num1 & 32) == 0 && numfmt.NumberNegativePattern != 2)
        {
          char* chPtr1;
          if ((options & NumberStyles.AllowLeadingSign) != NumberStyles.None && (num1 & 1) == 0 && ((IntPtr) (chPtr1 = Number.MatchChars(p, strEnd, numfmt.PositiveSign)) != IntPtr.Zero || (IntPtr) (chPtr1 = Number.MatchChars(p, strEnd, numfmt.NegativeSign)) != IntPtr.Zero && (number.sign = true)))
          {
            num1 |= 1;
            p = chPtr1 - 1;
          }
          else if (ch == '(' && (options & NumberStyles.AllowParentheses) != NumberStyles.None && (num1 & 1) == 0)
          {
            num1 |= 3;
            number.sign = true;
          }
          else
          {
            char* chPtr2;
            if (str1 != null && (IntPtr) (chPtr2 = Number.MatchChars(p, strEnd, str1)) != IntPtr.Zero)
            {
              num1 |= 32;
              str1 = (string) null;
              p = chPtr2 - 1;
            }
            else
              break;
          }
        }
        ch = ++p < strEnd ? *p : char.MinValue;
      }
      int num2 = 0;
      int index = 0;
      while (true)
      {
        if (ch >= '0' && ch <= '9' || (options & NumberStyles.AllowHexSpecifier) != NumberStyles.None && (ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F'))
        {
          num1 |= 4;
          if (ch != '0' || (num1 & 8) != 0)
          {
            if (num2 < 50)
            {
              number.digits[num2++] = ch;
              if (ch != '0' | parseDecimal)
                index = num2;
            }
            if ((num1 & 16) == 0)
              ++number.scale;
            num1 |= 8;
          }
          else if ((num1 & 16) != 0)
            --number.scale;
        }
        else
        {
          char* chPtr1;
          if ((options & NumberStyles.AllowDecimalPoint) != NumberStyles.None && (num1 & 16) == 0 && ((IntPtr) (chPtr1 = Number.MatchChars(p, strEnd, decimalSeparator)) != IntPtr.Zero || flag1 && (num1 & 32) == 0 && (IntPtr) (chPtr1 = Number.MatchChars(p, strEnd, numfmt.NumberDecimalSeparator)) != IntPtr.Zero))
          {
            num1 |= 16;
            p = chPtr1 - 1;
          }
          else
          {
            char* chPtr2;
            if ((options & NumberStyles.AllowThousands) != NumberStyles.None && (num1 & 4) != 0 && (num1 & 16) == 0 && ((IntPtr) (chPtr2 = Number.MatchChars(p, strEnd, str2)) != IntPtr.Zero || flag1 && (num1 & 32) == 0 && (IntPtr) (chPtr2 = Number.MatchChars(p, strEnd, numfmt.NumberGroupSeparator)) != IntPtr.Zero))
              p = chPtr2 - 1;
            else
              break;
          }
        }
        ch = ++p < strEnd ? *p : char.MinValue;
      }
      bool flag2 = false;
      number.precision = index;
      number.digits[index] = char.MinValue;
      if ((num1 & 4) != 0)
      {
        if ((ch == 'E' || ch == 'e') && (options & NumberStyles.AllowExponent) != NumberStyles.None)
        {
          char* chPtr1 = p;
          ch = ++p < strEnd ? *p : char.MinValue;
          char* chPtr2;
          if ((IntPtr) (chPtr2 = Number.MatchChars(p, strEnd, numfmt.positiveSign)) != IntPtr.Zero)
          {
            ch = (p = chPtr2) < strEnd ? *p : char.MinValue;
          }
          else
          {
            char* chPtr3;
            if ((IntPtr) (chPtr3 = Number.MatchChars(p, strEnd, numfmt.negativeSign)) != IntPtr.Zero)
            {
              ch = (p = chPtr3) < strEnd ? *p : char.MinValue;
              flag2 = true;
            }
          }
          if (ch >= '0' && ch <= '9')
          {
            int num3 = 0;
            do
            {
              num3 = num3 * 10 + ((int) ch - 48);
              ch = ++p < strEnd ? *p : char.MinValue;
              if (num3 > 1000)
              {
                num3 = 9999;
                while (ch >= '0' && ch <= '9')
                  ch = ++p < strEnd ? *p : char.MinValue;
              }
            }
            while (ch >= '0' && ch <= '9');
            if (flag2)
              num3 = -num3;
            number.scale += num3;
          }
          else
          {
            p = chPtr1;
            ch = p < strEnd ? *p : char.MinValue;
          }
        }
        while (true)
        {
          if (!Number.IsWhite(ch) || (options & NumberStyles.AllowTrailingWhite) == NumberStyles.None)
          {
            char* chPtr1;
            if ((options & NumberStyles.AllowTrailingSign) != NumberStyles.None && (num1 & 1) == 0 && ((IntPtr) (chPtr1 = Number.MatchChars(p, strEnd, numfmt.PositiveSign)) != IntPtr.Zero || (IntPtr) (chPtr1 = Number.MatchChars(p, strEnd, numfmt.NegativeSign)) != IntPtr.Zero && (number.sign = true)))
            {
              num1 |= 1;
              p = chPtr1 - 1;
            }
            else if (ch == ')' && (num1 & 2) != 0)
            {
              num1 &= -3;
            }
            else
            {
              char* chPtr2;
              if (str1 != null && (IntPtr) (chPtr2 = Number.MatchChars(p, strEnd, str1)) != IntPtr.Zero)
              {
                str1 = (string) null;
                p = chPtr2 - 1;
              }
              else
                break;
            }
          }
          ch = ++p < strEnd ? *p : char.MinValue;
        }
        if ((num1 & 2) == 0)
        {
          if ((num1 & 8) == 0)
          {
            if (!parseDecimal)
              number.scale = 0;
            if ((num1 & 16) == 0)
              number.sign = false;
          }
          str = p;
          return true;
        }
      }
      str = p;
      return false;
    }

    internal static bool TryParseInt32(
      ReadOnlySpan<char> s,
      NumberStyles style,
      NumberFormatInfo info,
      out int result)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      result = 0;
      if (!Number.TryStringToNumber(s, style, ref number, info, false))
        return false;
      if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
      {
        if (!Number.HexNumberToInt32(ref number, ref result))
          return false;
      }
      else if (!Number.NumberToInt32(ref number, ref result))
        return false;
      return true;
    }

    internal static bool TryParseInt64(
      ReadOnlySpan<char> s,
      NumberStyles style,
      NumberFormatInfo info,
      out long result)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      result = 0L;
      if (!Number.TryStringToNumber(s, style, ref number, info, false))
        return false;
      if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
      {
        if (!Number.HexNumberToInt64(ref number, ref result))
          return false;
      }
      else if (!Number.NumberToInt64(ref number, ref result))
        return false;
      return true;
    }

    internal static bool TryParseUInt32(
      ReadOnlySpan<char> s,
      NumberStyles style,
      NumberFormatInfo info,
      out uint result)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      result = 0U;
      if (!Number.TryStringToNumber(s, style, ref number, info, false))
        return false;
      if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
      {
        if (!Number.HexNumberToUInt32(ref number, ref result))
          return false;
      }
      else if (!Number.NumberToUInt32(ref number, ref result))
        return false;
      return true;
    }

    internal static bool TryParseUInt64(
      ReadOnlySpan<char> s,
      NumberStyles style,
      NumberFormatInfo info,
      out ulong result)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      result = 0UL;
      if (!Number.TryStringToNumber(s, style, ref number, info, false))
        return false;
      if ((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None)
      {
        if (!Number.HexNumberToUInt64(ref number, ref result))
          return false;
      }
      else if (!Number.NumberToUInt64(ref number, ref result))
        return false;
      return true;
    }

    internal static Decimal ParseDecimal(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      Decimal num = new Decimal();
      Number.StringToNumber(value, options, ref number, numfmt, true);
      if (!Number.NumberBufferToDecimal(ref number, ref num))
        throw new OverflowException(SR.Overflow_Decimal);
      return num;
    }

    internal static double ParseDouble(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      double num = 0.0;
      if (!Number.TryStringToNumber(value, options, ref number, numfmt, false))
      {
        ReadOnlySpan<char> span = value.Trim();
        if (span.EqualsOrdinal((ReadOnlySpan<char>) numfmt.PositiveInfinitySymbol))
          return double.PositiveInfinity;
        if (span.EqualsOrdinal((ReadOnlySpan<char>) numfmt.NegativeInfinitySymbol))
          return double.NegativeInfinity;
        if (span.EqualsOrdinal((ReadOnlySpan<char>) numfmt.NaNSymbol))
          return double.NaN;
        throw new FormatException(SR.Format_InvalidString);
      }
      if (!Number.NumberBufferToDouble(ref number, ref num))
        throw new OverflowException(SR.Overflow_Double);
      return num;
    }

    internal static float ParseSingle(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      double num = 0.0;
      if (!Number.TryStringToNumber(value, options, ref number, numfmt, false))
      {
        ReadOnlySpan<char> span = value.Trim();
        if (span.EqualsOrdinal((ReadOnlySpan<char>) numfmt.PositiveInfinitySymbol))
          return float.PositiveInfinity;
        if (span.EqualsOrdinal((ReadOnlySpan<char>) numfmt.NegativeInfinitySymbol))
          return float.NegativeInfinity;
        if (span.EqualsOrdinal((ReadOnlySpan<char>) numfmt.NaNSymbol))
          return float.NaN;
        throw new FormatException(SR.Format_InvalidString);
      }
      if (!Number.NumberBufferToDouble(ref number, ref num))
        throw new OverflowException(SR.Overflow_Single);
      float f = (float) num;
      if (float.IsInfinity(f))
        throw new OverflowException(SR.Overflow_Single);
      return f;
    }

    internal static bool TryParseDecimal(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt,
      out Decimal result)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      result = new Decimal();
      return Number.TryStringToNumber(value, options, ref number, numfmt, true) && Number.NumberBufferToDecimal(ref number, ref result);
    }

    internal static bool TryParseDouble(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt,
      out double result)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      result = 0.0;
      return Number.TryStringToNumber(value, options, ref number, numfmt, false) && Number.NumberBufferToDouble(ref number, ref result);
    }

    internal static bool TryParseSingle(
      ReadOnlySpan<char> value,
      NumberStyles options,
      NumberFormatInfo numfmt,
      out float result)
    {
      Number.NumberBuffer number = new Number.NumberBuffer();
      result = 0.0f;
      double num = 0.0;
      if (!Number.TryStringToNumber(value, options, ref number, numfmt, false) || !Number.NumberBufferToDouble(ref number, ref num))
        return false;
      float f = (float) num;
      if (float.IsInfinity(f))
        return false;
      result = f;
      return true;
    }

    private static unsafe void StringToNumber(
      ReadOnlySpan<char> str,
      NumberStyles options,
      ref Number.NumberBuffer number,
      NumberFormatInfo info,
      bool parseDecimal)
    {
      fixed (char* chPtr = &MemoryMarshal.GetReference<char>(str))
      {
        char* str1 = chPtr;
        if (!Number.ParseNumber(ref str1, str1 + str.Length, options, ref number, info, parseDecimal) || str1 - chPtr < (long) str.Length && !Number.TrailingZeros(str, (int) (str1 - chPtr)))
          throw new FormatException(SR.Format_InvalidString);
      }
    }

    internal static unsafe bool TryStringToNumber(
      ReadOnlySpan<char> str,
      NumberStyles options,
      ref Number.NumberBuffer number,
      NumberFormatInfo numfmt,
      bool parseDecimal)
    {
      fixed (char* chPtr = &MemoryMarshal.GetReference<char>(str))
      {
        char* str1 = chPtr;
        if (!Number.ParseNumber(ref str1, str1 + str.Length, options, ref number, numfmt, parseDecimal) || str1 - chPtr < (long) str.Length && !Number.TrailingZeros(str, (int) (str1 - chPtr)))
          return false;
      }
      return true;
    }

    private static bool TrailingZeros(ReadOnlySpan<char> s, int index)
    {
      for (int index1 = index; index1 < s.Length; ++index1)
      {
        if (s[index1] != char.MinValue)
          return false;
      }
      return true;
    }

    private static unsafe char* MatchChars(char* p, char* pEnd, string str)
    {
      fixed (char* str1 = str)
        return Number.MatchChars(p, pEnd, str1);
    }

    private static unsafe char* MatchChars(char* p, char* pEnd, char* str)
    {
      if (*str == char.MinValue)
        return (char*) null;
      do
      {
        char ch = p < pEnd ? *p : char.MinValue;
        if ((int) ch == (int) *str || *str == ' ' && ch == ' ')
        {
          ++p;
          ++str;
        }
        else
          goto label_5;
      }
      while (*str != char.MinValue);
      return p;
label_5:
      return (char*) null;
    }

    private static bool IsWhite(char ch)
    {
      if (ch == ' ')
        return true;
      if (ch >= '\t')
        return ch <= '\r';
      return false;
    }

    private static bool NumberBufferToDouble(ref Number.NumberBuffer number, ref double value)
    {
      double d = Number.NumberToDouble(ref number);
      uint num1 = Number.DoubleHelper.Exponent(d);
      ulong num2 = Number.DoubleHelper.Mantissa(d);
      switch (num1)
      {
        case 0:
          if (num2 == 0UL)
          {
            d = 0.0;
            break;
          }
          break;
        case 2047:
          return false;
      }
      value = d;
      return true;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal ref struct NumberBuffer
    {
      public int precision;
      public int scale;
      private int _sign;
      private Number.NumberBuffer.DigitsAndNullTerminator _digits;
      private unsafe char* _allDigits;

      public bool sign
      {
        get
        {
          return (uint) this._sign > 0U;
        }
        set
        {
          this._sign = value ? 1 : 0;
        }
      }

      public unsafe char* digits
      {
        get
        {
          return (char*) Unsafe.AsPointer<Number.NumberBuffer.DigitsAndNullTerminator>(ref this._digits);
        }
      }

      [StructLayout(LayoutKind.Sequential, Size = 102)]
      private struct DigitsAndNullTerminator
      {
      }
    }

    private static class DoubleHelper
    {
      public static unsafe uint Exponent(double d)
      {
        return *(uint*) ((byte*) &d + 4) >> 20 & 2047U;
      }

      public static unsafe ulong Mantissa(double d)
      {
        return (ulong) (*(long*) &d & 4503599627370495L);
      }
    }
  }
}
