diff --git a/src/libraries/Common/src/System/Number.NumberBuffer.cs b/src/libraries/Common/src/System/Number.NumberBuffer.cs
index 44c1d47d96dcab..325f752ec625c2 100644
--- a/src/libraries/Common/src/System/Number.NumberBuffer.cs
+++ b/src/libraries/Common/src/System/Number.NumberBuffer.cs
@@ -21,6 +21,9 @@ internal static partial class Number
internal const int UInt32NumberBufferLength = 10 + 1; // 10 for the longest input: 4,294,967,295
internal const int UInt64NumberBufferLength = 20 + 1; // 20 for the longest input: 18,446,744,073,709,551,615
internal const int UInt128NumberBufferLength = 39 + 1; // 39 for the longest input: 340,282,366,920,938,463,463,374,607,431,768,211,455
+ internal const int Decimal32NumberBufferLength = 97 + 1 + 1; // 97 for the longest input + 1 for rounding
+ internal const int Decimal64NumberBufferLength = 385 + 1 + 1; // 385 for the longest input + 1 for rounding
+ internal const int Decimal128NumberBufferLength = 6145 + 1 + 1; // 6145 for the longest input + 1 for rounding
internal unsafe ref struct NumberBuffer
{
diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
index 2ced3b884d6fa3..b8252764421382 100644
--- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
+++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
@@ -540,6 +540,15 @@
Object must be of type Decimal.
+
+ Object must be of type Decimal32.
+
+
+ Object must be of type Decimal64.
+
+
+ Object must be of type Decimal128.
+
Type must derive from Delegate.
diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index a25bcdfc984f28..7bc265f531bcb8 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -436,6 +436,10 @@
+
+
+
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs
index 733faa5320aab3..adf8cb452b94cb 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs
@@ -1324,6 +1324,31 @@ public ulong ToUInt64()
return 0;
}
+ public UInt128 ToUInt128()
+ {
+ if (_length > 3)
+ {
+ return new UInt128(((ulong)(_blocks[3]) << 96) + ((ulong)_blocks[2] << 64), ((ulong)(_blocks[1]) << 32) + _blocks[0]);
+ }
+
+ if (_length > 2)
+ {
+ return new UInt128(((ulong)_blocks[2] << 64), ((ulong)(_blocks[1]) << 32) + _blocks[0]);
+ }
+
+ if (_length > 1)
+ {
+ return ((ulong)(_blocks[1]) << 32) + _blocks[0];
+ }
+
+ if (_length > 0)
+ {
+ return _blocks[0];
+ }
+
+ return 0;
+ }
+
private void Clear(uint length) =>
NativeMemory.Clear(
(byte*)Unsafe.AsPointer(ref _blocks[0]), // This is safe to do since we are a ref struct
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.DecimalIeee754.cs b/src/libraries/System.Private.CoreLib/src/System/Number.DecimalIeee754.cs
new file mode 100644
index 00000000000000..9b801cb7380409
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.DecimalIeee754.cs
@@ -0,0 +1,352 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Numerics;
+
+namespace System
+{
+ internal static partial class Number
+ {
+ internal static unsafe TValue ConstructorToDecimalIeee754Bits(bool signed, TValue significand, int exponent)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ if (TValue.IsZero(significand))
+ {
+ return TDecimal.Zero;
+ }
+
+ if (significand > TDecimal.MaxSignificand || exponent > TDecimal.MaxExponent || exponent < TDecimal.MinExponent)
+ {
+ return ConstructorToDecimalIeee754BitsRounding(signed, significand, exponent);
+ }
+
+ return DecimalIeee754BinaryEncoding(signed, significand, exponent);
+
+ // This method adjusts the significand and exponent to ensure they fall within valid bounds.
+ // It handles underflow and overflow of the exponent by trimming or padding digits accordingly,
+ // and applies rounding when the number of digits exceeds the allowed precision.
+ static TValue ConstructorToDecimalIeee754BitsRounding(bool signed, TValue significand, int exponent)
+ {
+ byte* pDigits = stackalloc byte[TDecimal.SignificandBufferLength];
+ NumberBuffer number = new NumberBuffer(NumberBufferKind.Integer, pDigits, TDecimal.SignificandBufferLength);
+ TDecimal.ToNumber(significand, ref number);
+
+ if (exponent < TDecimal.MinExponent)
+ {
+ int numberDigitsRemove = (TDecimal.MinExponent - exponent);
+
+ if (numberDigitsRemove < number.DigitsCount)
+ {
+ int numberDigitsRemain = number.DigitsCount - numberDigitsRemove;
+ DecimalIeee754Rounding(ref number, numberDigitsRemain, out significand, out int extraExponent);
+ exponent += extraExponent;
+ }
+ else
+ {
+ return TDecimal.Zero;
+ }
+ }
+ else if (exponent > TDecimal.MaxExponent)
+ {
+ int numberZeroDigits = exponent - TDecimal.MaxExponent;
+
+ if (number.DigitsCount + numberZeroDigits <= TDecimal.Precision)
+ {
+ byte* p = number.DigitsPtr + number.DigitsCount;
+
+ for (int i = 0; i < numberZeroDigits; i++)
+ {
+ *p = (byte)'0';
+ p++;
+ }
+
+ *p = (byte)'\0';
+ number.DigitsCount += numberZeroDigits;
+ number.Scale += numberZeroDigits;
+
+ exponent -= numberZeroDigits;
+ significand = TDecimal.NumberToSignificand(ref number, number.DigitsCount);
+ }
+ else
+ {
+ return signed ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
+ }
+ }
+ else if (number.DigitsCount > TDecimal.Precision)
+ {
+ DecimalIeee754Rounding(ref number, TDecimal.Precision, out significand, out int extraExponent);
+ exponent += extraExponent;
+
+ if (exponent >= TDecimal.MaxExponent)
+ {
+ return signed ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
+ }
+ }
+
+ return DecimalIeee754BinaryEncoding(signed, significand, exponent);
+ }
+ }
+
+ internal struct DecimalIeee754
+ where TSignificand : IBinaryInteger
+ {
+ public bool Signed { get; }
+ public int Exponent { get; }
+ public TSignificand Significand { get; }
+
+ public DecimalIeee754(bool signed, int exponent, TSignificand significand)
+ {
+ Signed = signed;
+ Exponent = exponent;
+ Significand = significand;
+ }
+ }
+
+ internal static DecimalIeee754 UnpackDecimalIeee754(TValue value)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ bool signed = (value & TDecimal.SignMask) != TValue.Zero;
+ TValue significand;
+ int exponent;
+
+ if ((value & TDecimal.G0G1Mask) == TDecimal.G0G1Mask)
+ {
+ exponent = TDecimal.ConvertToExponent((value & TDecimal.G2ToGwPlus3ExponentMask) >> (TDecimal.NumberBitsSignificand + 1));
+ significand =(value & TDecimal.GwPlus4SignificandMask) | TDecimal.MostSignificantBitOfSignificandMask;
+ }
+ else
+ {
+ exponent = TDecimal.ConvertToExponent((value & TDecimal.G0ToGwPlus1ExponentMask) >> (TDecimal.NumberBitsSignificand + 3));
+ significand = value & TDecimal.GwPlus2ToGwPlus4SignificandMask;
+ }
+
+ return new DecimalIeee754(signed, exponent - TDecimal.ExponentBias, significand);
+ }
+
+ internal static int CompareDecimalIeee754(TValue currentValue, TValue otherValue)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ if (currentValue == otherValue)
+ {
+ return 0;
+ }
+ DecimalIeee754 current = UnpackDecimalIeee754(currentValue);
+ DecimalIeee754 other = UnpackDecimalIeee754(otherValue);
+
+ if (current.Signed)
+ {
+ if (!other.Signed)
+ {
+ return -1;
+ }
+ }
+ else if (other.Signed)
+ {
+ return 1;
+ }
+
+ if (current.Signed)
+ {
+ (current, other) = (other, current);
+ }
+
+ // This method is needed to correctly compare decimals that represent the same numeric value
+ // but have different exponent/significand pairs. For example, 10e2 and 1e3 have different exponents,
+ // but represent the same number (1000). This function normalizes exponents and compares them accordingly,
+ // without considering sign.
+ return InternalUnsignedCompare(current, other);
+
+ static int InternalUnsignedCompare(DecimalIeee754 current, DecimalIeee754 other)
+ {
+ if (current.Exponent == other.Exponent && current.Significand == other.Significand)
+ {
+ return 0;
+ }
+
+ if (current.Exponent < other.Exponent)
+ {
+ return -InternalUnsignedCompare(other, current);
+ }
+
+ if (current.Significand >= other.Significand)
+ {
+ return 1;
+ }
+
+ int diffExponent = current.Exponent - other.Exponent;
+ if (diffExponent < TDecimal.Precision)
+ {
+ TValue factor = TDecimal.Power10(diffExponent);
+ (TValue quotient, TValue remainder) = TValue.DivRem(other.Significand, current.Significand);
+
+ if (quotient < factor)
+ {
+ return 1;
+ }
+ if (quotient > factor)
+ {
+ return -1;
+ }
+ if (remainder > TValue.Zero)
+ {
+ return -1;
+ }
+ return 0;
+ }
+
+ return 1;
+ }
+ }
+
+ private static unsafe TValue NumberToDecimalIeee754Bits(ref NumberBuffer number)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ Debug.Assert(number.DigitsPtr[0] != '0');
+ Debug.Assert(number.DigitsCount != 0);
+
+ TValue significand;
+ int exponent;
+
+ if (number.DigitsCount > TDecimal.Precision)
+ {
+ DecimalIeee754Rounding(ref number, TDecimal.Precision, out significand, out exponent);
+
+ if (exponent > TDecimal.MaxExponent)
+ {
+ return number.IsNegative ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
+ }
+ }
+ else
+ {
+ int positiveExponent = (Math.Max(0, number.Scale));
+ int integerDigitsPresent = Math.Min(positiveExponent, number.DigitsCount);
+ int fractionalDigitsPresent = number.DigitsCount - integerDigitsPresent;
+ exponent = number.Scale - integerDigitsPresent - fractionalDigitsPresent;
+
+ if (exponent < TDecimal.MinExponent)
+ {
+ return SmallExponentRounding(ref number, exponent);
+ }
+
+ significand = TDecimal.NumberToSignificand(ref number, number.DigitsCount);
+ return DecimalIeee754BinaryEncoding(number.IsNegative, significand, exponent);
+ }
+ return DecimalIeee754BinaryEncoding(number.IsNegative, significand, exponent);
+
+ static TValue SmallExponentRounding(ref NumberBuffer number, int exponent)
+ {
+ Debug.Assert(exponent < TDecimal.MinExponent);
+ int numberDigitsRemove = (TDecimal.MinExponent - exponent);
+ if (numberDigitsRemove < number.DigitsCount)
+ {
+ int numberDigitsRemain = number.DigitsCount - numberDigitsRemove;
+ DecimalIeee754Rounding(ref number, numberDigitsRemain, out TValue significand, out exponent);
+ return DecimalIeee754BinaryEncoding(number.IsNegative, significand, exponent);
+ }
+ else
+ {
+ return TDecimal.Zero;
+ }
+ }
+ }
+
+ private static unsafe TValue DecimalIeee754BinaryEncoding(bool signed, TValue significand, int exponent)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ exponent += TDecimal.ExponentBias;
+
+ TValue value = TValue.Zero;
+ TValue exponentVal = TValue.CreateTruncating(exponent);
+ bool msbSignificand = (significand & TDecimal.MostSignificantBitOfSignificandMask) != TValue.Zero;
+
+ if (signed)
+ {
+ value = TDecimal.SignMask;
+ }
+
+ if (msbSignificand)
+ {
+ value |= TDecimal.G0G1Mask;
+ exponentVal <<= TDecimal.NumberBitsEncoding - TDecimal.NumberBitsExponent - 3;
+ value |= exponentVal;
+ significand ^= TDecimal.MostSignificantBitOfSignificandMask;
+ value |= significand;
+ }
+ else
+ {
+ exponentVal <<= TDecimal.NumberBitsEncoding - TDecimal.NumberBitsExponent - 1;
+ value |= exponentVal;
+ value |= significand;
+ }
+
+ return value;
+ }
+
+ private static unsafe void DecimalIeee754Rounding(ref NumberBuffer number, int digits, out TValue significand, out int exponent)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ Debug.Assert(digits < number.DigitsCount);
+
+ significand = TDecimal.NumberToSignificand(ref number, digits);
+
+ int positiveExponent = (Math.Max(0, number.Scale));
+ int integerDigitsPresent = Math.Min(positiveExponent, number.DigitsCount);
+ int fractionalDigitsPresent = number.DigitsCount - integerDigitsPresent;
+ exponent = number.Scale - integerDigitsPresent - fractionalDigitsPresent;
+
+ exponent += number.DigitsCount - digits;
+
+ bool increaseOne = false;
+ int midPointValue = *(number.DigitsPtr + digits);
+
+ if (midPointValue > '5')
+ {
+ increaseOne = true;
+ }
+ else if (midPointValue == '5')
+ {
+ int index = digits + 1;
+ byte* p = number.DigitsPtr + index;
+ int c = *p;
+ bool tiedToEvenRounding = true;
+
+ while (index < number.DigitsCount && c != 0)
+ {
+ if (c != '0')
+ {
+ increaseOne = true;
+ tiedToEvenRounding = false;
+ break;
+ }
+ ++index;
+ c = *++p;
+ }
+
+ if (tiedToEvenRounding && !int.IsEvenInteger(*(number.DigitsPtr + digits - 1) - '0'))
+ {
+ increaseOne = true;
+ }
+ }
+
+ if (increaseOne)
+ {
+ if (significand == TDecimal.MaxSignificand)
+ {
+ significand = TDecimal.Power10(TDecimal.Precision - 1);
+ exponent += 1;
+ }
+ else
+ {
+ significand += TValue.One;
+ }
+ }
+ }
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
index 2062aa526cb386..d954a629b3d62f 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Buffers;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Diagnostics;
@@ -329,6 +330,42 @@ private static ref byte GetTwoDigitsBytesRef(bool useChars) =>
ref MemoryMarshal.GetReference(useChars ? TwoDigitsCharsAsBytes : TwoDigitsBytes);
#endif
+ public static unsafe string FormatDecimalIeee754(TDecimal value, ReadOnlySpan format, NumberFormatInfo info)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ char fmt = ParseFormatSpecifier(format, out int digits);
+ byte[] buffer = ArrayPool.Shared.Rent(TDecimal.BufferLength);
+ try
+ {
+ fixed (byte* pDigits = buffer)
+ {
+ NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, pDigits, TDecimal.BufferLength);
+
+ DecimalIeee754ToNumber(value, ref number);
+
+ char* stackPtr = stackalloc char[CharStackBufferSize];
+ var vlb = new ValueListBuilder(new Span(stackPtr, CharStackBufferSize));
+
+ if (fmt != 0)
+ {
+ NumberToString(ref vlb, ref number, fmt, digits, info);
+ }
+ else
+ {
+ NumberToStringFormat(ref vlb, ref number, format, info);
+ }
+
+ string result = vlb.AsSpan().ToString();
+ vlb.Dispose();
+ return result;
+ }
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(buffer);
+ }
+ }
public static unsafe string FormatDecimal(decimal value, ReadOnlySpan format, NumberFormatInfo info)
{
@@ -384,6 +421,50 @@ public static unsafe bool TryFormatDecimal(decimal value, ReadOnlySpan(TDecimal value, ref NumberBuffer number)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ byte* buffer = number.DigitsPtr;
+ DecimalIeee754 unpackDecimal = value.Unpack();
+ number.IsNegative = unpackDecimal.Signed;
+
+ byte* p = buffer + TDecimal.Precision;
+ p = TDecimal.ToDecChars(p, unpackDecimal.Significand);
+ int numberDigitsSignificand = (int)((buffer + TDecimal.Precision) - p);
+
+ byte* dst = number.DigitsPtr;
+ int i = numberDigitsSignificand;
+ while (--i >= 0)
+ {
+ *dst++ = *p++;
+ }
+
+ number.Scale = TValue.IsZero(unpackDecimal.Significand) ? 0 : numberDigitsSignificand + unpackDecimal.Exponent;
+
+ if (unpackDecimal.Exponent >= 0)
+ {
+ number.DigitsCount = numberDigitsSignificand + unpackDecimal.Exponent;
+
+ if (unpackDecimal.Exponent > 0)
+ {
+ i = unpackDecimal.Exponent;
+ while (--i >= 0)
+ {
+ *dst++ = (byte)'0';
+ }
+ }
+ }
+ else
+ {
+ number.DigitsCount = numberDigitsSignificand;
+ }
+
+ *dst = (byte)'\0';
+
+ number.CheckConsistency();
+ }
+
internal static unsafe void DecimalToNumber(scoped ref decimal d, ref NumberBuffer number)
{
byte* buffer = number.DigitsPtr;
@@ -1576,7 +1657,7 @@ private static unsafe bool TryUInt32ToBinaryStr(uint value, int digits, S
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static unsafe void UInt32ToNumber(uint value, ref NumberBuffer number)
+ internal static unsafe void UInt32ToNumber(uint value, ref NumberBuffer number)
{
number.DigitsCount = UInt32Precision;
number.IsNegative = false;
@@ -2041,7 +2122,7 @@ private static unsafe bool TryUInt64ToBinaryStr(ulong value, int digits,
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static unsafe void UInt64ToNumber(ulong value, ref NumberBuffer number)
+ internal static unsafe void UInt64ToNumber(ulong value, ref NumberBuffer number)
{
number.DigitsCount = UInt64Precision;
number.IsNegative = false;
@@ -2453,7 +2534,7 @@ private static unsafe bool TryUInt128ToBinaryStr(Int128 value, int digits
}
}
- private static unsafe void UInt128ToNumber(UInt128 value, ref NumberBuffer number)
+ internal static unsafe void UInt128ToNumber(UInt128 value, ref NumberBuffer number)
{
number.DigitsCount = UInt128Precision;
number.IsNegative = false;
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs
index 303ae2f43c9222..50bca18dfe3dc0 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs
@@ -696,7 +696,7 @@ internal unsafe partial class Number
0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648
];
- private static void AccumulateDecimalDigitsIntoBigInteger(scoped ref NumberBuffer number, uint firstIndex, uint lastIndex, out BigInteger result)
+ internal static void AccumulateDecimalDigitsIntoBigInteger(scoped ref NumberBuffer number, uint firstIndex, uint lastIndex, out BigInteger result)
{
BigInteger.SetZero(out result);
@@ -890,7 +890,7 @@ private static ulong ConvertBigIntegerToFloatingPointBits(ref BigInteger
}
// get 32-bit integer from at most 9 digits
- private static uint DigitsToUInt32(byte* p, int count)
+ internal static uint DigitsToUInt32(byte* p, int count)
{
Debug.Assert((1 <= count) && (count <= 9));
@@ -914,7 +914,7 @@ private static uint DigitsToUInt32(byte* p, int count)
}
// get 64-bit integer from at most 19 digits
- private static ulong DigitsToUInt64(byte* p, int count)
+ internal static ulong DigitsToUInt64(byte* p, int count)
{
Debug.Assert((1 <= count) && (count <= 19));
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
index bb80ebd3ff67a2..9b70e12ee1abae 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
@@ -99,6 +99,41 @@ internal interface IBinaryFloatParseAndFormatInfo : IBinaryFloatingPointI
static abstract int MaxPrecisionCustomFormat { get; }
}
+ internal interface IDecimalIeee754ParseAndFormatInfo
+ where TSelf : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ static abstract int Precision { get; }
+ static abstract int MaxScale { get; }
+ static abstract int MinScale { get; }
+ static abstract int BufferLength { get; }
+ static abstract int MaxExponent { get; }
+ static abstract int MinExponent { get; }
+ static abstract int ExponentBias { get; }
+ static abstract TValue PositiveInfinity { get; }
+ static abstract TValue NegativeInfinity { get; }
+ static abstract TValue Zero { get; }
+ static abstract TValue MaxSignificand { get; }
+ static abstract TValue NumberToSignificand(ref Number.NumberBuffer number, int digits);
+ static abstract unsafe byte* ToDecChars(byte* p, TValue significand);
+ static abstract int ConvertToExponent(TValue value);
+ static abstract TValue Power10(int exponent);
+ Number.DecimalIeee754 Unpack();
+ static abstract TSelf Construct(TValue value);
+ static abstract void ToNumber(TValue significand, ref Number.NumberBuffer number);
+ static abstract int NumberBitsEncoding { get; }
+ static abstract int NumberBitsExponent { get; }
+ static abstract int NumberBitsSignificand { get; }
+ static abstract TValue SignMask { get; }
+ static abstract TValue G0G1Mask { get; }
+ static abstract TValue G0ToGwPlus1ExponentMask { get; } //G0 to G(w+1)
+ static abstract TValue G2ToGwPlus3ExponentMask { get; } //G2 to G(w+3)
+ static abstract TValue GwPlus2ToGwPlus4SignificandMask { get; } //G(w+2) to G(w+4)
+ static abstract TValue GwPlus4SignificandMask { get; } //G(w+4)
+ static abstract TValue MostSignificantBitOfSignificandMask { get; }
+ static abstract int SignificandBufferLength { get; }
+ }
+
internal static partial class Number
{
private const int Int32Precision = 10;
@@ -733,6 +768,21 @@ internal static decimal ParseDecimal(ReadOnlySpan value, NumberSty
return result;
}
+ internal static TDecimal ParseDecimalIeee754(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info)
+ where TChar : unmanaged, IUtfChar
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ ParsingStatus status = TryParseDecimalIeee754(value, styles, info, out TDecimal result);
+
+ if (status == ParsingStatus.Failed)
+ {
+ ThrowFormatException(value);
+ }
+
+ return result;
+ }
+
internal static unsafe bool TryNumberToDecimal(ref NumberBuffer number, ref decimal value)
{
number.CheckConsistency();
@@ -884,6 +934,24 @@ internal static ParsingStatus TryParseDecimal(ReadOnlySpan value,
return ParsingStatus.OK;
}
+ internal static ParsingStatus TryParseDecimalIeee754(ReadOnlySpan value, NumberStyles styles, NumberFormatInfo info, out TDecimal result)
+ where TChar : unmanaged, IUtfChar
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, stackalloc byte[TDecimal.BufferLength]);
+ result = default;
+
+ if (!TryStringToNumber(value, styles, ref number, info))
+ {
+ return ParsingStatus.Failed;
+ }
+
+ result = NumberToDecimalIeee754(ref number);
+
+ return ParsingStatus.OK;
+ }
+
internal static bool SpanStartsWith(ReadOnlySpan span, TChar c)
where TChar : unmanaged, IUtfChar
{
@@ -1101,5 +1169,27 @@ internal static TFloat NumberToFloat(ref NumberBuffer number)
return number.IsNegative ? -result : result;
}
+
+ internal static TDecimal NumberToDecimalIeee754(ref NumberBuffer number)
+ where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo
+ where TValue : unmanaged, IBinaryInteger
+ {
+ number.CheckConsistency();
+ TValue value;
+
+ if ((number.DigitsCount == 0) || (number.Scale < TDecimal.MinScale))
+ {
+ value = TDecimal.Zero;
+ }
+ else if (number.Scale > TDecimal.MaxScale)
+ {
+ value = number.IsNegative ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
+ }
+ else
+ {
+ value = NumberToDecimalIeee754Bits(ref number);
+ }
+ return TDecimal.Construct(value);
+ }
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal128.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal128.cs
new file mode 100644
index 00000000000000..0017bdbf07c5fd
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal128.cs
@@ -0,0 +1,358 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Buffers.Text;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Text;
+
+namespace System.Numerics
+{
+ public readonly struct Decimal128
+ : IComparable,
+ IComparable,
+ IEquatable,
+ ISpanParsable,
+ IDecimalIeee754ParseAndFormatInfo
+ {
+#if BIGENDIAN
+ internal readonly ulong _upper;
+ internal readonly ulong _lower;
+#else
+ internal readonly ulong _lower;
+ internal readonly ulong _upper;
+#endif
+
+ private const int MaxExponent = 6111;
+ private const int MinExponent = -6176;
+ private const int Precision = 34;
+ private const int ExponentBias = 6176;
+ private const int NumberBitsExponent = 14;
+ private static readonly UInt128 PositiveInfinityValue = new UInt128(upper: 0x7800_0000_0000_0000, lower: 0);
+ private static readonly UInt128 NegativeInfinityValue = new UInt128(upper: 0xf800_0000_0000_0000, lower: 0);
+ private static readonly UInt128 ZeroValue = new UInt128(0, 0);
+
+ internal Decimal128(UInt128 value)
+ {
+ _upper = value.Upper;
+ _lower = value.Lower;
+ }
+
+ public Decimal128(Int128 significand, int exponent)
+ {
+ UInt128 value = Number.ConstructorToDecimalIeee754Bits(significand < 0, (UInt128)(significand < 0 ? -significand : significand), exponent);
+ _upper = value.Upper;
+ _lower = value.Lower;
+ }
+
+ ///
+ /// Parses a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string. If the input exceeds Decimal128's range, a or is returned.
+ public static Decimal128 Parse(string s) => Parse(s, NumberStyles.Number, provider: null);
+
+ ///
+ /// Parses a from a in the given .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// The equivalent value representing the input string. If the input exceeds Decimal128's range, a or is returned.
+ public static Decimal128 Parse(string s, NumberStyles style) => Parse(s, style, provider: null);
+
+ ///
+ public static Decimal128 Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Number, provider);
+
+ ///
+ /// Parses a from a and .
+ ///
+ /// The input to be parsed.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal128's range, a or is returned.
+ public static Decimal128 Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Number, provider);
+
+ ///
+ /// Parses a from a and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal128's range, a or is returned.
+ public static Decimal128 Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Number, IFormatProvider? provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.ParseDecimalIeee754(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ ///
+ /// Parses a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal128's range, a or is returned.
+ public static Decimal128 Parse(string s, NumberStyles style, IFormatProvider? provider)
+ {
+ if (s is null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ }
+ return Parse(s.AsSpan(), style, provider);
+ }
+
+ ///
+ /// Tries to parse a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal128's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, out Decimal128 result) => TryParse(s, NumberStyles.Number, provider: null, out result);
+
+ ///
+ /// Tries to parse a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal128's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse(ReadOnlySpan s, out Decimal128 result) => TryParse(s, NumberStyles.Number, provider: null, out result);
+
+ ///
+ public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal128 result) => TryParse(s, NumberStyles.Number, provider, out result);
+
+ ///
+ /// Tries to parse a from a with the given .
+ ///
+ /// The input to be parsed.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal128's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal128 result) => TryParse(s, NumberStyles.Number, provider, out result);
+
+ ///
+ /// Tries to parse a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal128's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal128 result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.TryParseDecimalIeee754(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
+ }
+
+ ///
+ /// Tries to parse a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal128's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal128 result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+
+ if (s == null)
+ {
+ result = default;
+ return false;
+ }
+ return Number.TryParseDecimalIeee754(s.AsSpan(), style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
+ }
+
+ ///
+ public int CompareTo(object? value)
+ {
+ if (value is not Decimal128 other)
+ {
+ return (value is null) ? 1 : throw new ArgumentException(SR.Arg_MustBeDecimal128);
+ }
+ return CompareTo(other);
+ }
+
+ ///
+ public int CompareTo(Decimal128 other)
+ {
+ var current = new UInt128(_upper, _lower);
+ var another = new UInt128(other._upper, other._lower);
+ return Number.CompareDecimalIeee754(current, another);
+ }
+
+ ///
+ public bool Equals(Decimal128 other)
+ {
+ var current = new UInt128(_upper, _lower);
+ var another = new UInt128(other._upper, other._lower);
+ return Number.CompareDecimalIeee754(current, another) == 0;
+ }
+
+ ///
+ /// Returns a value that indicates whether this instance is equal to a specified .
+ ///
+ public override bool Equals([NotNullWhen(true)] object? obj)
+ {
+ return obj is Decimal128 && Equals((Decimal128)obj);
+ }
+
+ ///
+ /// Serves as the default hash function.
+ ///
+ public override int GetHashCode()
+ {
+ return new UInt128(_upper, _lower).GetHashCode();
+ }
+
+ ///
+ /// Returns a string representation of the current value.
+ ///
+ public override string ToString()
+ {
+ return Number.FormatDecimalIeee754(this, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ ///
+ /// Returns a string representation of the current value using the specified .
+ ///
+ public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format)
+ {
+ return Number.FormatDecimalIeee754(this, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ ///
+ /// Returns a string representation of the current value with the specified .
+ ///
+ public string ToString(IFormatProvider? provider)
+ {
+ return Number.FormatDecimalIeee754(this, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ ///
+ /// Returns a string representation of the current value using the specified and .
+ ///
+ public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? provider)
+ {
+ return Number.FormatDecimalIeee754(this, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static UInt128[] UInt128Powers10 =>
+ [
+ new UInt128(0, 1),
+ new UInt128(0, 10),
+ new UInt128(0, 100),
+ new UInt128(0, 1000),
+ new UInt128(0, 10000),
+ new UInt128(0, 100000),
+ new UInt128(0, 1000000),
+ new UInt128(0, 10000000),
+ new UInt128(0, 100000000),
+ new UInt128(0, 1000000000),
+ new UInt128(0, 10000000000),
+ new UInt128(0, 100000000000),
+ new UInt128(0, 1000000000000),
+ new UInt128(0, 10000000000000),
+ new UInt128(0, 100000000000000),
+ new UInt128(0, 1000000000000000),
+ new UInt128(0, 10000000000000000),
+ new UInt128(0, 100000000000000000),
+ new UInt128(0, 1000000000000000000),
+ new UInt128(0, 10000000000000000000),
+ new UInt128(5, 7766279631452241920),
+ new UInt128(54, 3875820019684212736),
+ new UInt128(542, 1864712049423024128),
+ new UInt128(5421, 200376420520689664),
+ new UInt128(54210, 2003764205206896640),
+ new UInt128(542101, 1590897978359414784),
+ new UInt128(5421010, 15908979783594147840),
+ new UInt128(54210108, 11515845246265065472),
+ new UInt128(542101086, 4477988020393345024),
+ new UInt128(5421010862, 7886392056514347008),
+ new UInt128(54210108624, 5076944270305263616),
+ new UInt128(542101086242, 13875954555633532928),
+ new UInt128(5421010862427, 9632337040368467968),
+ new UInt128(54210108624275, 4089650035136921600),
+ new UInt128(542101086242752, 4003012203950112768),
+ ];
+
+ static int IDecimalIeee754ParseAndFormatInfo.MaxScale => 6145;
+
+ static int IDecimalIeee754ParseAndFormatInfo.MinScale => -6175;
+
+ static unsafe byte* IDecimalIeee754ParseAndFormatInfo.ToDecChars(byte* p, UInt128 significand)
+ {
+ return Number.UInt128ToDecChars(p, significand, 0);
+ }
+
+ Number.DecimalIeee754 IDecimalIeee754ParseAndFormatInfo.Unpack()
+ {
+ return Number.UnpackDecimalIeee754(new UInt128(_upper, _lower));
+ }
+
+ static unsafe UInt128 IDecimalIeee754ParseAndFormatInfo.NumberToSignificand(ref Number.NumberBuffer number, int digits)
+ {
+ if (digits <= 19)
+ {
+ return Number.DigitsToUInt64(number.DigitsPtr, digits);
+ }
+ else
+ {
+ Number.AccumulateDecimalDigitsIntoBigInteger(ref number, 0, (uint)digits, out Number.BigInteger result);
+ return result.ToUInt128();
+ }
+ }
+
+ static Decimal128 IDecimalIeee754ParseAndFormatInfo.Construct(UInt128 value) => new Decimal128(value);
+
+ static int IDecimalIeee754ParseAndFormatInfo.ConvertToExponent(UInt128 value) => (int)value;
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.Power10(int exponent) => UInt128Powers10[exponent];
+
+ static int IDecimalIeee754ParseAndFormatInfo.Precision => Precision;
+
+ static int IDecimalIeee754ParseAndFormatInfo.BufferLength => Number.Decimal128NumberBufferLength;
+
+ static int IDecimalIeee754ParseAndFormatInfo.MaxExponent => MaxExponent;
+
+ static int IDecimalIeee754ParseAndFormatInfo.MinExponent => MinExponent;
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.PositiveInfinity => PositiveInfinityValue;
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.NegativeInfinity => NegativeInfinityValue;
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.Zero => ZeroValue;
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.MostSignificantBitOfSignificandMask => new UInt128(0x0002_0000_0000_0000, 0);
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsEncoding => 128;
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsExponent => NumberBitsExponent;
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.SignMask => new UInt128(0x8000_0000_0000_0000, 0);
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.G0G1Mask => new UInt128(0x6000_0000_0000_0000, 0);
+
+ static int IDecimalIeee754ParseAndFormatInfo.ExponentBias => ExponentBias;
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsSignificand => 110;
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.G0ToGwPlus1ExponentMask => new UInt128(0x7FFE_0000_0000_0000, 0);
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.G2ToGwPlus3ExponentMask => new UInt128(0x1FFF_8000_0000_0000, 0);
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.GwPlus2ToGwPlus4SignificandMask => new UInt128(0x0001_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF);
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.GwPlus4SignificandMask => new UInt128(0x0000_7FFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF);
+
+ static UInt128 IDecimalIeee754ParseAndFormatInfo.MaxSignificand => new UInt128(upper: 0x0001_ED09_BEAD_87C0, lower: 0x378D_8E63_FFFF_FFFF); // 9_999_999_999_999_999_999_999_999_999_999_999;
+
+ static unsafe void IDecimalIeee754ParseAndFormatInfo.ToNumber(UInt128 significand, ref Number.NumberBuffer number)
+ {
+ Number.UInt128ToNumber(significand, ref number);
+ }
+
+ static int IDecimalIeee754ParseAndFormatInfo.SignificandBufferLength => Number.UInt128NumberBufferLength;
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal32.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal32.cs
new file mode 100644
index 00000000000000..154452827c086f
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal32.cs
@@ -0,0 +1,315 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Buffers.Text;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+namespace System.Numerics
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public readonly struct Decimal32
+ : IComparable,
+ IComparable,
+ IEquatable,
+ ISpanParsable,
+ IDecimalIeee754ParseAndFormatInfo
+ {
+ internal readonly uint _value;
+
+ internal Decimal32(uint value)
+ {
+ _value = value;
+ }
+
+ private const int MaxExponent = 90;
+ private const int MinExponent = -101;
+ private const int Precision = 7;
+ private const int ExponentBias = 101;
+ private const int NumberBitsExponent = 8;
+ private const uint PositiveInfinityValue = 0x7800_0000;
+ private const uint NegativeInfinityValue = 0xF800_0000;
+ private const uint ZeroValue = 0x00000000;
+ private const uint G0G1Mask = 0x6000_0000;
+ private const uint SignMask = 0x8000_0000;
+ private const uint MostSignificantBitOfSignificandMask = 0x0080_0000;
+ private const uint MaxSignificand = 9_999_999;
+
+ private static ReadOnlySpan UInt32Powers10 =>
+ [
+ 1,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ ];
+
+ public Decimal32(int significand, int exponent)
+ {
+ _value = Number.ConstructorToDecimalIeee754Bits(significand < 0, (uint)Math.Abs(significand), exponent);
+ }
+
+ ///
+ /// Parses a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string. If the input exceeds Decimal32's range, a or is returned.
+ public static Decimal32 Parse(string s) => Parse(s, NumberStyles.Number, provider: null);
+
+ ///
+ /// Parses a from a in the given .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// The equivalent value representing the input string. If the input exceeds Decimal32's range, a or is returned.
+ public static Decimal32 Parse(string s, NumberStyles style) => Parse(s, style, provider: null);
+
+ ///
+ public static Decimal32 Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Number, provider);
+
+ ///
+ /// Parses a from a and .
+ ///
+ /// The input to be parsed.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal32's range, a or is returned.
+ public static Decimal32 Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Number, provider);
+
+ ///
+ /// Parses a from a and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal32's range, a or is returned.
+ public static Decimal32 Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Number, IFormatProvider? provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.ParseDecimalIeee754(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ ///
+ /// Parses a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal32's range, a or is returned.
+ public static Decimal32 Parse(string s, NumberStyles style, IFormatProvider? provider)
+ {
+ if (s is null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ }
+ return Parse(s.AsSpan(), style, provider);
+ }
+
+ ///
+ /// Tries to parse a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal32's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, out Decimal32 result) => TryParse(s, NumberStyles.Number, provider: null, out result);
+
+ ///
+ /// Tries to parse a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal32's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse(ReadOnlySpan s, out Decimal32 result) => TryParse(s, NumberStyles.Number, provider: null, out result);
+
+ ///
+ public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal32 result) => TryParse(s, NumberStyles.Number, provider, out result);
+
+ ///
+ /// Tries to parse a from a with the given .
+ ///
+ /// The input to be parsed.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal32's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal32 result) => TryParse(s, NumberStyles.Number, provider, out result);
+
+ ///
+ /// Tries to parse a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal32's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal32 result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.TryParseDecimalIeee754(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
+ }
+
+ ///
+ /// Tries to parse a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal32's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal32 result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+
+ if (s == null)
+ {
+ result = default;
+ return false;
+ }
+ return Number.TryParseDecimalIeee754(s.AsSpan(), style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
+ }
+
+ ///
+ public int CompareTo(object? value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+
+ if (value is not Decimal32 i)
+ {
+ throw new ArgumentException(SR.Arg_MustBeDecimal32);
+ }
+
+ return Number.CompareDecimalIeee754(_value, i._value);
+ }
+
+ ///
+ public int CompareTo(Decimal32 other)
+ {
+ return Number.CompareDecimalIeee754(_value, other._value);
+ }
+
+ ///
+ public bool Equals(Decimal32 other)
+ {
+ return Number.CompareDecimalIeee754(_value, other._value) == 0;
+ }
+
+ ///
+ /// Returns a value that indicates whether this instance is equal to a specified .
+ ///
+ public override bool Equals([NotNullWhen(true)] object? obj)
+ {
+ return obj is Decimal32 && Equals((Decimal32)obj);
+ }
+
+ ///
+ /// Serves as the default hash function.
+ ///
+ public override int GetHashCode()
+ {
+ return _value.GetHashCode();
+ }
+
+ ///
+ /// Returns a string representation of the current value.
+ ///
+ public override string ToString()
+ {
+ return Number.FormatDecimalIeee754(this, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ ///
+ /// Returns a string representation of the current value using the specified .
+ ///
+ public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format)
+ {
+ return Number.FormatDecimalIeee754(this, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ ///
+ /// Returns a string representation of the current value with the specified .
+ ///
+ public string ToString(IFormatProvider? provider)
+ {
+ return Number.FormatDecimalIeee754(this, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ ///
+ /// Returns a string representation of the current value using the specified and .
+ ///
+ public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? provider)
+ {
+ return Number.FormatDecimalIeee754(this, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ static int IDecimalIeee754ParseAndFormatInfo.Precision => Precision;
+
+ static int IDecimalIeee754ParseAndFormatInfo.BufferLength => Number.Decimal32NumberBufferLength;
+
+ static unsafe byte* IDecimalIeee754ParseAndFormatInfo.ToDecChars(byte* p, uint significand)
+ {
+ return Number.UInt32ToDecChars(p, significand, 0);
+ }
+
+ Number.DecimalIeee754 IDecimalIeee754ParseAndFormatInfo.Unpack()
+ {
+ return Number.UnpackDecimalIeee754(_value);
+ }
+
+ static unsafe uint IDecimalIeee754ParseAndFormatInfo.NumberToSignificand(ref Number.NumberBuffer number, int digits)
+ {
+ return Number.DigitsToUInt32(number.DigitsPtr, digits);
+ }
+
+ static Decimal32 IDecimalIeee754ParseAndFormatInfo.Construct(uint value) => new Decimal32(value);
+ static int IDecimalIeee754ParseAndFormatInfo.ConvertToExponent(uint value) => (int)value;
+ static uint IDecimalIeee754ParseAndFormatInfo.Power10(int exponent) => UInt32Powers10[exponent];
+
+ static int IDecimalIeee754ParseAndFormatInfo.MaxScale => 97;
+ static int IDecimalIeee754ParseAndFormatInfo.MinScale => -100;
+
+ static int IDecimalIeee754ParseAndFormatInfo.MaxExponent => MaxExponent;
+
+ static int IDecimalIeee754ParseAndFormatInfo.MinExponent => MinExponent;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.PositiveInfinity => PositiveInfinityValue;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.NegativeInfinity => NegativeInfinityValue;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.Zero => ZeroValue;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.MostSignificantBitOfSignificandMask => MostSignificantBitOfSignificandMask;
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsEncoding => 32;
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsExponent => NumberBitsExponent;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.SignMask => SignMask;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.G0G1Mask => G0G1Mask;
+
+ static int IDecimalIeee754ParseAndFormatInfo.ExponentBias => ExponentBias;
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsSignificand => 20;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.G0ToGwPlus1ExponentMask => 0x7F80_0000;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.G2ToGwPlus3ExponentMask => 0x1FE0_0000;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.GwPlus2ToGwPlus4SignificandMask => 0x007F_FFFF;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.GwPlus4SignificandMask => 0x001F_FFFF;
+
+ static uint IDecimalIeee754ParseAndFormatInfo.MaxSignificand => MaxSignificand;
+
+ static unsafe void IDecimalIeee754ParseAndFormatInfo.ToNumber(uint significand, ref Number.NumberBuffer number)
+ {
+ Number.UInt32ToNumber(significand, ref number);
+ }
+
+ static int IDecimalIeee754ParseAndFormatInfo.SignificandBufferLength => Number.UInt32NumberBufferLength;
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal64.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal64.cs
new file mode 100644
index 00000000000000..bb3c91f1a5d3a1
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Decimal64.cs
@@ -0,0 +1,319 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Buffers.Text;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+
+namespace System.Numerics
+{
+ public readonly struct Decimal64
+ : IComparable,
+ IComparable,
+ IEquatable,
+ ISpanParsable,
+ IDecimalIeee754ParseAndFormatInfo
+ {
+ internal readonly ulong _value;
+
+ private const int MaxExponent = 369;
+ private const int MinExponent = -398;
+ private const int Precision = 16;
+ private const int ExponentBias = 398;
+ private const int NumberBitsExponent = 10;
+ private const ulong PositiveInfinityValue = 0x7800_0000_0000_0000;
+ private const ulong NegativeInfinityValue = 0xF800_0000_0000_0000;
+ private const ulong ZeroValue = 0x0000_0000_0000_0000;
+ private const ulong G0G1Mask = 0x6000_0000_0000_0000;
+ private const ulong SignMask = 0x8000_0000_0000_0000;
+ private const ulong MostSignificantBitOfSignificandMask = 0x0020_0000_0000_0000;
+ private const ulong MaxSignificand = 9_999_999_999_999_999;
+
+ private static ReadOnlySpan UInt64Powers10 =>
+ [
+ 1,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ 10000000,
+ 100000000,
+ 1000000000,
+ 10000000000,
+ 100000000000,
+ 1000000000000,
+ 10000000000000,
+ 100000000000000,
+ 1000000000000000,
+ ];
+
+ public Decimal64(long significand, int exponent)
+ {
+ _value = Number.ConstructorToDecimalIeee754Bits(significand < 0, (ulong)Math.Abs(significand), exponent);
+ }
+
+ internal Decimal64(ulong value)
+ {
+ _value = value;
+ }
+
+ ///
+ /// Parses a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string. If the input exceeds Decimal64's range, a or is returned.
+ public static Decimal64 Parse(string s) => Parse(s, NumberStyles.Number, provider: null);
+
+ ///
+ /// Parses a from a in the given .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// The equivalent value representing the input string. If the input exceeds Decimal64's range, a or is returned.
+ public static Decimal64 Parse(string s, NumberStyles style) => Parse(s, style, provider: null);
+
+ ///
+ public static Decimal64 Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Number, provider);
+
+ ///
+ /// Parses a from a and .
+ ///
+ /// The input to be parsed.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal64's range, a or is returned.
+ public static Decimal64 Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Number, provider);
+
+ ///
+ /// Parses a from a and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal64's range, a or is returned.
+ public static Decimal64 Parse(ReadOnlySpan s, NumberStyles style = NumberStyles.Number, IFormatProvider? provider = null)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.ParseDecimalIeee754(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ ///
+ /// Parses a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string. If the input exceeds Decimal64's range, a or is returned.
+ public static Decimal64 Parse(string s, NumberStyles style, IFormatProvider? provider)
+ {
+ if (s is null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
+ }
+ return Parse(s.AsSpan(), style, provider);
+ }
+
+ ///
+ /// Tries to parse a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal64's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, out Decimal64 result) => TryParse(s, NumberStyles.Number, provider: null, out result);
+
+ ///
+ /// Tries to parse a from a in the default parse style.
+ ///
+ /// The input to be parsed.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal64's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse(ReadOnlySpan s, out Decimal64 result) => TryParse(s, NumberStyles.Number, provider: null, out result);
+
+ ///
+ public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal64 result) => TryParse(s, NumberStyles.Number, provider, out result);
+
+ ///
+ /// Tries to parse a from a with the given .
+ ///
+ /// The input to be parsed.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal64's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal64 result) => TryParse(s, NumberStyles.Number, provider, out result);
+
+ ///
+ /// Tries to parse a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal64's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal64 result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.TryParseDecimalIeee754(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
+ }
+
+ ///
+ /// Tries to parse a from a with the given and .
+ ///
+ /// The input to be parsed.
+ /// The used to parse the input.
+ /// A format provider.
+ /// The equivalent value representing the input string if the parse was successful. If the input exceeds Decimal64's range, a or is returned. If the parse was unsuccessful, a default value is returned.
+ /// if the parse was successful, otherwise.
+ public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, [MaybeNullWhen(false)] out Decimal64 result)
+ {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+
+ if (s == null)
+ {
+ result = default;
+ return false;
+ }
+ return Number.TryParseDecimalIeee754(s.AsSpan(), style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
+ }
+
+ ///
+ public int CompareTo(object? value)
+ {
+ if (value is not Decimal64 other)
+ {
+ return (value is null) ? 1 : throw new ArgumentException(SR.Arg_MustBeDecimal64);
+ }
+ return CompareTo(other);
+ }
+
+ ///
+ public int CompareTo(Decimal64 other)
+ {
+ return Number.CompareDecimalIeee754(_value, other._value);
+ }
+
+ ///
+ public bool Equals(Decimal64 other)
+ {
+ return Number.CompareDecimalIeee754(_value, other._value) == 0;
+ }
+
+ ///
+ /// Returns a value that indicates whether this instance is equal to a specified .
+ ///
+ public override bool Equals([NotNullWhen(true)] object? obj)
+ {
+ return obj is Decimal64 && Equals((Decimal64)obj);
+ }
+
+ ///
+ /// Serves as the default hash function.
+ ///
+ public override int GetHashCode()
+ {
+ return _value.GetHashCode();
+ }
+
+ ///
+ /// Returns a string representation of the current value.
+ ///
+ public override string ToString()
+ {
+ return Number.FormatDecimalIeee754(this, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ ///
+ /// Returns a string representation of the current value using the specified .
+ ///
+ public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format)
+ {
+ return Number.FormatDecimalIeee754(this, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ ///
+ /// Returns a string representation of the current value with the specified .
+ ///
+ public string ToString(IFormatProvider? provider)
+ {
+ return Number.FormatDecimalIeee754(this, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ ///
+ /// Returns a string representation of the current value using the specified and .
+ ///
+ public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? provider)
+ {
+ return Number.FormatDecimalIeee754(this, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ static int IDecimalIeee754ParseAndFormatInfo.Precision => Precision;
+
+ static int IDecimalIeee754ParseAndFormatInfo.BufferLength => Number.Decimal64NumberBufferLength;
+
+ static unsafe byte* IDecimalIeee754ParseAndFormatInfo.ToDecChars(byte* p, ulong significand)
+ {
+ return Number.UInt64ToDecChars(p, significand, 0);
+ }
+
+ Number.DecimalIeee754 IDecimalIeee754ParseAndFormatInfo.Unpack()
+ {
+ return Number.UnpackDecimalIeee754(_value);
+ }
+
+ static unsafe ulong IDecimalIeee754ParseAndFormatInfo.NumberToSignificand(ref Number.NumberBuffer number, int digits)
+ {
+ return Number.DigitsToUInt64(number.DigitsPtr, digits);
+ }
+
+ static Decimal64 IDecimalIeee754ParseAndFormatInfo.Construct(ulong value) => new Decimal64(value);
+
+ static int IDecimalIeee754ParseAndFormatInfo.ConvertToExponent(ulong value) => (int)value;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.Power10(int exponent) => UInt64Powers10[exponent];
+
+ static int IDecimalIeee754ParseAndFormatInfo.MaxScale => 385;
+
+ static int IDecimalIeee754ParseAndFormatInfo.MinScale => -397;
+
+ static int IDecimalIeee754ParseAndFormatInfo.MaxExponent => MaxExponent;
+
+ static int IDecimalIeee754ParseAndFormatInfo.MinExponent => MinExponent;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.PositiveInfinity => PositiveInfinityValue;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.NegativeInfinity => NegativeInfinityValue;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.Zero => ZeroValue;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.MostSignificantBitOfSignificandMask => MostSignificantBitOfSignificandMask;
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsEncoding => 64;
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsExponent => NumberBitsExponent;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.SignMask => SignMask;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.G0G1Mask => G0G1Mask;
+
+ static int IDecimalIeee754ParseAndFormatInfo.ExponentBias => ExponentBias;
+
+ static int IDecimalIeee754ParseAndFormatInfo.NumberBitsSignificand => 50;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.G0ToGwPlus1ExponentMask => 0x7FE0_0000_0000_0000;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.G2ToGwPlus3ExponentMask => 0x1FF8_0000_0000_0000;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.GwPlus2ToGwPlus4SignificandMask => 0x001F_FFFF_FFFF_FFFF;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.GwPlus4SignificandMask => 0x0007_FFFF_FFFF_FFFF;
+
+ static ulong IDecimalIeee754ParseAndFormatInfo.MaxSignificand => MaxSignificand;
+
+ static unsafe void IDecimalIeee754ParseAndFormatInfo.ToNumber(ulong significand, ref Number.NumberBuffer number)
+ {
+ Number.UInt64ToNumber(significand, ref number);
+ }
+
+ static int IDecimalIeee754ParseAndFormatInfo.SignificandBufferLength => Number.UInt64NumberBufferLength;
+ }
+}
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index e1d6c46cbfe499..be06b4141aaaf3 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -11176,6 +11176,103 @@ public static void HtmlEncode(string? value, System.IO.TextWriter output) { }
}
namespace System.Numerics
{
+ public readonly struct Decimal32
+ : System.IComparable,
+ System.IComparable,
+ System.IEquatable,
+ System.ISpanParsable
+ {
+ public Decimal32(int significand, int exponent) { throw null; }
+
+ public int CompareTo(object? value) { throw null; }
+ public int CompareTo(Decimal32 other) { throw null; }
+ public bool Equals(Decimal32 other) { throw null; }
+
+ public static Decimal32 Parse(string s) { throw null; }
+ public static Decimal32 Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static Decimal32 Parse(ReadOnlySpan s, IFormatProvider? provider) { throw null; }
+ public static Decimal32 Parse(string s, IFormatProvider? provider) { throw null; }
+ public static Decimal32 Parse(ReadOnlySpan s, System.Globalization.NumberStyles style = System.Globalization.NumberStyles.Number, IFormatProvider? provider = null) { throw null; }
+ public static Decimal32 Parse(string s, System.Globalization.NumberStyles style, IFormatProvider? provider) { throw null; }
+
+ public override string ToString() { throw null; }
+ public string ToString(System.IFormatProvider? provider) { throw null; }
+ public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] string? format) { throw null; }
+ public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] string? format, System.IFormatProvider? provider) { throw null; }
+
+ public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, out Decimal32 result) { throw null; }
+ public static bool TryParse(ReadOnlySpan s, out Decimal32 result) { throw null; }
+ public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out Decimal32 result) { throw null; }
+ public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out Decimal32 result) { throw null; }
+ public static bool TryParse(ReadOnlySpan s, System.Globalization.NumberStyles style, IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out Decimal32 result) { throw null; }
+ public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, System.Globalization.NumberStyles style, IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out Decimal32 result) { throw null; }
+ }
+
+ public readonly struct Decimal64
+ : System.IComparable,
+ System.IComparable,
+ System.IEquatable,
+ System.ISpanParsable
+ {
+ public Decimal64(long significand, int exponent) { throw null; }
+
+ public int CompareTo(object? value) { throw null; }
+ public int CompareTo(Decimal64 other) { throw null; }
+ public bool Equals(Decimal64 other) { throw null; }
+
+ public static Decimal64 Parse(string s) { throw null; }
+ public static Decimal64 Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static Decimal64 Parse(ReadOnlySpan s, IFormatProvider? provider) { throw null; }
+ public static Decimal64 Parse(string s, IFormatProvider? provider) { throw null; }
+ public static Decimal64 Parse(ReadOnlySpan s, System.Globalization.NumberStyles style = System.Globalization.NumberStyles.Number, IFormatProvider? provider = null) { throw null; }
+ public static Decimal64 Parse(string s, System.Globalization.NumberStyles style, IFormatProvider? provider) { throw null; }
+
+ public override string ToString() { throw null; }
+ public string ToString(System.IFormatProvider? provider) { throw null; }
+ public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] string? format) { throw null; }
+ public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute(System.Diagnostics.CodeAnalysis.StringSyntaxAttribute.NumericFormat)] string? format, System.IFormatProvider? provider) { throw null; }
+
+ public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, out Decimal64 result) { throw null; }
+ public static bool TryParse(ReadOnlySpan s, out Decimal64 result) { throw null; }
+ public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out Decimal64 result) { throw null; }
+ public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out Decimal64 result) { throw null; }
+ public static bool TryParse(ReadOnlySpan s, System.Globalization.NumberStyles style, IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out Decimal64 result) { throw null; }
+ public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] string? s, System.Globalization.NumberStyles style, IFormatProvider? provider, [System.Diagnostics.CodeAnalysis.MaybeNullWhen(false)] out Decimal64 result) { throw null; }
+
+ }
+
+ public readonly struct Decimal128
+ : System.IComparable,
+ System.IComparable