File: src\runtime\src\libraries\System.Private.CoreLib\src\System\Number.DecimalIeee754.cs
Web Access
Project: src\runtime\src\coreclr\nativeaot\System.Private.CoreLib\src\System.Private.CoreLib.csproj (System.Private.CoreLib)
// 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;
using System.Numerics;
using System.Runtime.CompilerServices;

namespace System
{
    internal static partial class Number
    {
        internal static int GetDecimalIeee754HashCode<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsNaN(decimalBits) || TDecimal.IsInfinity(decimalBits))
            {
                return (decimalBits & TDecimal.NaNMask).GetHashCode();
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(decimalBits);
            if (decoded.Significand == TValue.Zero)
            {
                return TDecimal.Zero.GetHashCode();
            }

            int digits = TDecimal.CountDigits(decoded.Significand);
            if (digits < TDecimal.Precision)
            {
                int numberZeroDigits = TDecimal.Precision - digits;
                TValue significand = decoded.Significand * TDecimal.Power10(numberZeroDigits);
                int exponent = decoded.UnbiasedExponent - numberZeroDigits;
                return HashCode.Combine(decoded.Signed, significand, exponent);
            }
            return HashCode.Combine(decoded.Signed, decoded.Significand, decoded.UnbiasedExponent);
        }

        internal struct DecodedDecimalIeee754<TSignificand>
            where TSignificand : IBinaryInteger<TSignificand>
        {
            public bool Signed { get; }
            public int UnbiasedExponent { get; }

            /// <summary>
            /// The decoded significand (coefficient) in integer form:
            /// - Fully decoded from the BID encoding (no combination-field or DPD/BID packing).
            /// - Represents the normalized coefficient; includes the implicit leading digit if applicable.
            /// - Not scaled by the (unbiased) exponent.
            /// </summary>
            public TSignificand Significand { get; }

            public DecodedDecimalIeee754(bool signed, int unbiasedExponent, TSignificand significand)
            {
                Signed = signed;
                UnbiasedExponent = unbiasedExponent;
                Significand = significand;
            }
        }

        internal static DecodedDecimalIeee754<TValue> UnpackDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            bool signed = (decimalBits & TDecimal.SignMask) != TValue.Zero;
            TValue significand;
            int biasedExponent;

            if ((decimalBits & TDecimal.G0G1Mask) == TDecimal.G0G1Mask)
            {
                biasedExponent = TDecimal.ConvertToExponent((decimalBits & TDecimal.G2ToGwPlus3ExponentMask) >> (TDecimal.NumberBitsSignificand + 1));
                significand = (decimalBits & TDecimal.GwPlus4SignificandMask) | TDecimal.MostSignificantBitOfSignificandMask;
            }
            else
            {
                biasedExponent = TDecimal.ConvertToExponent((decimalBits & TDecimal.G0ToGwPlus1ExponentMask) >> (TDecimal.NumberBitsSignificand + 3));
                significand = decimalBits & TDecimal.GwPlus2ToGwPlus4SignificandMask;
            }

            // A finite encoding whose significand exceeds the maximum representable coefficient is
            // non-canonical and is treated as zero. This matches the non-canonical handling in
            // `unpack_BID32`, `unpack_BID64`, and `unpack_BID128` from the Intel Decimal
            // Floating-Point Math Library and keeps all downstream arithmetic and comparison
            // logic robust for every finite bit pattern.
            if (significand > TDecimal.MaxSignificand)
            {
                significand = TValue.Zero;
            }

            return new DecodedDecimalIeee754<TValue>(signed, biasedExponent - TDecimal.ExponentBias, significand);
        }

        /// <summary>
        /// Compares two IEEE 754 decimal values represented by their raw bit patterns.
        /// </summary>
        /// <remarks>
        /// The implementation first handles special cases so the result stays consistent
        /// with the .NET equality and ordering contract required by <c>Equals</c>,
        /// <c>GetHashCode</c>, and <c>CompareTo</c>:
        /// - identical bit patterns compare equal;
        /// - NaN compares equal to NaN;
        /// - infinities are handled explicitly;
        /// - positive and negative zero compare equal.
        /// After special-case handling, finite non-zero values are unpacked and compared
        /// by sign first, then by unsigned magnitude.
        /// Treating NaN as equal to NaN here is intentional so values that are considered
        /// equal for comparison also behave consistently in hashing, collections, and
        /// sorting scenarios.
        /// </remarks>
        internal static int CompareDecimalIeee754<TDecimal, TValue>(TValue currentDecimalBits, TValue otherDecimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (currentDecimalBits == otherDecimalBits)
            {
                return 0;
            }

            bool isCurrentNaN = TDecimal.IsNaN(currentDecimalBits);
            bool isOtherNaN = TDecimal.IsNaN(otherDecimalBits);

            if (isCurrentNaN || isOtherNaN)
            {
                if (isCurrentNaN && isOtherNaN)
                {
                    return 0;
                }
                else
                {
                    return isCurrentNaN ? -1 : 1;
                }
            }

            if (TDecimal.IsInfinity(currentDecimalBits) || TDecimal.IsInfinity(otherDecimalBits))
            {
                return InternalInfinityCompare(currentDecimalBits, otherDecimalBits);
            }

            DecodedDecimalIeee754<TValue> current = UnpackDecimalIeee754<TDecimal, TValue>(currentDecimalBits);
            DecodedDecimalIeee754<TValue> other = UnpackDecimalIeee754<TDecimal, TValue>(otherDecimalBits);

            if (current.Significand == TValue.Zero && other.Significand == TValue.Zero)
            {
                return 0;
            }

            if (current.Signed)
            {
                if (!other.Signed)
                {
                    return -1;
                }
            }
            else if (other.Signed)
            {
                return 1;
            }

            int result = InternalUnsignedCompare(current, other);
            return current.Signed ? -result : result;

            // 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.
            static int InternalUnsignedCompare(DecodedDecimalIeee754<TValue> current, DecodedDecimalIeee754<TValue> other)
            {
                if (current.Significand == TValue.Zero)
                {
                    return other.Significand == TValue.Zero ? 0 : -1;
                }
                else if (other.Significand == TValue.Zero)
                {
                    return 1;
                }

                if (current.UnbiasedExponent == other.UnbiasedExponent && current.Significand == other.Significand)
                {
                    return 0;
                }

                if (current.UnbiasedExponent < other.UnbiasedExponent)
                {
                    return -InternalUnsignedCompare(other, current);
                }

                if (current.Significand >= other.Significand)
                {
                    return 1;
                }

                int diffExponent = current.UnbiasedExponent - other.UnbiasedExponent;
                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;
            }

            static int InternalInfinityCompare(TValue current, TValue other)
            {
                if (TDecimal.IsPositiveInfinity(current))
                {
                    return TDecimal.IsPositiveInfinity(other) ? 0 : 1;
                }
                else if (TDecimal.IsNegativeInfinity(current))
                {
                    return TDecimal.IsNegativeInfinity(other) ? 0 : -1;
                }

                return TDecimal.IsPositiveInfinity(other) ? -1 : 1;
            }
        }

        /// <summary>
        /// Determines whether two IEEE 754 decimal values represented by their raw bit patterns
        /// are numerically equal using the semantics required by the equality operator.
        /// </summary>
        /// <remarks>
        /// Unlike <see cref="CompareDecimalIeee754{TDecimal, TValue}"/>, which treats NaN as equal
        /// to NaN so that equality is consistent with hashing and ordering, this method follows the
        /// IEEE 754 equality-comparison rules used by <c>operator ==</c>: NaN is unordered and is
        /// therefore never equal to any value, including itself. All other values (including the two
        /// zeros and different members of the same cohort) compare by numeric value.
        /// </remarks>
        internal static bool EqualsDecimalIeee754<TDecimal, TValue>(TValue leftDecimalBits, TValue rightDecimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // Identical encodings are equal unless they are NaN; this also resolves most inequalities cheaply.
            if (leftDecimalBits == rightDecimalBits)
            {
                return !TDecimal.IsNaN(leftDecimalBits);
            }

            if (TDecimal.IsNaN(leftDecimalBits) || TDecimal.IsNaN(rightDecimalBits))
            {
                return false;
            }

            // Distinct bit patterns where either is infinity: equal only if both are infinity of the same sign
            // (non-canonical infinities share the same value).
            bool leftInfinity = TDecimal.IsInfinity(leftDecimalBits);
            bool rightInfinity = TDecimal.IsInfinity(rightDecimalBits);

            if (leftInfinity || rightInfinity)
            {
                return leftInfinity && rightInfinity && (TDecimal.IsNegative(leftDecimalBits) == TDecimal.IsNegative(rightDecimalBits));
            }

            DecodedDecimalIeee754<TValue> left = UnpackDecimalIeee754<TDecimal, TValue>(leftDecimalBits);
            DecodedDecimalIeee754<TValue> right = UnpackDecimalIeee754<TDecimal, TValue>(rightDecimalBits);

            bool leftZero = left.Significand == TValue.Zero;
            bool rightZero = right.Significand == TValue.Zero;

            if (leftZero || rightZero)
            {
                // Every zero (either sign, any cohort) is equal to every other zero and to nothing else.
                return leftZero && rightZero;
            }

            if (left.Signed != right.Signed)
            {
                return false;
            }

            if (left.UnbiasedExponent == right.UnbiasedExponent)
            {
                return left.Significand == right.Significand;
            }

            // Align to the smaller exponent: the larger-exponent coefficient must divide evenly into the other.
            if (left.UnbiasedExponent < right.UnbiasedExponent)
            {
                (left, right) = (right, left);
            }

            int diffExponent = left.UnbiasedExponent - right.UnbiasedExponent;
            if (diffExponent >= TDecimal.Precision)
            {
                return false;
            }

            (TValue quotient, TValue remainder) = TValue.DivRem(right.Significand, TDecimal.Power10(diffExponent));
            return (remainder == TValue.Zero) && (quotient == left.Significand);
        }

        /// <summary>
        /// Determines the ordering of two IEEE 754 decimal values represented by their raw bit
        /// patterns using the semantics required by the relational operators
        /// (<c>&lt;</c>, <c>&gt;</c>, <c>&lt;=</c>, <c>&gt;=</c>).
        /// </summary>
        /// <remarks>
        /// A NaN operand is unordered: every relational comparison that involves one is
        /// <see langword="false"/>. When neither operand is NaN the values are ordered by numeric
        /// value using <see cref="CompareDecimalIeee754{TDecimal, TValue}"/>, so the two zeros
        /// compare equal and different members of the same cohort compare equal.
        /// </remarks>
        internal static bool LessThanDecimalIeee754<TDecimal, TValue>(TValue leftDecimalBits, TValue rightDecimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return !TDecimal.IsNaN(leftDecimalBits) && !TDecimal.IsNaN(rightDecimalBits)
                && CompareDecimalIeee754<TDecimal, TValue>(leftDecimalBits, rightDecimalBits) < 0;
        }

        /// <inheritdoc cref="LessThanDecimalIeee754{TDecimal, TValue}(TValue, TValue)"/>
        internal static bool GreaterThanDecimalIeee754<TDecimal, TValue>(TValue leftDecimalBits, TValue rightDecimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return !TDecimal.IsNaN(leftDecimalBits) && !TDecimal.IsNaN(rightDecimalBits)
                && CompareDecimalIeee754<TDecimal, TValue>(leftDecimalBits, rightDecimalBits) > 0;
        }

        /// <inheritdoc cref="LessThanDecimalIeee754{TDecimal, TValue}(TValue, TValue)"/>
        internal static bool LessThanOrEqualDecimalIeee754<TDecimal, TValue>(TValue leftDecimalBits, TValue rightDecimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return !TDecimal.IsNaN(leftDecimalBits) && !TDecimal.IsNaN(rightDecimalBits)
                && CompareDecimalIeee754<TDecimal, TValue>(leftDecimalBits, rightDecimalBits) <= 0;
        }

        /// <inheritdoc cref="LessThanDecimalIeee754{TDecimal, TValue}(TValue, TValue)"/>
        internal static bool GreaterThanOrEqualDecimalIeee754<TDecimal, TValue>(TValue leftDecimalBits, TValue rightDecimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return !TDecimal.IsNaN(leftDecimalBits) && !TDecimal.IsNaN(rightDecimalBits)
                && CompareDecimalIeee754<TDecimal, TValue>(leftDecimalBits, rightDecimalBits) >= 0;
        }

        private static TValue NumberToDecimalIeee754Bits<TDecimal, TValue>(ref NumberBuffer number)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (number.DigitsCount == 0)
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(number.IsNegative, TValue.Zero, number.Scale);
            }

            Debug.Assert(number.Digits[0] != '0');
            Debug.Assert(number.DigitsCount != 0);

            int positiveExponent = Math.Max(0, number.Scale);
            int integerDigitsPresent = Math.Min(positiveExponent, number.DigitsCount);
            int fractionalDigitsPresent = number.DigitsCount - integerDigitsPresent;
            int exponent = number.Scale - integerDigitsPresent - fractionalDigitsPresent;

            if (exponent > TDecimal.MaxExponent)
            {
                return number.IsNegative ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            if (exponent > TDecimal.MaxAdjustedExponent)
            {
                return ClampExponentOverflow(ref number, exponent);
            }

            if (exponent < TDecimal.MinAdjustedExponent)
            {
                int numberDigitsRemove = TDecimal.MinAdjustedExponent - exponent;

                if (numberDigitsRemove > number.DigitsCount)
                {
                    return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(number.IsNegative, TValue.Zero, TDecimal.MinAdjustedExponent);
                }
                else if (numberDigitsRemove < number.DigitsCount)
                {
                    int numberDigitsRemain = number.DigitsCount - numberDigitsRemove;

                    if (numberDigitsRemain > TDecimal.Precision)
                    {
                        // The coefficient still exceeds the format precision after shifting to the
                        // minimum quantum, so the value is actually in the normal range rather than
                        // subnormal. Round the full (exact) digit string to the format precision in a
                        // single step; this avoids a double rounding and yields a quantum that is at or
                        // above the minimum adjusted exponent.
                        numberDigitsRemain = TDecimal.Precision;
                    }

                    return DecimalIeee754Rounding<TDecimal, TValue>(ref number, numberDigitsRemain);
                }
                else
                {
                    return RoundToZeroOrEpsilon<TDecimal, TValue>(ref number);
                }
            }

            if (number.DigitsCount > TDecimal.Precision)
            {
                int numberDigitsRemove = number.DigitsCount - TDecimal.Precision;
                if (exponent + numberDigitsRemove > TDecimal.MaxAdjustedExponent)
                {
                    return number.IsNegative ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
                }
                return DecimalIeee754Rounding<TDecimal, TValue>(ref number, TDecimal.Precision);
            }

            TValue significand = TDecimal.NumberToSignificand(ref number, number.DigitsCount);

            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(number.IsNegative, significand, exponent);

            static TValue ClampExponentOverflow(ref NumberBuffer number, int exponent)
            {
                Debug.Assert(exponent > TDecimal.MaxAdjustedExponent);

                int numberDigits = number.DigitsCount;

                int numberZeroDigits = exponent - TDecimal.MaxAdjustedExponent;

                if (numberDigits + numberZeroDigits > TDecimal.Precision)
                {
                    return number.IsNegative ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
                }

                for (int i = numberDigits; i < numberDigits + numberZeroDigits; i++)
                {
                    number.Digits[i] = (byte)'0';
                }

                number.Digits[numberDigits + numberZeroDigits] = (byte)('\0');
                number.DigitsCount += numberZeroDigits;
                number.Scale -= numberZeroDigits;

                number.CheckConsistency();

                TValue significand = TDecimal.NumberToSignificand(ref number, number.DigitsCount);

                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(number.IsNegative, significand, TDecimal.MaxAdjustedExponent);
            }
        }

        /// <summary>
        /// Encodes the given IEEE 754 decimal components into their Binary Integer Decimal (BID),
        /// producing the final <typeparamref name="TValue"/> bit pattern.
        /// </summary>
        /// <param name="signed">
        /// The sign of the value. <c>true</c> indicates a negative number; otherwise, <c>false</c>.
        /// </param>
        /// <param name="significand">
        /// The fully decoded significand (coefficient):
        /// - This is the complete integer coefficient with no packed BID encoding.
        /// - It includes all significant digits (non-trailing).
        /// - It has not been scaled by the exponent.
        /// </param>
        /// <param name="exponent">
        /// The <b>unbiased</b> exponent (actual exponent as defined by IEEE 754).
        /// This value has already been adjusted by subtracting the format's exponent bias,
        /// and will be re-biased internally when constructing the BID bit pattern.
        /// </param>
        /// <returns>
        /// The 32-bit or 64-bit or 128-bit IEEE 754 decimal BID encoding (depending on <typeparamref name="TValue"/>),
        /// containing the sign bit, combination field, biased exponent, and coefficient continuation bits.
        /// </returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static TValue DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(bool signed, TValue significand, int exponent)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            Debug.Assert(significand <= TDecimal.MaxSignificand);

            if (TValue.IsZero(significand))
            {
                if (exponent < TDecimal.MinAdjustedExponent)
                {
                    exponent = TDecimal.MinAdjustedExponent;
                }
                else if (exponent > TDecimal.MaxAdjustedExponent)
                {
                    exponent = TDecimal.MaxAdjustedExponent;
                }
            }

            uint biasedExponent = (uint)(exponent + TDecimal.ExponentBias);

            TValue value = TValue.Zero;
            bool msbSignificand = (significand & TDecimal.MostSignificantBitOfSignificandMask) != TValue.Zero;

            if (signed)
            {
                value = TDecimal.SignMask;
            }

            if (msbSignificand)
            {
                value |= TDecimal.G0G1Mask;
                value |= TDecimal.EncodeExponentToG2ThroughGwPlus3(biasedExponent);
                significand ^= TDecimal.MostSignificantBitOfSignificandMask;
                value |= significand;
            }
            else
            {
                value |= TDecimal.EncodeExponentToG0ThroughGwPlus1(biasedExponent);
                value |= significand;
            }

            return value;
        }

        /// <summary>
        /// Converts a value from its IEEE 754 binary integer decimal (BID) bit pattern to the equivalent
        /// densely packed decimal (DPD) bit pattern.
        /// </summary>
        internal static TValue EncodeDecimalIeee754<TDecimal, TValue>(TValue bidBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsInfinity(bidBits))
            {
                return ((bidBits & TDecimal.SignMask) != TValue.Zero) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            int declets = TDecimal.NumberBitsSignificand / 10;
            TValue payloadMask = (TValue.One << TDecimal.NumberBitsSignificand) - TValue.One;

            if (TDecimal.IsNaN(bidBits))
            {
                // The sign, the five-bit NaN marker, and the signaling bit occupy the same positions in both
                // encodings; only the trailing payload changes representation (binary integer to declets). This
                // is a cross-encoding conversion, so the reserved bits between the signaling bit and the payload
                // are dropped to keep the result canonical.
                TValue payload = bidBits & payloadMask;

                if (payload >= TDecimal.Power10(TDecimal.Precision - 1))
                {
                    payload = TValue.Zero;
                }

                return (bidBits & (TDecimal.SignMask | TDecimal.SNaNMask)) | PackDeclets(payload, declets);
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(bidBits);
            uint biasedExponent = (uint)(decoded.UnbiasedExponent + TDecimal.ExponentBias);

            TValue scale = TDecimal.Power10(TDecimal.Precision - 1);
            TValue leadingDigit = decoded.Significand / scale;
            uint msd = uint.CreateTruncating(leadingDigit);

            int exponentContinuationBits = (sizeof(TValue) * 8) - 6 - TDecimal.NumberBitsSignificand;
            uint exponentHigh = biasedExponent >> exponentContinuationBits;
            uint exponentLow = biasedExponent & ((1u << exponentContinuationBits) - 1);

            // The leading digit and the two most-significant exponent bits share the five-bit combination field.
            uint combination = (msd <= 7)
                ? (exponentHigh << 3) | msd
                : 0b11000u | (exponentHigh << 1) | (msd - 8);

            TValue result = (decoded.Signed ? TDecimal.SignMask : TValue.Zero);
            result |= TValue.CreateTruncating(combination) << (TDecimal.NumberBitsSignificand + exponentContinuationBits);
            result |= TValue.CreateTruncating(exponentLow) << TDecimal.NumberBitsSignificand;
            result |= PackDeclets(decoded.Significand - (leadingDigit * scale), declets);
            return result;
        }

        /// <summary>
        /// Converts a value from its IEEE 754 densely packed decimal (DPD) bit pattern to the equivalent
        /// binary integer decimal (BID) bit pattern.
        /// </summary>
        internal static TValue DecodeDecimalIeee754<TDecimal, TValue>(TValue dpdBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsInfinity(dpdBits))
            {
                return ((dpdBits & TDecimal.SignMask) != TValue.Zero) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            int declets = TDecimal.NumberBitsSignificand / 10;
            TValue payloadMask = (TValue.One << TDecimal.NumberBitsSignificand) - TValue.One;

            if (TDecimal.IsNaN(dpdBits))
            {
                // The sign, the five-bit NaN marker, and the signaling bit occupy the same positions in both
                // encodings; only the trailing payload changes representation (declets to binary integer). This
                // is a cross-encoding conversion, so the reserved bits between the signaling bit and the payload
                // are dropped to keep the result canonical.
                TValue payload = UnpackDeclets(dpdBits & payloadMask, declets);

                return (dpdBits & (TDecimal.SignMask | TDecimal.SNaNMask)) | payload;
            }

            int exponentContinuationBits = (sizeof(TValue) * 8) - 6 - TDecimal.NumberBitsSignificand;
            uint combination = uint.CreateTruncating(dpdBits >> (TDecimal.NumberBitsSignificand + exponentContinuationBits)) & 0x1F;
            uint exponentLow = uint.CreateTruncating(dpdBits >> TDecimal.NumberBitsSignificand) & ((1u << exponentContinuationBits) - 1);

            uint exponentHigh;
            uint msd;

            if ((combination >> 3) != 0b11)
            {
                exponentHigh = combination >> 3;
                msd = combination & 0x7;
            }
            else
            {
                exponentHigh = (combination >> 1) & 0x3;
                msd = 8 | (combination & 1);
            }

            int unbiasedExponent = (int)((exponentHigh << exponentContinuationBits) | exponentLow) - TDecimal.ExponentBias;
            TValue significand = (TValue.CreateTruncating(msd) * TDecimal.Power10(TDecimal.Precision - 1)) + UnpackDeclets(dpdBits & payloadMask, declets);

            bool signed = (dpdBits & TDecimal.SignMask) != TValue.Zero;
            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(signed, significand, unbiasedExponent);
        }

        /// <summary>Packs the trailing decimal digits of a coefficient into densely packed decimal declets.</summary>
        private static TValue PackDeclets<TValue>(TValue low, int declets)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue thousand = TValue.CreateTruncating(1000);
            TValue trailing = TValue.Zero;

            for (int i = 0; i < declets; i++)
            {
                TValue quotient = low / thousand;
                uint group = uint.CreateTruncating(low - (quotient * thousand));
                low = quotient;

                uint declet = DigitsToDeclet((int)(group / 100), (int)((group / 10) % 10), (int)(group % 10));
                trailing |= TValue.CreateTruncating(declet) << (10 * i);
            }

            return trailing;
        }

        /// <summary>Unpacks densely packed decimal declets into the trailing decimal digits of a coefficient.</summary>
        private static TValue UnpackDeclets<TValue>(TValue trailing, int declets)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue thousand = TValue.CreateTruncating(1000);
            TValue decletMask = TValue.CreateTruncating(0x3FF);
            TValue low = TValue.Zero;

            for (int i = declets - 1; i >= 0; i--)
            {
                uint declet = uint.CreateTruncating((trailing >> (10 * i)) & decletMask);
                (int d2, int d1, int d0) = DecletToDigits(declet);
                low = (low * thousand) + TValue.CreateTruncating((d2 * 100) + (d1 * 10) + d0);
            }

            return low;
        }

        /// <summary>Packs three decimal digits (each 0-9) into a ten-bit densely packed decimal declet.</summary>
        private static uint DigitsToDeclet(int d2, int d1, int d0)
        {
            // See IEEE 754-2019 Table 3.6. Each digit's unit bit passes through unchanged (b7, b4, b0);
            // the high bits of each digit and a three-bit selector for which digits are 8 or 9 fill the rest.
            int u2 = d2 & 1;
            int u1 = d1 & 1;
            int u0 = d0 & 1;

            int p2 = (d2 >> 2) & 1;
            int q2 = (d2 >> 1) & 1;
            int p1 = (d1 >> 2) & 1;
            int q1 = (d1 >> 1) & 1;
            int p0 = (d0 >> 2) & 1;
            int q0 = (d0 >> 1) & 1;

            bool large2 = d2 >= 8;
            bool large1 = d1 >= 8;
            bool large0 = d0 >= 8;

            (int b9, int b8, int b6, int b5, int b3, int b2, int b1) = (large2, large1, large0) switch
            {
                (false, false, false) => (p2, q2, p1, q1, 0, p0, q0),
                (false, false, true) => (p2, q2, p1, q1, 1, 0, 0),
                (false, true, false) => (p2, q2, p0, q0, 1, 0, 1),
                (true, false, false) => (p0, q0, p1, q1, 1, 1, 0),
                (true, true, false) => (p0, q0, 0, 0, 1, 1, 1),
                (true, false, true) => (p1, q1, 0, 1, 1, 1, 1),
                (false, true, true) => (p2, q2, 1, 0, 1, 1, 1),
                (true, true, true) => (0, 0, 1, 1, 1, 1, 1),
            };

            return (uint)((b9 << 9) | (b8 << 8) | (u2 << 7) | (b6 << 6) | (b5 << 5) | (u1 << 4) | (b3 << 3) | (b2 << 2) | (b1 << 1) | u0);
        }

        /// <summary>Unpacks a ten-bit densely packed decimal declet into three decimal digits (each 0-9).</summary>
        private static (int D2, int D1, int D0) DecletToDigits(uint declet)
        {
            static int Digit(int hi, int mid, int lo) => (hi << 2) | (mid << 1) | lo;

            int b0 = (int)(declet & 1);
            int b1 = (int)((declet >> 1) & 1);
            int b2 = (int)((declet >> 2) & 1);
            int b3 = (int)((declet >> 3) & 1);
            int b4 = (int)((declet >> 4) & 1);
            int b5 = (int)((declet >> 5) & 1);
            int b6 = (int)((declet >> 6) & 1);
            int b7 = (int)((declet >> 7) & 1);
            int b8 = (int)((declet >> 8) & 1);
            int b9 = (int)((declet >> 9) & 1);

            // See IEEE 754-2019 Table 3.6. b3 then b2/b1 then b6/b5 select which digits were 8 or 9.
            return (b3, b2, b1, b6, b5) switch
            {
                (0, _, _, _, _) => (Digit(b9, b8, b7), Digit(b6, b5, b4), Digit(b2, b1, b0)),
                (1, 0, 0, _, _) => (Digit(b9, b8, b7), Digit(b6, b5, b4), 8 | b0),
                (1, 0, 1, _, _) => (Digit(b9, b8, b7), 8 | b4, Digit(b6, b5, b0)),
                (1, 1, 0, _, _) => (8 | b7, Digit(b6, b5, b4), Digit(b9, b8, b0)),
                (1, 1, 1, 0, 0) => (8 | b7, 8 | b4, Digit(b9, b8, b0)),
                (1, 1, 1, 0, 1) => (8 | b7, Digit(b9, b8, b4), 8 | b0),
                (1, 1, 1, 1, 0) => (Digit(b9, b8, b7), 8 | b4, 8 | b0),
                _ => (8 | b7, 8 | b4, 8 | b0),
            };
        }

        private static TValue RoundToZeroOrEpsilon<TDecimal, TValue>(ref NumberBuffer coefficient)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            int midPointValue = coefficient.Digits[0];

            if (midPointValue < '5')
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(coefficient.IsNegative, TValue.Zero, TDecimal.MinAdjustedExponent);
            }
            else if (midPointValue > '5')
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(coefficient.IsNegative, TValue.One, TDecimal.MinAdjustedExponent);
            }
            else
            {
                return coefficient.DigitsCount > 1 && (coefficient.Digits.Slice(1).ContainsAnyExcept((byte)'0') || coefficient.HasNonZeroTail)
                    ? DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(coefficient.IsNegative, TValue.One, TDecimal.MinAdjustedExponent)
                    : DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(coefficient.IsNegative, TValue.Zero, TDecimal.MinAdjustedExponent);
            }
        }

        /// <summary>
        /// Performs IEEE 754-compliant rounding on a decimal-like number before converting it
        /// to an IEEE 754 decimal32/64/128 encoded value.
        ///
        /// ---------------------------------------------------------------
        ///  ROUNDING DECISION (implements round-to-nearest, ties-to-even)
        ///
        ///  Unit In The Last Place (ULP) formula: ULP = 10^(unbiased exponent - number digits precision + 1)
        ///  The difference between the unrounded number and the rounded
        ///  representable value is effectively compared against ±ULP/2.
        ///
        ///  If discarded part > 0.5 ULP → round up
        ///  If discarded part &lt; 0.5 ULP → round down
        ///  If exactly 0.5 ULP → ties-to-even
        /// </summary>
        private static TValue DecimalIeee754Rounding<TDecimal, TValue>(ref NumberBuffer number, int digitsRemain)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            Debug.Assert(digitsRemain < number.DigitsCount);
            Debug.Assert(digitsRemain <= TDecimal.Precision);
            Debug.Assert(digitsRemain >= 0);

            int positiveExponent = (Math.Max(0, number.Scale));
            int integerDigitsPresent = Math.Min(positiveExponent, number.DigitsCount);
            int fractionalDigitsPresent = number.DigitsCount - integerDigitsPresent;
            int exponent = number.Scale - integerDigitsPresent - fractionalDigitsPresent;
            exponent += number.DigitsCount - digitsRemain;

            Debug.Assert(exponent >= TDecimal.MinAdjustedExponent && exponent <= TDecimal.MaxAdjustedExponent);

            TValue significand = TDecimal.NumberToSignificand(ref number, digitsRemain);

            Debug.Assert(significand <= TDecimal.MaxSignificand);

            bool roundDown = true;
            int midPointValue = number.Digits[digitsRemain];

            if (midPointValue > '5')
            {
                roundDown = false;
            }
            else if (midPointValue == '5')
            {
                int index = digitsRemain + 1;

                if (number.HasNonZeroTail
                    || int.IsOddInteger(number.Digits[digitsRemain - 1] - '0')
                    || number.Digits.Slice(index, number.DigitsCount - index).ContainsAnyExcept((byte)'0'))
                {
                    roundDown = false;
                }
            }

            if (roundDown)
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(number.IsNegative, significand, exponent);
            }

            if (significand == TDecimal.MaxSignificand)
            {
                exponent += 1;

                if (exponent > TDecimal.MaxAdjustedExponent)
                {
                    return number.IsNegative ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
                }

                significand = TDecimal.Power10(TDecimal.Precision - 1);
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(number.IsNegative, significand, exponent);
            }

            significand += TValue.One;

            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(number.IsNegative, significand, exponent);
        }

        /// <summary>
        /// Produces the quiet NaN that an arithmetic operation propagates from its NaN operands, following the
        /// IEEE 754-2019 §6.2.3 recommendation to preserve the payload of the first NaN operand.
        /// </summary>
        /// <remarks>
        /// The first NaN operand (<paramref name="left" /> before <paramref name="right" />) supplies the sign and
        /// payload of the result. A signaling NaN is quieted and a payload that is too large to be canonical
        /// (greater than or equal to 10^(<c>Precision</c> - 1)) is discarded, matching the behavior of the Intel
        /// reference implementation.
        /// </remarks>
        private static TValue PropagateNaN<TDecimal, TValue>(TValue left, TValue right)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `unpack_BID32`, `unpack_BID64`, and `unpack_BID128_value_BLE` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            TValue nanBits = TDecimal.IsNaN(left) ? left : right;

            // The payload occupies the trailing significand field; a value at or above the canonical
            // bound is non-canonical and reads as zero. Re-encoding through the NaN combination mask
            // clears the signaling bit, yielding a canonical quiet NaN that keeps the operand's sign.
            TValue payload = nanBits & ((TValue.One << TDecimal.NumberBitsSignificand) - TValue.One);

            if (payload >= TDecimal.Power10(TDecimal.Precision - 1))
            {
                payload = TValue.Zero;
            }

            return (nanBits & TDecimal.SignMask) | TDecimal.NaNMask | payload;
        }

        /// <summary>
        /// Returns <paramref name="bits" /> unchanged when it is a number, or the canonical quiet NaN when it is a
        /// NaN. The minimum/maximum family selects one operand to return; routing that operand through this helper
        /// canonicalizes a NaN result as IEEE 754-2019 §5.1 requires without disturbing the numeric selection.
        /// </summary>
        private static TValue CanonicalizeIfNaN<TDecimal, TValue>(TValue bits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return TDecimal.IsNaN(bits) ? PropagateNaN<TDecimal, TValue>(bits, bits) : bits;
        }

        /// <summary>
        /// Adds two IEEE 754 decimal values represented by their raw bit patterns and returns the
        /// bit pattern of the correctly rounded (round-to-nearest, ties-to-even) sum.
        /// </summary>
        /// <remarks>
        /// The two operands are decoded and aligned to their common (smaller) exponent by scaling the larger-exponent
        /// coefficient up at double integer width. Digits of the smaller operand that fall below the retained precision
        /// are folded into a sticky flag. The aligned coefficients are then added or subtracted with word-level integer
        /// arithmetic and fed into the shared rounding path, producing the same result as computing the exact sum. This
        /// mirrors the mathematical behavior of the Intel reference implementation.
        /// </remarks>
        internal static TValue AddDecimalIeee754<TDecimal, TValue>(TValue left, TValue right)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_add`, `bid64_add`, and `bid128_add` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(left) || TDecimal.IsNaN(right))
            {
                return PropagateNaN<TDecimal, TValue>(left, right);
            }

            if (TDecimal.IsInfinity(left))
            {
                // Inf + Inf with opposing signs is invalid (NaN); every other combination
                // that includes at least one infinity returns that infinity (canonicalized).
                if (TDecimal.IsInfinity(right) && (TDecimal.IsNegative(left) != TDecimal.IsNegative(right)))
                {
                    // An invalid operation produces the canonical quiet NaN, which the Intel reference
                    // emits with a positive sign and empty payload (`NaNMask`), unlike the negative
                    // `TDecimal.NaN` constant.
                    return TDecimal.NaNMask;
                }
                return TDecimal.IsNegative(left) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            if (TDecimal.IsInfinity(right))
            {
                return TDecimal.IsNegative(right) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(left);
            DecodedDecimalIeee754<TValue> b = UnpackDecimalIeee754<TDecimal, TValue>(right);

            bool aZero = TValue.IsZero(a.Significand);
            bool bZero = TValue.IsZero(b.Significand);

            if (aZero && bZero)
            {
                // The sum of two zeros keeps the shared sign, otherwise it is +0 under
                // round-to-nearest. The preferred exponent for a zero result is the smaller one.
                bool zeroSign = a.Signed == b.Signed && a.Signed;
                int zeroExponent = Math.Min(a.UnbiasedExponent, b.UnbiasedExponent);
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(zeroSign, TValue.Zero, zeroExponent);
            }

            if (aZero || bZero)
            {
                // Adding zero yields the other operand's value, but the preferred exponent is the
                // smaller of the two exponents. When the zero's exponent is larger there is nothing
                // to do; otherwise the coefficient is padded with trailing zeros (bounded by the
                // available precision) to lower the exponent toward the zero's exponent.
                DecodedDecimalIeee754<TValue> nonZero = aZero ? b : a;
                TValue nonZeroBits = aZero ? right : left;
                int zeroExponent = aZero ? a.UnbiasedExponent : b.UnbiasedExponent;

                if (zeroExponent >= nonZero.UnbiasedExponent)
                {
                    return nonZeroBits;
                }

                int nonZeroDigits = TDecimal.CountDigits(nonZero.Significand);
                int pad = Math.Min(nonZero.UnbiasedExponent - zeroExponent, TDecimal.Precision - nonZeroDigits);
                TValue paddedSignificand = nonZero.Significand * TDecimal.Power10(pad);
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(nonZero.Signed, paddedSignificand, nonZero.UnbiasedExponent - pad);
            }

            // Both operands are finite and non-zero. Order them so `hi` has the larger (or equal)
            // exponent, then align `lo` to `hi` by scaling `hi` up. The exponent difference is
            // capped: anything beyond `guard` extra digits cannot influence the retained precision
            // except through rounding, so those low-order digits of `lo` become a sticky flag.
            DecodedDecimalIeee754<TValue> hi;
            DecodedDecimalIeee754<TValue> lo;

            if (a.UnbiasedExponent >= b.UnbiasedExponent)
            {
                hi = a;
                lo = b;
            }
            else
            {
                hi = b;
                lo = a;
            }

            int exponentDifference = hi.UnbiasedExponent - lo.UnbiasedExponent;
            int guard = TDecimal.Precision + 2;
            int effectiveDifference = Math.Min(exponentDifference, guard);
            int droppedDigits = exponentDifference - effectiveDifference;
            int commonExponent = hi.UnbiasedExponent - effectiveDifference;

            // Align `hi` to the common exponent by scaling its coefficient up by 10^effectiveDifference. The
            // scaled coefficient can exceed a single limb (up to ~10^(2*Precision+1)), so it is held at double
            // width. The scale factor fits a single limb because effectiveDifference <= Precision + 2. When the
            // exponents are already equal (the common case) the scale factor is one, so the coefficient stays in
            // the low limb and the wide multiply is skipped.
            TValue magnitudeHigh;
            TValue magnitudeLow;

            if (effectiveDifference == 0)
            {
                magnitudeHigh = TValue.Zero;
                magnitudeLow = hi.Significand;
            }
            else
            {
                WideMultiply(hi.Significand, AlignmentScaleFactor<TDecimal, TValue>(effectiveDifference), out magnitudeHigh, out magnitudeLow);
            }

            // Align `lo` to the common exponent by discarding its `droppedDigits` least-significant digits, which
            // fall below the retained range and only contribute stickiness. The retained portion fits a single limb.
            bool sticky = false;
            TValue loRetained;

            if (droppedDigits >= TDecimal.CountDigits(lo.Significand))
            {
                loRetained = TValue.Zero;
                sticky = true;
            }
            else if (droppedDigits > 0)
            {
                (loRetained, TValue remainder) = TValue.DivRem(lo.Significand, TDecimal.Power10(droppedDigits));
                sticky = !TValue.IsZero(remainder);
            }
            else
            {
                loRetained = lo.Significand;
            }

            bool sameSign = hi.Signed == lo.Signed;
            bool resultSign;

            if (sameSign)
            {
                // Magnitudes add. Fold the retained `lo` coefficient into the double-width accumulator.
                TValue newLow = magnitudeLow + loRetained;
                if (newLow < magnitudeLow)
                {
                    magnitudeHigh += TValue.One;
                }
                magnitudeLow = newLow;
                resultSign = hi.Signed;
            }
            else
            {
                // Magnitudes subtract. When `droppedDigits > 0` the scaled `hi` coefficient is at least 10^guard,
                // which dominates the retained `lo` (< 10^Precision), so `hi` always compares greater in that case.
                int comparison = !TValue.IsZero(magnitudeHigh) ? 1 : magnitudeLow.CompareTo(loRetained);

                if (comparison > 0)
                {
                    if (magnitudeLow < loRetained)
                    {
                        magnitudeHigh -= TValue.One;
                    }
                    magnitudeLow -= loRetained;
                    resultSign = hi.Signed;

                    if (sticky)
                    {
                        // The true `lo` magnitude is slightly larger than its retained digits, so the exact
                        // difference is one unit smaller with a non-zero fractional remainder.
                        if (TValue.IsZero(magnitudeLow))
                        {
                            magnitudeHigh -= TValue.One;
                        }
                        magnitudeLow -= TValue.One;
                    }
                }
                else if (comparison < 0)
                {
                    // `droppedDigits` is always zero here, so there is no sticky remainder to account for and both
                    // magnitudes fit a single limb.
                    magnitudeLow = loRetained - magnitudeLow;
                    magnitudeHigh = TValue.Zero;
                    resultSign = lo.Signed;
                }
                else
                {
                    // Exact cancellation produces +0 under round-to-nearest.
                    return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(false, TValue.Zero, commonExponent);
                }
            }

            if (TValue.IsZero(magnitudeHigh) && TValue.IsZero(magnitudeLow) && !sticky)
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(false, TValue.Zero, commonExponent);
            }

            // Common case: the exact sum already fits the format precision at a representable exponent, so it needs
            // no rounding and encodes directly. This mirrors the no-rounding tail of the wide path below without the
            // out-of-line call. A non-empty `sticky` tail cannot occur here: it only arises when the exponent
            // difference exceeds the guard span, which forces more than `Precision` result digits (a non-zero high
            // limb or a wider low limb), so it is excluded by these bounds and needs no separate check.
            if (TValue.IsZero(magnitudeHigh)
                && (commonExponent >= TDecimal.MinAdjustedExponent)
                && (commonExponent <= TDecimal.MaxAdjustedExponent)
                && (TDecimal.CountDigits(magnitudeLow) <= TDecimal.Precision))
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, magnitudeLow, commonExponent);
            }

            return NumberToDecimalIeee754BitsFromWide<TDecimal, TValue>(resultSign, magnitudeHigh, magnitudeLow, commonExponent, sticky);
        }

        /// <summary>
        /// Subtracts one IEEE 754 decimal value from another, both represented by their raw bit patterns, and
        /// returns the bit pattern of the correctly rounded (round-to-nearest, ties-to-even) difference.
        /// </summary>
        /// <remarks>
        /// Subtraction negates the right operand and defers to <see cref="AddDecimalIeee754" />. The sign of a NaN
        /// operand is left untouched so that a NaN result propagates the same payload and sign as addition would.
        /// </remarks>
        internal static TValue SubtractDecimalIeee754<TDecimal, TValue>(TValue left, TValue right)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_sub`, `bid64_sub`, and `bid128_sub` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (!TDecimal.IsNaN(right))
            {
                right ^= TDecimal.SignMask;
            }

            return AddDecimalIeee754<TDecimal, TValue>(left, right);
        }

        /// <summary>
        /// Multiplies two IEEE 754 decimal values represented by their raw bit patterns and returns the
        /// bit pattern of the correctly rounded (round-to-nearest, ties-to-even) product.
        /// </summary>
        /// <remarks>
        /// The operands are decoded and their coefficients multiplied exactly using a double-width integer product
        /// (the product can require up to twice the format precision). The exact product exponent is the sum of the
        /// operand exponents, which is also the IEEE 754 preferred exponent because trailing zeros of the product are
        /// retained. The exact product is then fed into the shared word-level rounding path. This mirrors the
        /// mathematical behavior of the Intel reference implementation.
        /// </remarks>
        internal static TValue MultiplyDecimalIeee754<TDecimal, TValue>(TValue left, TValue right)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_mul`, `bid64_mul`, and `bid128_mul` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(left) || TDecimal.IsNaN(right))
            {
                return PropagateNaN<TDecimal, TValue>(left, right);
            }

            // The sign of a product is always the exclusive-or of the operand signs, including zeros.
            bool resultSign = TDecimal.IsNegative(left) ^ TDecimal.IsNegative(right);

            bool leftInfinity = TDecimal.IsInfinity(left);
            bool rightInfinity = TDecimal.IsInfinity(right);

            if (leftInfinity || rightInfinity)
            {
                // Infinity multiplied by zero is invalid (NaN); any other product involving an infinity is
                // an infinity carrying the exclusive-or sign.
                bool otherZero = (leftInfinity && !rightInfinity && TValue.IsZero(UnpackDecimalIeee754<TDecimal, TValue>(right).Significand))
                              || (rightInfinity && !leftInfinity && TValue.IsZero(UnpackDecimalIeee754<TDecimal, TValue>(left).Significand));

                if (otherZero)
                {
                    // An invalid operation produces the canonical quiet NaN, which the Intel reference
                    // emits with a positive sign and empty payload (`NaNMask`), unlike the negative
                    // `TDecimal.NaN` constant.
                    return TDecimal.NaNMask;
                }

                return resultSign ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(left);
            DecodedDecimalIeee754<TValue> b = UnpackDecimalIeee754<TDecimal, TValue>(right);

            int productExponent = a.UnbiasedExponent + b.UnbiasedExponent;

            if (TValue.IsZero(a.Significand) || TValue.IsZero(b.Significand))
            {
                // Zero times a finite value is zero. The preferred exponent is the sum of the operand
                // exponents (clamped to the representable range by the encoder).
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, TValue.Zero, productExponent);
            }

            // The exact product of two coefficients needs up to twice the format precision, so it is computed at
            // double the integer width. The sum of the operand exponents is also the IEEE 754 preferred exponent
            // (trailing zeros of the product are retained), so it is fed unchanged into the shared word-level
            // rounding/encoding path.
            WideMultiply(a.Significand, b.Significand, out TValue productHigh, out TValue productLow);

            return NumberToDecimalIeee754BitsFromWide<TDecimal, TValue>(resultSign, productHigh, productLow, productExponent, sticky: false);
        }

        /// <summary>
        /// Multiplies the IEEE 754 decimal value represented by <paramref name="bits"/> by the positive constant
        /// <c>((<paramref name="constantHead"/> × 10^Precision) + <paramref name="constantTail"/>) ×
        /// 10^<paramref name="constantExponent"/></c>, rounds the exact product once (round-to-nearest,
        /// ties-to-even), and returns its bit pattern.
        /// </summary>
        /// <remarks>
        /// Splitting the constant at the format precision is what keeps this within the double-width machinery
        /// the arithmetic operators already use: both halves fit a single limb, so each partial product is one
        /// <see cref="WideMultiply{TValue}"/>, and the low product is exactly <c>Precision</c> digits below the
        /// high one, so shifting it into place is a digit drop whose remainder can only ever be sticky.
        ///
        /// How many digits a constant needs is a property of that constant, not of the format: for an irrational
        /// constant the closest a <c>Precision</c> digit significand drives the exact product to a midpoint has
        /// no closed form, so it has to be enumerated against the truncation error once per constant rather than
        /// carried over from a narrower format. See <c>Decimal128</c> for the existing pair.
        /// </remarks>
        internal static TValue MultiplyByWideConstantDecimalIeee754<TDecimal, TValue>(TValue bits, TValue constantHead, TValue constantTail, int constantExponent)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsNaN(bits))
            {
                return PropagateNaN<TDecimal, TValue>(bits, bits);
            }

            if (TDecimal.IsInfinity(bits))
            {
                // The constant is positive and finite, so the infinity carries through with its sign
                return TDecimal.IsNegative(bits) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> value = UnpackDecimalIeee754<TDecimal, TValue>(bits);

            int precision = TDecimal.Precision;

            if (TValue.IsZero(value.Significand))
            {
                // The IEEE 754 preferred exponent for a product is the sum of the operand exponents, and the
                // constant's own quantum is 10^constantExponent
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(value.Signed, TValue.Zero, value.UnbiasedExponent + constantExponent);
            }

            // `significand × constantHead` spans at most `2p + 2` digits and `significand × constantTail` at most
            // `2p`, so both fit the limb pair, and everything the alignment drop removes is far enough below the
            // result's last digit to only ever reach it through `sticky`.
            WideMultiply(value.Significand, constantHead, out TValue high, out TValue low);
            WideMultiply(value.Significand, constantTail, out TValue tailHigh, out TValue tailLow);

            bool sticky = false;
            DropDigits<TDecimal, TValue>(ref tailHigh, ref tailLow, precision, ref sticky, out int roundDigit);
            sticky |= roundDigit != 0;

            WideAdd(high, low, tailHigh, tailLow, out high, out low);

            return NumberToDecimalIeee754BitsFromWide<TDecimal, TValue>(value.Signed, high, low, value.UnbiasedExponent + constantExponent + precision, sticky);
        }

        /// <summary>
        /// Computes <c>(left × right) + addend</c> for three IEEE 754 decimal values represented by their raw bit
        /// patterns, rounds the exact result once (round-to-nearest, ties-to-even), and returns its bit pattern.
        /// </summary>
        /// <remarks>
        /// The exact product coefficient (up to twice the format precision) is computed at double integer width, so the
        /// product is never rounded before the addend is combined with it. The product and addend are aligned to a
        /// common exponent within a window wide enough to preserve every digit that can influence the result (including
        /// the deepest cancellation); digits below the window are folded into a sticky flag and the aligned coefficients
        /// are fed into the shared word-level rounding path, producing the same result as a single rounding of the exact
        /// value. This mirrors the mathematical behavior of the Intel reference implementation; a faithful port of its
        /// reciprocal-multiply rounding is a possible future performance optimization.
        /// </remarks>
        internal static TValue FusedMultiplyAddDecimalIeee754<TDecimal, TValue>(TValue x, TValue y, TValue z)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_fma`, `bid64_fma`, and `bid128_fma` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            // A NaN operand propagates its (quieted) payload. The Intel reference inspects the operands in the order
            // y, then z, then x, so the first NaN in that order supplies the sign and payload of the result.
            if (TDecimal.IsNaN(y))
            {
                return PropagateNaN<TDecimal, TValue>(y, y);
            }

            if (TDecimal.IsNaN(z))
            {
                return PropagateNaN<TDecimal, TValue>(z, z);
            }

            if (TDecimal.IsNaN(x))
            {
                return PropagateNaN<TDecimal, TValue>(x, x);
            }

            // The product sign is the exclusive-or of the factor signs, including zeros and infinities.
            bool productSign = TDecimal.IsNegative(x) ^ TDecimal.IsNegative(y);

            bool xInfinity = TDecimal.IsInfinity(x);
            bool yInfinity = TDecimal.IsInfinity(y);

            if (xInfinity || yInfinity)
            {
                // Infinity multiplied by zero is invalid (NaN); the Intel reference emits the canonical quiet NaN.
                bool otherZero = (xInfinity && !yInfinity && TValue.IsZero(UnpackDecimalIeee754<TDecimal, TValue>(y).Significand))
                              || (yInfinity && !xInfinity && TValue.IsZero(UnpackDecimalIeee754<TDecimal, TValue>(x).Significand));

                if (otherZero)
                {
                    return TDecimal.NaNMask;
                }

                // The product is an infinity. Adding an infinity of the opposite sign is invalid (NaN); every other
                // addend leaves the product's infinity unchanged (canonicalized).
                if (TDecimal.IsInfinity(z) && (TDecimal.IsNegative(z) != productSign))
                {
                    return TDecimal.NaNMask;
                }

                return productSign ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            // The product is finite. A finite product plus an infinite addend is that infinity (canonicalized).
            if (TDecimal.IsInfinity(z))
            {
                return TDecimal.IsNegative(z) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> dx = UnpackDecimalIeee754<TDecimal, TValue>(x);
            DecodedDecimalIeee754<TValue> dy = UnpackDecimalIeee754<TDecimal, TValue>(y);
            DecodedDecimalIeee754<TValue> dz = UnpackDecimalIeee754<TDecimal, TValue>(z);

            int productExponent = dx.UnbiasedExponent + dy.UnbiasedExponent;
            bool productZero = TValue.IsZero(dx.Significand) || TValue.IsZero(dy.Significand);

            bool addendSign = dz.Signed;
            int addendExponent = dz.UnbiasedExponent;
            TValue addendSignificand = dz.Significand;
            bool addendZero = TValue.IsZero(addendSignificand);

            if (productZero)
            {
                // A zero product reduces the result to the addend at the preferred (smaller) exponent, matching the
                // zero handling in addition (the product's preferred exponent is the sum of the factor exponents).
                if (addendZero)
                {
                    bool bothNegative = productSign == addendSign && productSign;
                    return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(bothNegative, TValue.Zero, Math.Min(productExponent, addendExponent));
                }

                if (productExponent >= addendExponent)
                {
                    return z;
                }

                int addendDigits = TDecimal.CountDigits(addendSignificand);
                int pad = Math.Min(addendExponent - productExponent, TDecimal.Precision - addendDigits);

                // The product's exponent can be far below the minimum quantum, so bound the padding so the
                // result stays at or above it; a zero product cannot push the exact addend into subnormal range.
                pad = Math.Min(pad, addendExponent - TDecimal.MinAdjustedExponent);
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(addendSign, addendSignificand * TDecimal.Power10(pad), addendExponent - pad);
            }

            // The exact product coefficient occupies up to twice the format precision and is held at double width.
            WideMultiply(dx.Significand, dy.Significand, out TValue productHigh, out TValue productLow);
            int productDigits = WideDigitCount<TDecimal, TValue>(productHigh, productLow);

            if (addendZero)
            {
                // Adding a zero lowers the preferred exponent toward the addend's exponent, bounded by the product
                // exponent; the alignment below realizes it by scaling the product's coefficient up (padding zeros).
                addendExponent = Math.Min(addendExponent, productExponent);
            }

            int productMsd = productExponent + productDigits - 1;
            int addendDigitsCount = addendZero ? 0 : TDecimal.CountDigits(addendSignificand);
            int addendMsd = addendZero ? int.MinValue : addendExponent + addendDigitsCount - 1;

            int maxMsd = Math.Max(productMsd, addendMsd);
            int minLsd = Math.Min(productExponent, addendExponent);

            // Retain a window wide enough to hold the full product (up to 2*Precision digits) plus guard digits, which
            // also covers the deepest possible cancellation. When the operands are far enough apart that the window
            // cannot reach the lower one, its digits fall below the retained range and only contribute stickiness.
            int retain = (2 * TDecimal.Precision) + 2;
            int commonExponent = Math.Max(minLsd, maxMsd - retain + 1);

            bool sticky = false;

            TValue aHigh = productHigh;
            TValue aLow = productLow;
            AlignWideToCommonExponent<TDecimal, TValue>(ref aHigh, ref aLow, productExponent, commonExponent, ref sticky);

            TValue bHigh = TValue.Zero;
            TValue bLow = addendSignificand;

            if (!addendZero)
            {
                AlignWideToCommonExponent<TDecimal, TValue>(ref bHigh, ref bLow, addendExponent, commonExponent, ref sticky);
            }

            bool resultSign;
            TValue resultHigh;
            TValue resultLow;

            if (productSign == addendSign)
            {
                // Magnitudes add.
                resultHigh = aHigh + bHigh;
                resultLow = aLow + bLow;

                if (resultLow < aLow)
                {
                    resultHigh += TValue.One;
                }

                resultSign = productSign;
            }
            else
            {
                int comparison = WideCompare(aHigh, aLow, bHigh, bLow);

                if (comparison == 0)
                {
                    // The retained magnitudes cancel exactly. Capping only drops digits when the operands are far
                    // enough apart that one strictly dominates, so an exact cancellation here carries no sticky tail
                    // and yields +0 under round-to-nearest.
                    return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(false, TValue.Zero, commonExponent);
                }

                if (comparison > 0)
                {
                    WideSubtract(aHigh, aLow, bHigh, bLow, out resultHigh, out resultLow);
                    resultSign = productSign;
                }
                else
                {
                    WideSubtract(bHigh, bLow, aHigh, aLow, out resultHigh, out resultLow);
                    resultSign = addendSign;
                }

                if (sticky)
                {
                    // The dropped tail belongs to the smaller (subtrahend) magnitude, so the exact difference is one
                    // unit smaller with a non-zero fractional remainder retained in the sticky flag for rounding.
                    if (TValue.IsZero(resultLow))
                    {
                        resultHigh -= TValue.One;
                    }

                    resultLow -= TValue.One;
                }
            }

            if (TValue.IsZero(resultHigh) && TValue.IsZero(resultLow) && !sticky)
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(false, TValue.Zero, commonExponent);
            }

            return NumberToDecimalIeee754BitsFromWide<TDecimal, TValue>(resultSign, resultHigh, resultLow, commonExponent, sticky);
        }

        /// <summary>
        /// Divides two IEEE 754 decimal values represented by their raw bit patterns and returns the
        /// bit pattern of the correctly rounded (round-to-nearest, ties-to-even) quotient.
        /// </summary>
        /// <remarks>
        /// The dividend coefficient is scaled up by a power of ten large enough to expose more than the format
        /// precision in significant quotient digits, then long-divided by the divisor coefficient one decimal digit
        /// at a time. The running remainder and the quotient each stay within a single limb, so the division uses only
        /// word-level integer arithmetic. The final remainder determines whether the result is exact; an inexact
        /// result carries a sticky flag into the shared rounding path, while an exact result has its exponent raised
        /// toward the IEEE 754 preferred exponent (the difference of the operand exponents) by discarding trailing
        /// zeros. This mirrors the mathematical behavior of the Intel reference implementation.
        /// </remarks>
        internal static TValue DivideDecimalIeee754<TDecimal, TValue>(TValue left, TValue right)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_div`, `bid64_div`, and `bid128_div` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(left) || TDecimal.IsNaN(right))
            {
                return PropagateNaN<TDecimal, TValue>(left, right);
            }

            // The sign of a quotient is always the exclusive-or of the operand signs, including zeros.
            bool resultSign = TDecimal.IsNegative(left) ^ TDecimal.IsNegative(right);

            if (TDecimal.IsInfinity(left))
            {
                // Infinity divided by infinity is invalid (NaN); infinity divided by any finite value is
                // an infinity carrying the exclusive-or sign.
                if (TDecimal.IsInfinity(right))
                {
                    // An invalid operation produces the canonical quiet NaN, which the Intel reference
                    // emits with a positive sign and empty payload (`NaNMask`), unlike the negative
                    // `TDecimal.NaN` constant.
                    return TDecimal.NaNMask;
                }

                return resultSign ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            if (TDecimal.IsInfinity(right))
            {
                // A finite value divided by infinity is zero with the exclusive-or sign; the preferred
                // exponent is the minimum (the encoder clamps the sub-minimum exponent up to it).
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, TValue.Zero, TDecimal.MinAdjustedExponent);
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(left);
            DecodedDecimalIeee754<TValue> b = UnpackDecimalIeee754<TDecimal, TValue>(right);

            if (TValue.IsZero(b.Significand))
            {
                // Zero divided by zero is invalid (NaN); any other value divided by zero is an infinity
                // carrying the exclusive-or sign (division by zero).
                if (TValue.IsZero(a.Significand))
                {
                    // An invalid operation produces the canonical quiet NaN, which the Intel reference
                    // emits with a positive sign and empty payload (`NaNMask`), unlike the negative
                    // `TDecimal.NaN` constant.
                    return TDecimal.NaNMask;
                }

                return resultSign ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            if (TValue.IsZero(a.Significand))
            {
                // Zero divided by a finite non-zero value is zero. The preferred exponent is the difference
                // of the operand exponents (clamped to the representable range by the encoder).
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, TValue.Zero, a.UnbiasedExponent - b.UnbiasedExponent);
            }

            int dividendDigits = TDecimal.CountDigits(a.Significand);
            int divisorDigits = TDecimal.CountDigits(b.Significand);

            // Scale the dividend up so the quotient exposes at least Precision + 1 significant digits.
            // Because both coefficients have at most Precision digits, this shift is always positive.
            int shift = divisorDigits - dividendDigits + TDecimal.Precision + 1;
            Debug.Assert(shift > 0);

            int quotientExponent = a.UnbiasedExponent - b.UnbiasedExponent - shift;

            // Long-divide `a.Significand * 10^shift` by `b.Significand`, extracting several decimal digits per
            // iteration instead of one. Each step scales the remainder by the largest `10^k` that still fits the
            // limb (chosen from its leading-zero headroom, so `10^k <= 2^LeadingZeroCount(remainder)`) and does a
            // single `DivRem`. The running remainder stays below the divisor and the quotient stays below
            // 10^(Precision + 2), so every intermediate value fits a single limb. The final remainder determines
            // whether the quotient is exact.
            TValue divisor = b.Significand;
            TValue ten = TValue.CreateTruncating(10);
            (TValue quotient, TValue remainder) = TValue.DivRem(a.Significand, divisor);

            int remaining = shift;

            while (remaining > 0)
            {
                // `remainder < divisor <= MaxSignificand`, so it always has enough leading zeros for `k >= 1`.
                // `(lz * 3) / 10 <= lz / log2(10)` keeps `remainder * 10^k` from overflowing the limb, and `k` is
                // clamped to `Precision - 1` (an exponent every `Power10` table is guaranteed to hold) and to the
                // digits still owed.
                int lz = int.CreateTruncating(TValue.LeadingZeroCount(remainder));
                int k = (lz * 3) / 10;

                if (k > remaining)
                {
                    k = remaining;
                }
                if (k > TDecimal.Precision - 1)
                {
                    k = TDecimal.Precision - 1;
                }
                if (k < 1)
                {
                    k = 1;
                }

                TValue pow = TDecimal.Power10(k);
                remainder *= pow;
                (TValue chunk, remainder) = TValue.DivRem(remainder, divisor);
                quotient = (quotient * pow) + chunk;
                remaining -= k;
            }

            bool remainderNonZero = !TValue.IsZero(remainder);

            if (!remainderNonZero)
            {
                // The quotient is exact, so raise its exponent toward the preferred exponent (the difference
                // of the operand exponents) by discarding trailing zeros.
                int idealExponent = a.UnbiasedExponent - b.UnbiasedExponent;

                while (quotientExponent < idealExponent)
                {
                    (TValue stripped, TValue digit) = TValue.DivRem(quotient, ten);

                    if (!TValue.IsZero(digit))
                    {
                        break;
                    }

                    quotient = stripped;
                    quotientExponent++;
                }
            }

            return NumberToDecimalIeee754BitsFromWide<TDecimal, TValue>(resultSign, TValue.Zero, quotient, quotientExponent, remainderNonZero);
        }

        /// <summary>
        /// Computes the truncated remainder (the <c>%</c> operator) of two IEEE 754 decimal values represented by their
        /// raw bit patterns: <c>x - Truncate(x / y) * y</c>, matching the C# floating-point <c>%</c> operator on
        /// <see cref="double"/>/<see cref="float"/>/<see cref="Half"/> (and <em>not</em> the round-to-nearest
        /// IEEE 754 <c>remainder</c> operation).
        /// </summary>
        /// <remarks>
        /// The result carries the sign of the dividend, has magnitude strictly less than <c>|y|</c>, and is always
        /// exact. It is computed at the IEEE 754 preferred exponent <c>min(exp(x), exp(y))</c> by reducing the
        /// dividend coefficient modulo the divisor coefficient. Every intermediate value stays within a single limb:
        /// the running remainder is always below the divisor, so each step scales it up by as many trailing zeros as
        /// keep the product within the integer width (capped at the largest cached power of ten) before taking the
        /// remainder again, stopping once the remainder reaches zero. This mirrors the behavior of the Intel reference
        /// implementation.
        /// </remarks>
        internal static TValue RemainderDecimalIeee754<TDecimal, TValue>(TValue left, TValue right)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>, IMinMaxValue<TValue>
        {
            // This code is based on `bid32_fmod`, `bid64_fmod`, and `bid128_fmod` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(left) || TDecimal.IsNaN(right))
            {
                return PropagateNaN<TDecimal, TValue>(left, right);
            }

            // The remainder always carries the sign of the dividend.
            bool resultSign = TDecimal.IsNegative(left);

            if (TDecimal.IsInfinity(left))
            {
                // Infinity has no finite remainder; the operation is invalid and produces the canonical quiet NaN.
                return TDecimal.NaNMask;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(left);

            if (TDecimal.IsInfinity(right))
            {
                // A finite value has itself as its remainder modulo infinity; re-encode to a canonical form.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, a.Significand, a.UnbiasedExponent);
            }

            DecodedDecimalIeee754<TValue> b = UnpackDecimalIeee754<TDecimal, TValue>(right);

            if (TValue.IsZero(b.Significand))
            {
                // A remainder with a zero divisor is invalid and produces the canonical quiet NaN.
                return TDecimal.NaNMask;
            }

            // The preferred exponent of the remainder is the smaller of the two operand exponents.
            int resultExponent = Math.Min(a.UnbiasedExponent, b.UnbiasedExponent);

            if (TValue.IsZero(a.Significand))
            {
                // Zero modulo any non-zero value is a signed zero at the preferred exponent.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, TValue.Zero, resultExponent);
            }

            TValue remainder;

            if (a.UnbiasedExponent >= b.UnbiasedExponent)
            {
                // Reduce `a.Significand * 10^(ea - eb)` modulo `b.Significand`. The remainder always stays below the
                // divisor, so `remainder * 10^chunk` fits the integer width as long as `10^chunk <= MaxValue / divisor`.
                // Fold that many trailing zeros per step (capped at the largest cached power of ten). Modular
                // arithmetic lets each step absorb several digits at once, so a small divisor reaches the full cached
                // power while a large one folds only a handful. Once the remainder hits zero it stays zero, so stop.
                //
                // TODO: A wider intermediate (as Intel's `bidNN_fmod` uses for Decimal128) would let every step fold
                // the full `Precision` digits regardless of divisor magnitude, shaving the loop count for large gaps.
                remainder = a.Significand % b.Significand;

                int chunk = 1;
                TValue chunkLimit = TValue.MaxValue / b.Significand;

                while ((chunk < TDecimal.Precision - 1) && (TDecimal.Power10(chunk + 1) <= chunkLimit))
                {
                    chunk++;
                }

                for (int gap = a.UnbiasedExponent - b.UnbiasedExponent; (gap > 0) && !TValue.IsZero(remainder); gap -= chunk)
                {
                    int step = Math.Min(chunk, gap);
                    remainder = (remainder * TDecimal.Power10(step)) % b.Significand;
                }
            }
            else
            {
                // The divisor's coefficient is scaled up by `10^(eb - ea)`. When that scaled divisor cannot fit the
                // format precision it necessarily exceeds the dividend coefficient, so the dividend is the remainder.
                int gap = b.UnbiasedExponent - a.UnbiasedExponent;

                if (TDecimal.CountDigits(b.Significand) + gap > TDecimal.Precision)
                {
                    remainder = a.Significand;
                }
                else
                {
                    remainder = a.Significand % (b.Significand * TDecimal.Power10(gap));
                }
            }

            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, remainder, resultExponent);
        }

        /// <summary>
        /// Computes the round-to-nearest IEEE 754 <c>remainder</c> of two decimal values represented by their raw bit
        /// patterns: <c>x - y * RoundToNearestEven(x / y)</c>. Unlike the <c>%</c> operator this rounds the quotient to
        /// the nearest integer (ties to even), so the result magnitude is at most <c>|y| / 2</c> and its sign may differ
        /// from the dividend.
        /// </summary>
        /// <remarks>
        /// The truncated remainder and its integer quotient are formed exactly at the preferred exponent
        /// <c>min(exp(x), exp(y))</c> using the same coefficient reduction as the <c>%</c> operator. When twice the
        /// truncated remainder exceeds the divisor coefficient, or equals it while the quotient is odd, the divisor is
        /// subtracted and the sign flipped to land on the nearest multiple. Only the final reduction step's quotient
        /// determines parity: every earlier partial quotient is scaled by a positive power of ten and is therefore even.
        /// </remarks>
        internal static TValue Ieee754RemainderDecimalIeee754<TDecimal, TValue>(TValue left, TValue right)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>, IMinMaxValue<TValue>
        {
            // This code is based on `bid32_rem`, `bid64_rem`, and `bid128_rem` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(left) || TDecimal.IsNaN(right))
            {
                return PropagateNaN<TDecimal, TValue>(left, right);
            }

            bool resultSign = TDecimal.IsNegative(left);

            if (TDecimal.IsInfinity(left))
            {
                // Infinity has no finite remainder; the operation is invalid and produces the canonical quiet NaN.
                return TDecimal.NaNMask;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(left);

            if (TDecimal.IsInfinity(right))
            {
                // A finite value has itself as its remainder modulo infinity; re-encode to a canonical form.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, a.Significand, a.UnbiasedExponent);
            }

            DecodedDecimalIeee754<TValue> b = UnpackDecimalIeee754<TDecimal, TValue>(right);

            if (TValue.IsZero(b.Significand))
            {
                // A remainder with a zero divisor is invalid and produces the canonical quiet NaN.
                return TDecimal.NaNMask;
            }

            // The preferred exponent of the remainder is the smaller of the two operand exponents.
            int resultExponent = Math.Min(a.UnbiasedExponent, b.UnbiasedExponent);

            if (TValue.IsZero(a.Significand))
            {
                // Zero modulo any non-zero value is a signed zero at the preferred exponent.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, TValue.Zero, resultExponent);
            }

            // `remainder` is the truncated remainder and `divisor` the divisor coefficient, both at the preferred
            // exponent; `quotientIsOdd` carries the parity of the full integer quotient for the ties-to-even rule.
            TValue remainder;
            TValue divisor;
            bool quotientIsOdd;

            if (a.UnbiasedExponent >= b.UnbiasedExponent)
            {
                // Reduce `a.Significand * 10^(ea - eb)` modulo `b.Significand`, folding as many trailing zeros per step
                // as keep the product within the integer width (capped at the largest cached power of ten). Each step
                // tracks its quotient; the parity of the last one equals the parity of the full quotient because the
                // earlier partial quotients are each scaled by a later positive power of ten.
                divisor = b.Significand;

                TValue quotient = a.Significand / b.Significand;
                remainder = a.Significand - (quotient * b.Significand);

                int chunk = 1;
                TValue chunkLimit = TValue.MaxValue / b.Significand;

                while ((chunk < TDecimal.Precision - 1) && (TDecimal.Power10(chunk + 1) <= chunkLimit))
                {
                    chunk++;
                }

                for (int gap = a.UnbiasedExponent - b.UnbiasedExponent; (gap > 0) && !TValue.IsZero(remainder); gap -= chunk)
                {
                    int step = Math.Min(chunk, gap);
                    TValue scaled = remainder * TDecimal.Power10(step);

                    quotient = scaled / b.Significand;
                    remainder = scaled - (quotient * b.Significand);
                }

                quotientIsOdd = !TValue.IsZero(quotient & TValue.One);
            }
            else
            {
                // The divisor is scaled up by `10^(eb - ea)`. Once the scaled divisor has more than one digit beyond the
                // format precision it exceeds twice the dividend, so the dividend is already the nearest remainder.
                int gap = b.UnbiasedExponent - a.UnbiasedExponent;

                if (TDecimal.CountDigits(b.Significand) + gap > TDecimal.Precision + 1)
                {
                    return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, a.Significand, resultExponent);
                }

                // The scaled divisor has at most `Precision + 1` digits. Peel one factor of ten so the cached
                // power-of-ten lookup stays within its table, which only spans exponents below `Precision`.
                divisor = (b.Significand * TDecimal.Power10(gap - 1)) * TDecimal.Power10(1);

                TValue quotient = a.Significand / divisor;
                remainder = a.Significand - (quotient * divisor);
                quotientIsOdd = !TValue.IsZero(quotient & TValue.One);
            }

            // Round the quotient to nearest, ties to even: move to the nearer multiple of the divisor when the truncated
            // remainder is past the halfway point, or exactly halfway with an odd quotient. The subtraction flips the sign.
            TValue twiceRemainder = remainder + remainder;

            if ((twiceRemainder > divisor) || ((twiceRemainder == divisor) && quotientIsOdd))
            {
                remainder = divisor - remainder;
                resultSign = !resultSign;
            }

            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(resultSign, remainder, resultExponent);
        }

        internal static TValue SqrtDecimalIeee754<TDecimal, TValue>(TValue value)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>, IMinMaxValue<TValue>
        {
            // This code is based on `bid32_sqrt`, `bid64_sqrt`, and `bid128_sqrt` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(value))
            {
                return PropagateNaN<TDecimal, TValue>(value, value);
            }

            bool sign = TDecimal.IsNegative(value);

            if (TDecimal.IsInfinity(value))
            {
                // sqrt(+Infinity) is +Infinity; sqrt(-Infinity) is invalid and produces the canonical quiet NaN.
                return sign ? TDecimal.NaNMask : TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(value);

            // The exact result keeps its preferred exponent, floor(e / 2), for both zeros and perfect squares.
            int idealExponent = a.UnbiasedExponent >> 1;

            if (TValue.IsZero(a.Significand))
            {
                // sqrt(+/-0) is a signed zero, preserving the sign per IEEE 754.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, TValue.Zero, idealExponent);
            }

            if (sign)
            {
                // sqrt of a negative, non-zero value is invalid and produces the canonical quiet NaN.
                return TDecimal.NaNMask;
            }

            // Factor the value as coefficient * 10^(2 * idealExponent) by folding one power of ten into the
            // coefficient when the exponent is odd, so its square root is sqrt(coefficient) * 10^idealExponent.
            TValue coefficient = a.Significand;

            if ((a.UnbiasedExponent & 1) != 0)
            {
                coefficient *= TDecimal.Power10(1);
            }

            (TValue exactRoot, bool isPerfectSquare) = WideSqrt<TDecimal, TValue>(TValue.Zero, coefficient);

            if (isPerfectSquare)
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, exactRoot, idealExponent);
            }

            // Otherwise scale the coefficient up by an even power of ten so its integer square root carries
            // Precision + 1 digits: one guard digit past the format precision for a single correct rounding.
            int guard = TDecimal.Precision + 1 - ((TDecimal.CountDigits(coefficient) + 1) / 2);

            TValue high = TValue.Zero;
            TValue low = coefficient;
            WideScaleByPow10<TDecimal, TValue>(ref high, ref low, guard * 2);

            (TValue root, bool exact) = WideSqrt<TDecimal, TValue>(high, low);
            return NumberToDecimalIeee754BitsFromWide<TDecimal, TValue>(sign, TValue.Zero, root, idealExponent - guard, !exact);
        }

        /// <summary>
        /// Rounds a finite value to <paramref name="digits"/> fractional digits under <paramref name="mode"/>.
        /// The value is <c>coefficient * 10^exponent</c>; when its quantum exponent is already at or above
        /// <c>-digits</c> there is nothing to round and it is returned unchanged. Otherwise the digits below
        /// <c>10^(-digits)</c> are discarded and the retained coefficient is incremented per <paramref name="mode"/>.
        /// Every intermediate fits a single limb: the divisor is at most <c>10^(Precision - 1)</c> and dividing by
        /// at least ten keeps the rounded coefficient below <c>MaxSignificand</c>.
        /// </summary>
        internal static TValue RoundDecimalIeee754<TDecimal, TValue>(TValue bits, int digits, MidpointRounding mode)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (digits < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRange_RoundingDigits(nameof(digits));
            }

            if ((uint)mode > (uint)MidpointRounding.ToPositiveInfinity)
            {
                ThrowHelper.ThrowArgumentException_InvalidEnumValue(mode);
            }

            if (TDecimal.IsNaN(bits))
            {
                // Canonicalize so a signaling or out-of-range-payload NaN operand rounds to the canonical quiet NaN.
                return PropagateNaN<TDecimal, TValue>(bits, bits);
            }

            if (TDecimal.IsInfinity(bits))
            {
                // Canonicalize so a non-canonical infinity operand rounds to the canonical infinity.
                return TDecimal.IsNegative(bits) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(bits);
            int targetExponent = -digits;

            if (a.UnbiasedExponent >= targetExponent)
            {
                // The quantum is already at or coarser than the requested precision; nothing is discarded. Re-encode so
                // a non-canonical operand (coefficient above the format maximum, unpacked to zero) is returned canonical.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, a.Significand, a.UnbiasedExponent);
            }

            int drop = targetExponent - a.UnbiasedExponent;
            int coefficientDigits = TValue.IsZero(a.Significand) ? 0 : TDecimal.CountDigits(a.Significand);

            TValue five = TValue.CreateTruncating(5);
            TValue quotient;

            // Sign of (discarded - half quantum): negative below the midpoint, zero at it, positive above it.
            int discardedComparedToHalf;
            bool discardedNonZero;

            if (drop >= coefficientDigits)
            {
                // Every coefficient digit is discarded, so the retained value is zero before rounding.
                quotient = TValue.Zero;

                if (drop > coefficientDigits)
                {
                    // The whole coefficient is strictly less than half of the discarded quantum.
                    discardedComparedToHalf = -1;
                    discardedNonZero = !TValue.IsZero(a.Significand);
                }
                else
                {
                    TValue half = five * TDecimal.Power10(coefficientDigits - 1);
                    discardedComparedToHalf = a.Significand.CompareTo(half);
                    discardedNonZero = true;
                }
            }
            else
            {
                TValue divisor = TDecimal.Power10(drop);
                TValue discarded;
                (quotient, discarded) = TValue.DivRem(a.Significand, divisor);

                TValue half = five * TDecimal.Power10(drop - 1);
                discardedComparedToHalf = discarded.CompareTo(half);
                discardedNonZero = !TValue.IsZero(discarded);
            }

            bool roundAwayFromZero = mode switch
            {
                MidpointRounding.ToEven => (discardedComparedToHalf > 0) || ((discardedComparedToHalf == 0) && !TValue.IsZero(quotient & TValue.One)),
                MidpointRounding.AwayFromZero => discardedComparedToHalf >= 0,
                MidpointRounding.ToZero => false,
                MidpointRounding.ToNegativeInfinity => discardedNonZero && a.Signed,
                MidpointRounding.ToPositiveInfinity => discardedNonZero && !a.Signed,
                _ => throw new UnreachableException(),
            };

            if (roundAwayFromZero)
            {
                quotient += TValue.One;
            }

            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, quotient, targetExponent);
        }

        /// <summary>
        /// Computes the integer base-10 logarithm of a value: the exponent of its most significant digit. The special
        /// cases match <see cref="Math.ILogB(double)"/>, reporting <see cref="int.MinValue"/> for zero and
        /// <see cref="int.MaxValue"/> for both NaN and infinity.
        /// </summary>
        internal static int ILogBDecimalIeee754<TDecimal, TValue>(TValue bits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (!TDecimal.IsFinite(bits))
            {
                return int.MaxValue;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(bits);

            if (TValue.IsZero(a.Significand))
            {
                return int.MinValue;
            }

            return a.UnbiasedExponent + TDecimal.CountDigits(a.Significand) - 1;
        }

        /// <summary>
        /// Multiplies a value by <c>10^<paramref name="n"/></c>. A surplus exponent is absorbed into trailing zeros of
        /// the coefficient while it still fits the format precision; anything beyond that overflows to a signed infinity.
        /// A deficit exponent rounds the coefficient (to nearest, ties to even) up to the minimum quantum, underflowing
        /// gradually to a subnormal or a signed zero.
        /// </summary>
        internal static TValue ScaleBDecimalIeee754<TDecimal, TValue>(TValue bits, int n)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_scalbn`, `bid64_scalbn`, and `bid128_scalbn` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(bits))
            {
                return PropagateNaN<TDecimal, TValue>(bits, bits);
            }

            if (TDecimal.IsInfinity(bits))
            {
                // Canonicalize so a non-canonical infinity operand scales to the canonical infinity.
                return TDecimal.IsNegative(bits) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(bits);
            long exponent = (long)a.UnbiasedExponent + n;

            if (TValue.IsZero(a.Significand))
            {
                // Zero carries no significant digits, so the quantum simply clamps into the representable range.
                int zeroExponent = (int)Math.Clamp(exponent, TDecimal.MinAdjustedExponent, TDecimal.MaxAdjustedExponent);
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, TValue.Zero, zeroExponent);
            }

            if (exponent > TDecimal.MaxAdjustedExponent)
            {
                // Absorb the surplus into trailing zeros while the coefficient stays within the format precision.
                long surplus = exponent - TDecimal.MaxAdjustedExponent;

                if (surplus <= TDecimal.Precision - TDecimal.CountDigits(a.Significand))
                {
                    TValue significand = a.Significand * TDecimal.Power10((int)surplus);
                    return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, significand, TDecimal.MaxAdjustedExponent);
                }

                return a.Signed ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            if (exponent < TDecimal.MinAdjustedExponent)
            {
                // Raise the quantum to the minimum by discarding low-order digits, rounding to nearest with ties to even.
                long drop = TDecimal.MinAdjustedExponent - exponent;
                int coefficientDigits = TDecimal.CountDigits(a.Significand);

                if (drop > coefficientDigits)
                {
                    // Even the most significant digit sits below half the minimum quantum, so the result is a signed zero.
                    return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, TValue.Zero, TDecimal.MinAdjustedExponent);
                }

                TValue five = TValue.CreateTruncating(5);
                TValue quotient;
                int discardedComparedToHalf;

                if (drop == coefficientDigits)
                {
                    // The entire coefficient is discarded; compare it against half of the discarded quantum.
                    quotient = TValue.Zero;
                    TValue half = five * TDecimal.Power10(coefficientDigits - 1);
                    discardedComparedToHalf = a.Significand.CompareTo(half);
                }
                else
                {
                    TValue divisor = TDecimal.Power10((int)drop);
                    quotient = a.Significand / divisor;
                    TValue discarded = a.Significand - (quotient * divisor);
                    TValue half = five * TDecimal.Power10((int)drop - 1);
                    discardedComparedToHalf = discarded.CompareTo(half);
                }

                if ((discardedComparedToHalf > 0) || ((discardedComparedToHalf == 0) && !TValue.IsZero(quotient & TValue.One)))
                {
                    quotient += TValue.One;
                }

                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, quotient, TDecimal.MinAdjustedExponent);
            }

            // The shifted quantum is already representable, so the coefficient is preserved exactly.
            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, a.Significand, (int)exponent);
        }

        /// <summary>
        /// Re-expresses <paramref name="x"/> with the quantum (exponent) of <paramref name="y"/>, rounding the
        /// coefficient to nearest with ties to even (IEEE 754-2019 §5.3.2 <c>quantize</c>). The numeric value of
        /// <paramref name="y"/> is otherwise unused. A NaN operand propagates (<paramref name="x"/> before
        /// <paramref name="y"/>); one infinite and one finite operand is invalid and yields a quiet NaN, while two
        /// infinities keep the sign of <paramref name="x"/>. When the requested quantum cannot represent the value
        /// within the format precision the result is a quiet NaN.
        /// </summary>
        internal static TValue QuantizeDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_quantize`, `bid64_quantize`, and `bid128_quantize` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(x) || TDecimal.IsNaN(y))
            {
                // Propagate the first NaN operand (x before y), canonicalized to a quiet NaN.
                return PropagateNaN<TDecimal, TValue>(x, y);
            }

            if (TDecimal.IsInfinity(x) || TDecimal.IsInfinity(y))
            {
                if (TDecimal.IsInfinity(x) && TDecimal.IsInfinity(y))
                {
                    // Two infinities share a quantum; the result keeps the sign of x.
                    return TDecimal.IsNegative(x) ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
                }

                // One infinite and one finite operand cannot share a quantum, so the result is invalid.
                return TDecimal.NaNMask;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(x);
            int targetExponent = UnpackDecimalIeee754<TDecimal, TValue>(y).UnbiasedExponent;

            if (TValue.IsZero(a.Significand))
            {
                // Zero carries no significant digits, so it simply adopts the requested quantum.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, TValue.Zero, targetExponent);
            }

            int coefficientDigits = TDecimal.CountDigits(a.Significand);

            if (targetExponent <= a.UnbiasedExponent)
            {
                // A quantum at or below the current one only scales the coefficient up; it is exact unless the
                // scaled coefficient would exceed the format precision, in which case the value is unrepresentable.
                int shift = a.UnbiasedExponent - targetExponent;

                if (coefficientDigits + shift > TDecimal.Precision)
                {
                    return TDecimal.NaNMask;
                }

                TValue significand = a.Significand * TDecimal.Power10(shift);
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, significand, targetExponent);
            }

            // A coarser quantum discards low-order digits; rounding away never overflows the precision because the
            // magnitude only shrinks.
            int drop = targetExponent - a.UnbiasedExponent;
            TValue five = TValue.CreateTruncating(5);
            TValue quotient;
            int discardedComparedToHalf;

            if (drop >= coefficientDigits)
            {
                quotient = TValue.Zero;

                if (drop > coefficientDigits)
                {
                    // The whole coefficient is strictly below half of the discarded quantum.
                    discardedComparedToHalf = -1;
                }
                else
                {
                    TValue half = five * TDecimal.Power10(coefficientDigits - 1);
                    discardedComparedToHalf = a.Significand.CompareTo(half);
                }
            }
            else
            {
                TValue divisor = TDecimal.Power10(drop);
                TValue discarded;
                (quotient, discarded) = TValue.DivRem(a.Significand, divisor);

                TValue half = five * TDecimal.Power10(drop - 1);
                discardedComparedToHalf = discarded.CompareTo(half);
            }

            if ((discardedComparedToHalf > 0) || ((discardedComparedToHalf == 0) && !TValue.IsZero(quotient & TValue.One)))
            {
                quotient += TValue.One;
            }

            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, quotient, targetExponent);
        }

        /// <summary>
        /// Returns the quantum of <paramref name="bits"/>: <c>1 × 10^exp</c> sharing its exponent (IEEE 754-2019
        /// §5.3.2 <c>quantum</c>). The result is always positive. Infinity yields positive infinity and NaN
        /// propagates, canonicalized to a quiet NaN.
        /// </summary>
        internal static TValue QuantumDecimalIeee754<TDecimal, TValue>(TValue bits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_quantum`, `bid64_quantum`, and `bid128_quantum` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(bits))
            {
                return PropagateNaN<TDecimal, TValue>(bits, bits);
            }

            if (TDecimal.IsInfinity(bits))
            {
                return TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(bits);
            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(signed: false, TValue.One, a.UnbiasedExponent);
        }

        /// <summary>
        /// Determines whether <paramref name="x"/> and <paramref name="y"/> have the same quantum (exponent), following
        /// IEEE 754-2019 §5.7.3 <c>sameQuantum</c>. Two NaNs share a quantum and two infinities share a quantum; any
        /// other pairing that involves a NaN or infinity does not. No exception is ever signaled.
        /// </summary>
        internal static bool SameQuantumDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            bool xNaN = TDecimal.IsNaN(x);
            bool yNaN = TDecimal.IsNaN(y);

            if (xNaN || yNaN)
            {
                return xNaN && yNaN;
            }

            bool xInfinity = TDecimal.IsInfinity(x);
            bool yInfinity = TDecimal.IsInfinity(y);

            if (xInfinity || yInfinity)
            {
                return xInfinity && yInfinity;
            }

            return UnpackDecimalIeee754<TDecimal, TValue>(x).UnbiasedExponent == UnpackDecimalIeee754<TDecimal, TValue>(y).UnbiasedExponent;
        }

        /// <summary>
        /// Returns the least value that compares greater than <paramref name="bits"/> (IEEE 754 <c>nextUp</c>). NaN is
        /// returned unchanged, positive infinity is its own successor, and negative infinity steps to the most negative
        /// finite value.
        /// </summary>
        internal static TValue BitIncrementDecimalIeee754<TDecimal, TValue>(TValue bits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This code is based on `bid32_nextup`, `bid64_nextup`, and `bid128_nextup` from Intel(R) Decimal Floating-Point Math Library
            // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
            //
            // Licensed under the BSD 3-Clause "New" or "Revised" License
            // See THIRD-PARTY-NOTICES.TXT for the full license text

            if (TDecimal.IsNaN(bits))
            {
                return PropagateNaN<TDecimal, TValue>(bits, bits);
            }

            if (TDecimal.IsInfinity(bits))
            {
                return TDecimal.IsNegative(bits)
                    ? DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(signed: true, TDecimal.MaxSignificand, TDecimal.MaxAdjustedExponent)
                    : TDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> a = UnpackDecimalIeee754<TDecimal, TValue>(bits);

            if (TValue.IsZero(a.Significand))
            {
                // The successor of any zero is the smallest positive subnormal.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(signed: false, TValue.One, TDecimal.MinAdjustedExponent);
            }

            int exponent = a.UnbiasedExponent;

            if (!a.Signed && (a.Significand == TDecimal.MaxSignificand) && (exponent == TDecimal.MaxAdjustedExponent))
            {
                // The successor of the largest finite value is positive infinity.
                return TDecimal.PositiveInfinity;
            }

            if (a.Signed && (a.Significand == TValue.One) && (exponent == TDecimal.MinAdjustedExponent))
            {
                // The successor of the smallest negative subnormal is negative zero.
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(signed: true, TValue.Zero, TDecimal.MinAdjustedExponent);
            }

            // Pad the coefficient toward the minimum quantum (bounded by the precision and the minimum exponent) so a
            // single ulp is the smallest representable step at this magnitude.
            TValue significand = a.Significand;
            int padding = Math.Min(TDecimal.Precision - TDecimal.CountDigits(significand), exponent - TDecimal.MinAdjustedExponent);

            if (padding > 0)
            {
                significand *= TDecimal.Power10(padding);
                exponent -= padding;
            }

            if (!a.Signed)
            {
                // Stepping away from zero adds one ulp, carrying into the next exponent at the precision boundary.
                significand += TValue.One;

                if (significand > TDecimal.MaxSignificand)
                {
                    significand = TDecimal.Power10(TDecimal.Precision - 1);
                    exponent++;
                }
            }
            else
            {
                // Stepping toward zero subtracts one ulp, borrowing from the next exponent at the precision boundary.
                significand -= TValue.One;

                if ((significand == (TDecimal.Power10(TDecimal.Precision - 1) - TValue.One)) && (exponent != TDecimal.MinAdjustedExponent))
                {
                    significand = TDecimal.MaxSignificand;
                    exponent--;
                }
            }

            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(a.Signed, significand, exponent);
        }

        /// <summary>
        /// Returns the greatest value that compares less than <paramref name="bits"/> (IEEE 754 <c>nextDown</c>),
        /// computed from the successor identity <c>nextDown(x) = -nextUp(-x)</c>.
        /// </summary>
        internal static TValue BitDecrementDecimalIeee754<TDecimal, TValue>(TValue bits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return BitIncrementDecimalIeee754<TDecimal, TValue>(bits ^ TDecimal.SignMask) ^ TDecimal.SignMask;
        }

        /// <summary>
        /// Computes the scale factor <c>10^<paramref name="exponent"/></c> used to align addition operands. Exponents
        /// within the format's <c>Power10</c> lookup range (<c>0..Precision - 1</c>) come straight from that table,
        /// matching the existing parsing/formatting paths. The slightly larger alignment exponents
        /// (<c>Precision..Precision + 2</c>, which the table does not cover) reduce the exponent by the largest table
        /// entry each iteration and finish with a single lookup for the remainder. The result always fits a single limb
        /// for every supported format.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static TValue AlignmentScaleFactor<TDecimal, TValue>(int exponent)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            int highestTableExponent = TDecimal.Precision - 1;
            TValue largest = TDecimal.Power10(highestTableExponent);
            TValue result = TValue.One;

            while (exponent > highestTableExponent)
            {
                result *= largest;
                exponent -= highestTableExponent;
            }

            return result * TDecimal.Power10(exponent);
        }

        /// <summary>
        /// Computes the full (double-width) product of two significands as a pair of <typeparamref name="TValue"/>
        /// limbs (<paramref name="high"/> holds the more significant half). The product of two coefficients can
        /// require up to twice the format precision, which always fits in two limbs of the underlying integer width.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static void WideMultiply<TValue>(TValue left, TValue right, out TValue high, out TValue low)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // For the 32-bit and 64-bit formats the full product fits in a single wider C# integer (ulong and
            // UInt128 respectively), so it comes from one native multiply. The 128-bit format has no wider
            // native type and uses the schoolbook half-limb decomposition below.
            if (typeof(TValue) == typeof(uint))
            {
                ulong product = (ulong)uint.CreateTruncating(left) * uint.CreateTruncating(right);
                high = TValue.CreateTruncating(product >> 32);
                low = TValue.CreateTruncating(product);
                return;
            }
            else if (typeof(TValue) == typeof(ulong))
            {
                UInt128 product = (UInt128)ulong.CreateTruncating(left) * ulong.CreateTruncating(right);
                high = TValue.CreateTruncating(product >> 64);
                low = TValue.CreateTruncating(product);
                return;
            }

            int bits = TValue.Zero.GetByteCount() * 8;
            int half = bits / 2;
            TValue lowMask = (TValue.One << half) - TValue.One;

            // When both operands fit in the low half their exact product fits in a single TValue, so one
            // native multiply replaces the four-multiply schoolbook decomposition. This is the common case
            // for the 128-bit format, whose coefficients fit in the low 64 bits at up to ~19 digits.
            if (TValue.IsZero((left | right) >> half))
            {
                high = TValue.Zero;
                low = left * right;
                return;
            }

            TValue leftLow = left & lowMask;
            TValue leftHigh = left >> half;
            TValue rightLow = right & lowMask;
            TValue rightHigh = right >> half;

            TValue lowLow = leftLow * rightLow;
            TValue lowHigh = leftLow * rightHigh;
            TValue highLow = leftHigh * rightLow;
            TValue highHigh = leftHigh * rightHigh;

            TValue cross = (lowLow >> half) + (lowHigh & lowMask) + (highLow & lowMask);

            low = (lowLow & lowMask) | ((cross & lowMask) << half);
            high = highHigh + (lowHigh >> half) + (highLow >> half) + (cross >> half);
        }

        /// <summary>
        /// Multiplies the double-width value in (<paramref name="high"/>, <paramref name="low"/>) by a single-limb
        /// <paramref name="factor"/> in place. The caller guarantees the scaled result still fits two limbs.
        /// </summary>
        private static void WideMultiplyByLimb<TValue>(ref TValue high, ref TValue low, TValue factor)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            WideMultiply(low, factor, out TValue lowHigh, out TValue lowLow);
            WideMultiply(high, factor, out TValue highHigh, out TValue highLow);

            TValue newHigh = highLow + lowHigh;

            // The result fits two limbs by construction: the high limb never carries out and `high * factor` never
            // spills past the second limb.
            Debug.Assert(TValue.IsZero(highHigh));
            Debug.Assert(newHigh >= highLow);

            high = newHigh;
            low = lowLow;
        }

        /// <summary>
        /// Scales the double-width value in (<paramref name="high"/>, <paramref name="low"/>) up by
        /// <c>10^<paramref name="power"/></c> in place, multiplying by the largest single-limb power of ten each step.
        /// The caller guarantees the scaled result still fits two limbs.
        /// </summary>
        private static void WideScaleByPow10<TDecimal, TValue>(ref TValue high, ref TValue low, int power)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            int highestTableExponent = TDecimal.Precision - 1;

            while (power > 0)
            {
                int chunk = Math.Min(power, highestTableExponent);
                WideMultiplyByLimb(ref high, ref low, TDecimal.Power10(chunk));
                power -= chunk;
            }
        }

        /// <summary>
        /// Drops the <paramref name="dropCount"/> least-significant decimal digits from the double-width value in
        /// (<paramref name="high"/>, <paramref name="low"/>) in place, folding every dropped digit into
        /// <paramref name="sticky"/>. Used to align an addition operand whose low digits fall below the retained window,
        /// where all dropped digits lie below the rounding position and therefore only contribute stickiness.
        /// </summary>
        private static void WideDropLowDigits<TValue>(ref TValue high, ref TValue low, int dropCount, ref bool sticky)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            int chunkPower = SinglePassPow10<TValue>(out TValue chunkDivisor);

            while (dropCount > 0)
            {
                if (TValue.IsZero(high) && TValue.IsZero(low))
                {
                    break;
                }

                int step = Math.Min(dropCount, chunkPower);
                TValue divisor = (step == chunkPower) ? chunkDivisor : WidePow10<TValue>(step);

                sticky |= !TValue.IsZero(WideDivideByPow10(ref high, ref low, divisor));
                dropCount -= step;
            }
        }

        /// <summary>
        /// Aligns the double-width coefficient in (<paramref name="high"/>, <paramref name="low"/>), whose value is
        /// <c>coefficient·10^<paramref name="exponent"/></c>, to <paramref name="commonExponent"/> in place. A larger
        /// exponent scales the coefficient up (exact); a smaller exponent drops the low digits into
        /// <paramref name="sticky"/>.
        /// </summary>
        private static void AlignWideToCommonExponent<TDecimal, TValue>(ref TValue high, ref TValue low, int exponent, int commonExponent, ref bool sticky)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (exponent > commonExponent)
            {
                WideScaleByPow10<TDecimal, TValue>(ref high, ref low, exponent - commonExponent);
            }
            else if (exponent < commonExponent)
            {
                WideDropLowDigits(ref high, ref low, commonExponent - exponent, ref sticky);
            }
        }

        /// <summary>
        /// Adds the double-width magnitudes (<paramref name="leftHigh"/>, <paramref name="leftLow"/>) and
        /// (<paramref name="rightHigh"/>, <paramref name="rightLow"/>), which the caller guarantees cannot carry
        /// out of the high limb.
        /// </summary>
        private static void WideAdd<TValue>(TValue leftHigh, TValue leftLow, TValue rightHigh, TValue rightLow, out TValue high, out TValue low)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            low = leftLow + rightLow;
            high = leftHigh + rightHigh;

            if (low < leftLow)
            {
                high += TValue.One;
            }
        }

        /// <summary>
        /// Compares two double-width magnitudes, returning a negative value, zero, or a positive value according to
        /// whether the first is less than, equal to, or greater than the second.
        /// </summary>
        private static int WideCompare<TValue>(TValue leftHigh, TValue leftLow, TValue rightHigh, TValue rightLow)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            int highComparison = leftHigh.CompareTo(rightHigh);
            return highComparison != 0 ? highComparison : leftLow.CompareTo(rightLow);
        }

        /// <summary>
        /// Subtracts the double-width magnitude (<paramref name="rightHigh"/>, <paramref name="rightLow"/>) from
        /// (<paramref name="leftHigh"/>, <paramref name="leftLow"/>), which the caller guarantees is the larger.
        /// </summary>
        private static void WideSubtract<TValue>(TValue leftHigh, TValue leftLow, TValue rightHigh, TValue rightLow, out TValue high, out TValue low)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            high = leftHigh - rightHigh;

            if (leftLow < rightLow)
            {
                high -= TValue.One;
            }

            low = leftLow - rightLow;
        }

        /// <summary>
        /// Gets the largest power of ten that a single <see cref="WideDivideByPow10{TValue}"/> pass can strip,
        /// returning its exponent and, in <paramref name="divisor"/>, its value.
        /// </summary>
        /// <remarks>
        /// The bound is <c>10^k &lt;= 2^(bits / 2)</c>, which is what keeps the running remainder times the
        /// half-width base inside <typeparamref name="TValue"/>: <c>10^4</c> for a 32-bit limb, <c>10^9</c> for a
        /// 64-bit limb, and <c>10^19</c> for a 128-bit limb.
        /// </remarks>
        private static int SinglePassPow10<TValue>(out TValue divisor)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue ten = TValue.CreateTruncating(10);
            TValue limit = (TValue.One << ((TValue.Zero.GetByteCount() * 8) / 2)) / ten;

            divisor = TValue.One;
            int power = 0;

            while (divisor <= limit)
            {
                divisor *= ten;
                power++;
            }

            return power;
        }

        /// <summary>
        /// Computes <c>10^<paramref name="power"/></c>, which the caller guarantees fits a single limb.
        /// </summary>
        private static TValue WidePow10<TValue>(int power)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue ten = TValue.CreateTruncating(10);
            TValue result = TValue.One;

            for (int i = 0; i < power; i++)
            {
                result *= ten;
            }

            return result;
        }

        /// <summary>
        /// Divides the double-width value in (<paramref name="high"/>, <paramref name="low"/>) by
        /// <paramref name="divisor"/> in place, returning the discarded low-order digits. Used to strip low-order
        /// digits during rounding, a whole <see cref="SinglePassPow10{TValue}"/> chunk of them at a time.
        /// </summary>
        /// <remarks>
        /// The rounding paths only reach this helper with a two-limb value for the 128-bit format: the 32-bit and
        /// 64-bit formats widen the limb pair to a single native integer and divide directly (see
        /// <see cref="DropDigits{TDecimal, TValue}"/> and <see cref="WideDigitCount{TDecimal, TValue}"/>). Addition
        /// reaches it for every format through <see cref="WideDropLowDigits{TValue}"/>. The Intel reference
        /// implementation avoids hardware division here by multiplying with precomputed reciprocals of powers of ten
        /// (e.g. <c>bid_reciprocals10_64</c>) and shifting; this helper instead uses direct integer division for
        /// simplicity, and adopting the reciprocal-multiply tables is a possible future performance optimization.
        /// </remarks>
        private static TValue WideDivideByPow10<TValue>(ref TValue high, ref TValue low, TValue divisor)
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TValue.IsZero(high))
            {
                (TValue quotient, TValue remainder) = TValue.DivRem(low, divisor);
                low = quotient;
                return remainder;
            }

            int bits = TValue.Zero.GetByteCount() * 8;
            int half = bits / 2;
            TValue lowMask = (TValue.One << half) - TValue.One;
            TValue baseValue = TValue.One << half;

            // Long division of the four half-width limbs (most significant first). Because the running remainder
            // stays below the divisor, which `SinglePassPow10` caps at `baseValue`, the intermediate
            // `remainder * baseValue + limb` never exceeds the integer width.
            TValue rem = TValue.Zero;
            (TValue q3, rem) = TValue.DivRem((rem * baseValue) + (high >> half), divisor);
            (TValue q2, rem) = TValue.DivRem((rem * baseValue) + (high & lowMask), divisor);
            (TValue q1, rem) = TValue.DivRem((rem * baseValue) + (low >> half), divisor);
            (TValue q0, rem) = TValue.DivRem((rem * baseValue) + (low & lowMask), divisor);

            high = (q3 << half) | q2;
            low = (q1 << half) | q0;
            return rem;
        }

        /// <summary>
        /// Counts the number of decimal digits in the double-width value (<paramref name="high"/>, <paramref name="low"/>),
        /// which must be non-zero.
        /// </summary>
        private static int WideDigitCount<TDecimal, TValue>(TValue high, TValue low)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // When the high limb is zero the value fits in a single limb and the digit count comes straight
            // from the per-format helper, avoiding a promotion to the wider integer type.
            if (TValue.IsZero(high))
            {
                return TDecimal.CountDigits(low);
            }

            // For the 32-bit and 64-bit formats the (high, low) limb pair fits in a single wider C# integer
            // (ulong and UInt128 respectively), so the digit count comes straight from the existing helpers
            // instead of stripping the high limb a digit at a time. The 128-bit format has no wider native
            // type and falls back to the generic limb loop below.
            if (typeof(TValue) == typeof(uint))
            {
                ulong wide = ((ulong)uint.CreateTruncating(high) << 32) | uint.CreateTruncating(low);
                return FormattingHelpers.CountDigits(wide);
            }
            else if (typeof(TValue) == typeof(ulong))
            {
                UInt128 wide = ((UInt128)ulong.CreateTruncating(high) << 64) | ulong.CreateTruncating(low);
                return FormattingHelpers.CountDigits(wide);
            }

            int count = 0;
            int chunkPower = SinglePassPow10<TValue>(out TValue chunkDivisor);

            // A non-zero high limb means the value spans at least the full limb width, which is more digits than a
            // single pass strips, so the count stays additive across each pass.
            while (!TValue.IsZero(high))
            {
                WideDivideByPow10(ref high, ref low, chunkDivisor);
                count += chunkPower;
            }

            return count + TDecimal.CountDigits(low);
        }

        /// <summary>
        /// Computes the integer square root of the double-width value (<paramref name="high"/>, <paramref name="low"/>),
        /// returning <c>floor(sqrt(value))</c> and whether the value is a perfect square. The root fits a single limb
        /// because the input spans at most twice the limb width, so its square root spans at most one.
        /// </summary>
        private static (TValue Root, bool IsExact) WideSqrt<TDecimal, TValue>(TValue high, TValue low)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // Binary long-division square root: consume the input two bits at a time from the most-significant end,
            // appending a bit to the root when the trial subtrahend `2 * root + 1` fits the running remainder. The
            // remainder stays below `2 * root`, and the coefficients here never exceed Precision + 1 digits, so the
            // root, remainder, and trial subtrahend all fit a single limb even for the 128-bit format.
            int limbBits = TValue.Zero.GetByteCount() * 8;
            TValue three = TValue.CreateTruncating(3);

            TValue root = TValue.Zero;
            TValue remainder = TValue.Zero;

            for (int pair = limbBits - 1; pair >= 0; pair--)
            {
                int shift = pair * 2;
                TValue twoBits = (shift >= limbBits) ? ((high >> (shift - limbBits)) & three) : ((low >> shift) & three);

                remainder = (remainder << 2) | twoBits;
                root <<= 1;

                TValue trial = (root << 1) | TValue.One;

                if (remainder >= trial)
                {
                    remainder -= trial;
                    root += TValue.One;
                }
            }

            return (root, TValue.IsZero(remainder));
        }

        /// <summary>
        /// Removes the <paramref name="dropCount"/> least-significant decimal digits from the double-width value,
        /// returning the retained significand (which fits in a single limb). The most-significant removed digit is
        /// returned in <paramref name="roundDigit"/> for the rounding decision; all lower removed digits are folded
        /// into <paramref name="sticky"/>.
        /// </summary>
        private static TValue DropDigits<TDecimal, TValue>(ref TValue high, ref TValue low, int dropCount, ref bool sticky, out int roundDigit)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            roundDigit = 0;

            if (dropCount == 0)
            {
                return low;
            }

            // When the high limb is zero the value already fits in a single limb, so the digits are dropped
            // with one native TValue division instead of promoting to a wider integer (a software 128-bit
            // divide for the 64-bit format) or stripping a digit at a time (the 128-bit format). The removed
            // low-order digits land in `removed`: its most-significant digit is the rounding digit and the rest
            // folds into the sticky bit. `dropCount` is bounded by the precision so both powers stay in-table.
            if (TValue.IsZero(high) && (dropCount < TDecimal.Precision))
            {
                (TValue quotient, TValue removed) = TDecimal.DivRemPow10(low, dropCount);
                low = quotient;

                if (dropCount == 1)
                {
                    // The removed portion is a single digit, which is the rounding digit itself.
                    roundDigit = int.CreateTruncating(removed);
                }
                else
                {
                    (TValue rd, TValue rest) = TValue.DivRem(removed, TDecimal.Power10(dropCount - 1));
                    roundDigit = int.CreateTruncating(rd);
                    sticky |= !TValue.IsZero(rest);
                }

                return low;
            }

            // For the 32-bit and 64-bit formats the (high, low) limb pair fits in a single wider C# integer
            // (ulong and UInt128 respectively), so the requested digits are dropped with one native division
            // by 10^dropCount rather than a per-digit long-division loop. The remainder holds the removed
            // low-order digits: its most-significant digit is the rounding digit and everything below it is
            // folded into the sticky bit. The 128-bit format has no wider native type and uses the generic
            // limb loop below.
            if (typeof(TValue) == typeof(uint))
            {
                ulong wide = ((ulong)uint.CreateTruncating(high) << 32) | uint.CreateTruncating(low);

                ulong scale = 1;
                for (int i = 1; i < dropCount; i++)
                {
                    scale *= 10;
                }
                ulong power = scale * 10;

                (ulong quotient, ulong remainder) = ulong.DivRem(wide, power);
                roundDigit = int.CreateTruncating(remainder / scale);
                sticky |= (remainder % scale) != 0;

                high = TValue.Zero;
                low = TValue.CreateTruncating(quotient);
                return low;
            }
            else if (typeof(TValue) == typeof(ulong))
            {
                UInt128 wide = ((UInt128)ulong.CreateTruncating(high) << 64) | ulong.CreateTruncating(low);

                UInt128 scale = UInt128.One;
                for (int i = 1; i < dropCount; i++)
                {
                    scale *= 10;
                }
                UInt128 power = scale * 10;

                (UInt128 quotient, UInt128 remainder) = UInt128.DivRem(wide, power);
                roundDigit = int.CreateTruncating(remainder / scale);
                sticky |= (remainder % scale) != UInt128.Zero;

                high = TValue.Zero;
                low = TValue.CreateTruncating(quotient);
                return low;
            }

            // Every removed digit below the most-significant one only contributes stickiness, so they come off a
            // whole single-pass chunk at a time; the rounding digit is then stripped on its own.
            int chunkPower = SinglePassPow10<TValue>(out TValue chunkDivisor);
            int remaining = dropCount - 1;

            while (remaining > 0)
            {
                int step = Math.Min(remaining, chunkPower);
                TValue divisor = (step == chunkPower) ? chunkDivisor : WidePow10<TValue>(step);

                sticky |= !TValue.IsZero(WideDivideByPow10(ref high, ref low, divisor));
                remaining -= step;
            }

            roundDigit = int.CreateTruncating(WideDivideByPow10(ref high, ref low, TValue.CreateTruncating(10)));

            Debug.Assert(TValue.IsZero(high));
            return low;
        }

        /// <summary>
        /// Rounds the exact double-width coefficient (<paramref name="high"/>, <paramref name="low"/>) with value
        /// <c>±coefficient·10^<paramref name="exponent"/></c> (plus an optional sub-unit <paramref name="sticky"/> tail)
        /// to the nearest representable IEEE 754 decimal value using round-to-nearest, ties-to-even, and returns its
        /// BID bit pattern. This is the integer-based counterpart of <see cref="NumberToDecimalIeee754Bits{TDecimal, TValue}"/>
        /// used by the arithmetic operators; it mirrors the same exponent-range handling without materializing a digit string.
        /// </summary>
        private static TValue NumberToDecimalIeee754BitsFromWide<TDecimal, TValue>(bool sign, TValue high, TValue low, int exponent, bool sticky)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TValue.IsZero(high) && TValue.IsZero(low))
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, TValue.Zero, exponent);
            }

            int precision = TDecimal.Precision;

            if (exponent > TDecimal.MaxExponent)
            {
                return sign ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            int digitsCount = WideDigitCount<TDecimal, TValue>(high, low);

            if (exponent > TDecimal.MaxAdjustedExponent)
            {
                // The least-significant digit already sits above the largest representable quantum. The value is
                // representable only if the coefficient can be padded with trailing zeros without exceeding the
                // precision; otherwise it overflows to infinity.
                int numberZeroDigits = exponent - TDecimal.MaxAdjustedExponent;

                if (digitsCount + numberZeroDigits > precision)
                {
                    return sign ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
                }

                TValue paddedSignificand = low * TDecimal.Power10(numberZeroDigits);
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, paddedSignificand, TDecimal.MaxAdjustedExponent);
            }

            if (exponent < TDecimal.MinAdjustedExponent)
            {
                int numberDigitsRemove = TDecimal.MinAdjustedExponent - exponent;

                if (numberDigitsRemove > digitsCount)
                {
                    return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, TValue.Zero, TDecimal.MinAdjustedExponent);
                }
                else if (numberDigitsRemove < digitsCount)
                {
                    int numberDigitsRemain = digitsCount - numberDigitsRemove;

                    if (numberDigitsRemain > precision)
                    {
                        // Still above the format precision after shifting to the minimum quantum, so the value is
                        // actually normal. Round to the precision in a single step to avoid a double rounding.
                        numberDigitsRemain = precision;
                    }

                    return RoundWideToSignificand<TDecimal, TValue>(sign, high, low, digitsCount, exponent, numberDigitsRemain, sticky);
                }
                else
                {
                    return RoundWideToZeroOrEpsilon<TDecimal, TValue>(sign, high, low, digitsCount, sticky);
                }
            }

            if (digitsCount > precision)
            {
                int numberDigitsRemove = digitsCount - precision;

                if (exponent + numberDigitsRemove > TDecimal.MaxAdjustedExponent)
                {
                    return sign ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
                }

                return RoundWideToSignificand<TDecimal, TValue>(sign, high, low, digitsCount, exponent, precision, sticky);
            }

            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, low, exponent);
        }

        /// <summary>
        /// Rounds the double-width coefficient to <paramref name="numberDigitsRemain"/> significant digits using
        /// round-to-nearest, ties-to-even, and encodes the result. This is the integer-based counterpart of
        /// <see cref="DecimalIeee754Rounding{TDecimal, TValue}"/>.
        /// </summary>
        private static TValue RoundWideToSignificand<TDecimal, TValue>(bool sign, TValue high, TValue low, int digitsCount, int exponent, int numberDigitsRemain, bool sticky)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            int dropCount = digitsCount - numberDigitsRemain;
            TValue significand = DropDigits<TDecimal, TValue>(ref high, ref low, dropCount, ref sticky, out int roundDigit);
            int resultExponent = exponent + dropCount;

            bool roundUp = (roundDigit > 5)
                || ((roundDigit == 5) && (sticky || TValue.IsOddInteger(significand)));

            if (!roundUp)
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, significand, resultExponent);
            }

            if (significand == TDecimal.MaxSignificand)
            {
                resultExponent += 1;

                if (resultExponent > TDecimal.MaxAdjustedExponent)
                {
                    return sign ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
                }

                significand = TDecimal.Power10(TDecimal.Precision - 1);
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, significand, resultExponent);
            }

            significand += TValue.One;
            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, significand, resultExponent);
        }

        /// <summary>
        /// Rounds a double-width coefficient whose value lies below the minimum quantum to either zero or the
        /// smallest representable subnormal (epsilon), using round-to-nearest, ties-to-even. This is the
        /// integer-based counterpart of <see cref="RoundToZeroOrEpsilon{TDecimal, TValue}"/>.
        /// </summary>
        private static TValue RoundWideToZeroOrEpsilon<TDecimal, TValue>(bool sign, TValue high, TValue low, int digitsCount, bool sticky)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue lead = DropDigits<TDecimal, TValue>(ref high, ref low, digitsCount - 1, ref sticky, out int roundDigit);
            bool restNonZero = sticky || (roundDigit != 0);
            int leadDigit = int.CreateTruncating(lead);

            TValue significand = ((leadDigit > 5) || ((leadDigit == 5) && restNonZero)) ? TValue.One : TValue.Zero;
            return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, significand, TDecimal.MinAdjustedExponent);
        }

        internal static TValue AbsDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return decimalBits & ~TDecimal.SignMask;
        }

        /// <summary>
        /// Classifies a value as a non-integer (<c>-1</c>), an even integer (<c>0</c>), or an odd integer (<c>1</c>).
        /// A finite value is an integer when its significand is evenly divisible by the power of ten implied by a
        /// negative exponent; parity is that of the resulting integer coefficient.
        /// </summary>
        private static int ClassifyIntegerParityDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (!TDecimal.IsFinite(decimalBits))
            {
                return -1;
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(decimalBits);
            TValue significand = decoded.Significand;

            if (TValue.IsZero(significand))
            {
                // Zero is an even integer.
                return 0;
            }

            int exponent = decoded.UnbiasedExponent;

            if (exponent >= 1)
            {
                // significand * 10^exponent carries a factor of ten and is therefore even.
                return 0;
            }

            if (exponent == 0)
            {
                return int.CreateTruncating(significand & TValue.One);
            }

            // A negative exponent is an integer only when the significand is evenly divisible by 10^(-exponent).
            // The significand has at most Precision digits, so dropping Precision or more digits never divides evenly.
            int dropCount = -exponent;

            if (dropCount >= TDecimal.Precision)
            {
                return -1;
            }

            (TValue quotient, TValue remainder) = TDecimal.DivRemPow10(significand, dropCount);

            if (!TValue.IsZero(remainder))
            {
                return -1;
            }

            return int.CreateTruncating(quotient & TValue.One);
        }

        internal static bool IsIntegerDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return ClassifyIntegerParityDecimalIeee754<TDecimal, TValue>(decimalBits) >= 0;
        }

        internal static bool IsEvenIntegerDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return ClassifyIntegerParityDecimalIeee754<TDecimal, TValue>(decimalBits) == 0;
        }

        internal static bool IsOddIntegerDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return ClassifyIntegerParityDecimalIeee754<TDecimal, TValue>(decimalBits) == 1;
        }

        internal static bool IsZeroDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (!TDecimal.IsFinite(decimalBits))
            {
                return false;
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(decimalBits);
            return TValue.IsZero(decoded.Significand);
        }

        // This code is based on `bid32_isCanonical`, `bid64_isCanonical`, and `bid128_isCanonical`
        // from Intel(R) Decimal Floating-Point Math Library
        // Copyright (c) 2007-2025, Intel Corp. All rights reserved.
        //
        // Licensed under the BSD 3-Clause "New" or "Revised" License
        // See THIRD-PARTY-NOTICES.TXT for the full license text
        internal static bool IsCanonicalDecimalIeee754<TDecimal, TValue>(TValue decimalBits, TValue nanReservedMask, TValue nanPayloadMask, TValue maxNaNPayload)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsNaN(decimalBits))
            {
                // A canonical NaN leaves the reserved bits clear and carries a payload within range.
                if ((decimalBits & nanReservedMask) != TValue.Zero)
                {
                    return false;
                }
                return (decimalBits & nanPayloadMask) <= maxNaNPayload;
            }

            if (TDecimal.IsInfinity(decimalBits))
            {
                // A canonical infinity leaves every bit outside the sign and NaN/infinity indicator clear.
                return (decimalBits & ~(TDecimal.SignMask | TDecimal.NaNMask)) == TValue.Zero;
            }

            // A finite value is canonical when its raw coefficient does not exceed the maximum
            // representable significand. The `11` steering form implies the most significant bit,
            // whose combination always overflows the maximum for `Decimal128`.
            TValue significand;

            if ((decimalBits & TDecimal.G0G1Mask) == TDecimal.G0G1Mask)
            {
                significand = (decimalBits & TDecimal.GwPlus4SignificandMask) | TDecimal.MostSignificantBitOfSignificandMask;
            }
            else
            {
                significand = decimalBits & TDecimal.GwPlus2ToGwPlus4SignificandMask;
            }

            return significand <= TDecimal.MaxSignificand;
        }

        /// <summary>
        /// Determines whether a finite non-zero value has an adjusted exponent at or above the minimum normal
        /// exponent. Zero, infinity, and NaN are never normal.
        /// </summary>
        internal static bool IsNormalDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (!TDecimal.IsFinite(decimalBits))
            {
                return false;
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(decimalBits);

            if (TValue.IsZero(decoded.Significand))
            {
                return false;
            }

            int adjustedExponent = decoded.UnbiasedExponent + TDecimal.CountDigits(decoded.Significand) - 1;
            return adjustedExponent >= TDecimal.MinExponent;
        }

        /// <summary>
        /// Determines whether a finite non-zero value has an adjusted exponent below the minimum normal exponent.
        /// Zero, infinity, and NaN are never subnormal.
        /// </summary>
        internal static bool IsSubnormalDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (!TDecimal.IsFinite(decimalBits))
            {
                return false;
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(decimalBits);

            if (TValue.IsZero(decoded.Significand))
            {
                return false;
            }

            int adjustedExponent = decoded.UnbiasedExponent + TDecimal.CountDigits(decoded.Significand) - 1;
            return adjustedExponent < TDecimal.MinExponent;
        }

        // The magnitude helpers match the IEEE 754:2019 maximumMagnitude/minimumMagnitude family. The *Number
        // variants do not propagate NaN; both treat +0 as greater than -0. Comparisons are performed on the
        // absolute (sign-cleared) bit patterns using the existing ordering helpers.

        internal static TValue MaxMagnitudeDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue ax = AbsDecimalIeee754<TDecimal, TValue>(x);
            TValue ay = AbsDecimalIeee754<TDecimal, TValue>(y);

            if (GreaterThanDecimalIeee754<TDecimal, TValue>(ax, ay) || TDecimal.IsNaN(ax))
            {
                return CanonicalizeIfNaN<TDecimal, TValue>(x);
            }

            if (EqualsDecimalIeee754<TDecimal, TValue>(ax, ay))
            {
                return TDecimal.IsNegative(x) ? y : x;
            }

            return CanonicalizeIfNaN<TDecimal, TValue>(y);
        }

        internal static TValue MinMagnitudeDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue ax = AbsDecimalIeee754<TDecimal, TValue>(x);
            TValue ay = AbsDecimalIeee754<TDecimal, TValue>(y);

            if (LessThanDecimalIeee754<TDecimal, TValue>(ax, ay) || TDecimal.IsNaN(ax))
            {
                return CanonicalizeIfNaN<TDecimal, TValue>(x);
            }

            if (EqualsDecimalIeee754<TDecimal, TValue>(ax, ay))
            {
                return TDecimal.IsNegative(x) ? x : y;
            }

            return CanonicalizeIfNaN<TDecimal, TValue>(y);
        }

        internal static TValue MaxMagnitudeNumberDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue ax = AbsDecimalIeee754<TDecimal, TValue>(x);
            TValue ay = AbsDecimalIeee754<TDecimal, TValue>(y);

            if (GreaterThanDecimalIeee754<TDecimal, TValue>(ax, ay) || TDecimal.IsNaN(ay))
            {
                return CanonicalizeIfNaN<TDecimal, TValue>(x);
            }

            if (EqualsDecimalIeee754<TDecimal, TValue>(ax, ay))
            {
                return TDecimal.IsNegative(x) ? y : x;
            }

            return y;
        }

        internal static TValue MinMagnitudeNumberDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            TValue ax = AbsDecimalIeee754<TDecimal, TValue>(x);
            TValue ay = AbsDecimalIeee754<TDecimal, TValue>(y);

            if (LessThanDecimalIeee754<TDecimal, TValue>(ax, ay) || TDecimal.IsNaN(ay))
            {
                return CanonicalizeIfNaN<TDecimal, TValue>(x);
            }

            if (EqualsDecimalIeee754<TDecimal, TValue>(ax, ay))
            {
                return TDecimal.IsNegative(x) ? x : y;
            }

            return y;
        }

        // The Max/Min helpers match the IEEE 754:2019 maximum/minimum family. Max/Min propagate NaN; the *Native
        // variants mirror the greater-than/less-than operators (NaN never compares greater or less, so the second
        // operand wins); the *Number variants drop NaN inputs. All treat +0 as greater than -0.

        internal static TValue MaxDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsNaN(x))
            {
                return PropagateNaN<TDecimal, TValue>(x, x);
            }

            if (TDecimal.IsNaN(y))
            {
                return PropagateNaN<TDecimal, TValue>(y, y);
            }

            if (!EqualsDecimalIeee754<TDecimal, TValue>(x, y))
            {
                return GreaterThanDecimalIeee754<TDecimal, TValue>(x, y) ? x : y;
            }

            return TDecimal.IsNegative(y) ? x : y;
        }

        internal static TValue MinDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsNaN(x))
            {
                return PropagateNaN<TDecimal, TValue>(x, x);
            }

            if (TDecimal.IsNaN(y))
            {
                return PropagateNaN<TDecimal, TValue>(y, y);
            }

            if (!EqualsDecimalIeee754<TDecimal, TValue>(x, y))
            {
                return LessThanDecimalIeee754<TDecimal, TValue>(x, y) ? x : y;
            }

            return TDecimal.IsNegative(x) ? x : y;
        }

        internal static TValue MaxNativeDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return CanonicalizeIfNaN<TDecimal, TValue>(GreaterThanDecimalIeee754<TDecimal, TValue>(x, y) ? x : y);
        }

        internal static TValue MinNativeDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            return CanonicalizeIfNaN<TDecimal, TValue>(LessThanDecimalIeee754<TDecimal, TValue>(x, y) ? x : y);
        }

        internal static TValue MaxNumberDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (!EqualsDecimalIeee754<TDecimal, TValue>(x, y))
            {
                if (!TDecimal.IsNaN(y))
                {
                    return LessThanDecimalIeee754<TDecimal, TValue>(y, x) ? x : y;
                }

                return CanonicalizeIfNaN<TDecimal, TValue>(x);
            }

            return TDecimal.IsNegative(y) ? x : y;
        }

        internal static TValue MinNumberDecimalIeee754<TDecimal, TValue>(TValue x, TValue y)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (!EqualsDecimalIeee754<TDecimal, TValue>(x, y))
            {
                if (!TDecimal.IsNaN(y))
                {
                    return LessThanDecimalIeee754<TDecimal, TValue>(x, y) ? x : y;
                }

                return CanonicalizeIfNaN<TDecimal, TValue>(x);
            }

            return TDecimal.IsNegative(x) ? x : y;
        }

        internal static TValue CopySignDecimalIeee754<TDecimal, TValue>(TValue value, TValue sign)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            // This method must work for all inputs, including NaN, so it operates on the raw bits: clear the sign of
            // value, keep only the sign of sign, then combine them.
            return (value & ~TDecimal.SignMask) | (sign & TDecimal.SignMask);
        }

        internal static int SignDecimalIeee754<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsNaN(decimalBits))
            {
                throw new ArithmeticException(SR.Arithmetic_NaN);
            }

            if (TDecimal.IsFinite(decimalBits) && TValue.IsZero(UnpackDecimalIeee754<TDecimal, TValue>(decimalBits).Significand))
            {
                return 0;
            }

            return ((decimalBits & TDecimal.SignMask) != TValue.Zero) ? -1 : +1;
        }

        // ==================================================================================================
        // Conversions
        // ==================================================================================================

        /// <summary>
        /// Classifies a decimal value for conversion to an integer type: whether it is NaN, an infinity, or a
        /// finite value. For finite values it also returns the sign and the magnitude truncated toward zero.
        /// </summary>
        internal enum DecimalIeee754ToIntegerStatus
        {
            Finite,
            NaN,
            PositiveInfinity,
            NegativeInfinity,
        }

        /// <summary>
        /// Converts the decimal <paramref name="decimalBits"/> to the integer magnitude obtained by truncating
        /// toward zero (the fractional part is discarded). Returns whether the value is finite, an infinity, or
        /// NaN. For finite values, <paramref name="isNegative"/> carries the sign, <paramref name="magnitude"/>
        /// the truncated absolute value, and <paramref name="exceedsUInt128"/> is set when that magnitude does
        /// not fit in <see cref="UInt128"/> (and therefore in no integer type).
        /// </summary>
        private static DecimalIeee754ToIntegerStatus DecimalIeee754ToIntegerMagnitude<TDecimal, TValue>(TValue decimalBits, out bool isNegative, out UInt128 magnitude, out bool exceedsUInt128)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            isNegative = (decimalBits & TDecimal.SignMask) != TValue.Zero;
            magnitude = UInt128.Zero;
            exceedsUInt128 = false;

            if (TDecimal.IsNaN(decimalBits))
            {
                return DecimalIeee754ToIntegerStatus.NaN;
            }

            if (TDecimal.IsInfinity(decimalBits))
            {
                return isNegative ? DecimalIeee754ToIntegerStatus.NegativeInfinity : DecimalIeee754ToIntegerStatus.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(decimalBits);
            isNegative = decoded.Signed;

            UInt128 significand = UInt128.CreateTruncating(decoded.Significand);
            int exponent = decoded.UnbiasedExponent;

            if (significand == UInt128.Zero)
            {
                return DecimalIeee754ToIntegerStatus.Finite;
            }

            if (exponent >= 0)
            {
                // magnitude = significand * 10^exponent. UInt128 holds at most 39 digits, so any exponent that
                // would push the product past that bound overflows every integer type and saturates/throws.
                for (int i = 0; (i < exponent) && !exceedsUInt128; i++)
                {
                    if (significand > UInt128.MaxValue / 10)
                    {
                        exceedsUInt128 = true;
                        break;
                    }
                    significand *= 10;
                }

                magnitude = exceedsUInt128 ? UInt128.Zero : significand;
            }
            else
            {
                // magnitude = significand / 10^(-exponent), truncated toward zero. Once the divisor has more
                // digits than the significand the quotient is zero.
                int drop = -exponent;

                for (int i = 0; (i < drop) && (significand != UInt128.Zero); i++)
                {
                    significand /= 10;
                }

                magnitude = significand;
            }

            return DecimalIeee754ToIntegerStatus.Finite;
        }

        /// <summary>
        /// Converts a decimal value to an integer type, truncating toward zero. When <paramref name="isChecked"/>
        /// is <c>true</c>, NaN, infinities, and out-of-range values throw <see cref="OverflowException"/>;
        /// otherwise the result saturates (NaN maps to zero, out-of-range values clamp to the type's bounds),
        /// matching the behavior of the binary floating-point to integer conversions.
        /// </summary>
        internal static TInteger ConvertDecimalIeee754ToInteger<TDecimal, TValue, TInteger>(TValue decimalBits, bool isChecked)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
            where TInteger : IBinaryInteger<TInteger>, IMinMaxValue<TInteger>
        {
            DecimalIeee754ToIntegerStatus status = DecimalIeee754ToIntegerMagnitude<TDecimal, TValue>(decimalBits, out bool isNegative, out UInt128 magnitude, out bool exceedsUInt128);

            bool isUnsigned = TInteger.IsZero(TInteger.MinValue);
            UInt128 maxMagnitude = UInt128.CreateTruncating(TInteger.MaxValue);
            // For a two's-complement signed type the most-negative value has magnitude MaxValue + 1.
            UInt128 minMagnitude = isUnsigned ? UInt128.Zero : maxMagnitude + UInt128.One;

            switch (status)
            {
                case DecimalIeee754ToIntegerStatus.NaN:
                {
                    if (isChecked)
                    {
                        ThrowHelper.ThrowOverflowException();
                    }
                    return TInteger.Zero;
                }

                case DecimalIeee754ToIntegerStatus.PositiveInfinity:
                {
                    if (isChecked)
                    {
                        ThrowHelper.ThrowOverflowException();
                    }
                    return TInteger.MaxValue;
                }

                case DecimalIeee754ToIntegerStatus.NegativeInfinity:
                {
                    if (isChecked)
                    {
                        ThrowHelper.ThrowOverflowException();
                    }
                    return TInteger.MinValue;
                }

                default:
                {
                    if (!isNegative)
                    {
                        if (exceedsUInt128 || (magnitude > maxMagnitude))
                        {
                            if (isChecked)
                            {
                                ThrowHelper.ThrowOverflowException();
                            }
                            return TInteger.MaxValue;
                        }

                        return TInteger.CreateTruncating(magnitude);
                    }

                    // Negative magnitude.
                    if (isUnsigned)
                    {
                        if ((magnitude != UInt128.Zero) && isChecked)
                        {
                            ThrowHelper.ThrowOverflowException();
                        }
                        return TInteger.Zero;
                    }

                    if (exceedsUInt128 || (magnitude > minMagnitude))
                    {
                        if (isChecked)
                        {
                            ThrowHelper.ThrowOverflowException();
                        }
                        return TInteger.MinValue;
                    }

                    if (magnitude == minMagnitude)
                    {
                        return TInteger.MinValue;
                    }

                    return TInteger.Zero - TInteger.CreateTruncating(magnitude);
                }
            }
        }

        /// <summary>
        /// Converts an integer value of type <typeparamref name="TInteger"/> to the decimal format, rounding to
        /// the format precision when the integer has more significant digits than the format can represent. The
        /// result uses the preferred exponent of zero (quantum one) whenever the value fits exactly.
        /// </summary>
        internal static TValue ConvertIntegerToDecimalIeee754<TDecimal, TValue, TInteger>(TInteger value)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
            where TInteger : IBinaryInteger<TInteger>
        {
            bool isNegative = TInteger.IsNegative(value);
            UInt128 bits = UInt128.CreateTruncating(value);

            // For a negative value CreateTruncating sign-extends the two's-complement pattern to 128 bits, so a
            // width-independent negate recovers the true magnitude (including the most-negative value).
            UInt128 magnitude = isNegative ? (~bits) + UInt128.One : bits;

            // When the magnitude fits the significand (at most Precision digits) the integer is exactly
            // representable with exponent 0, so encode it directly and skip rendering the digits and running
            // the string-parse rounding pipeline. This is the overwhelmingly common case.
            if (magnitude <= UInt128.CreateTruncating(TDecimal.MaxSignificand))
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(isNegative, TValue.CreateTruncating(magnitude), 0);
            }

            return DecimalIeee754FromMagnitude<TDecimal, TValue>(isNegative, magnitude, 0);
        }

        /// <summary>
        /// Builds the decimal encoding for the value <c>(-1)^<paramref name="sign"/> * <paramref name="magnitude"/> * 10^<paramref name="exponent"/></c>,
        /// rendering the magnitude to its decimal digits and running the shared rounding pipeline (which rounds
        /// to the format precision and handles the subnormal and overflow ranges).
        /// </summary>
        private static TValue DecimalIeee754FromMagnitude<TDecimal, TValue>(bool sign, UInt128 magnitude, int exponent)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (magnitude == UInt128.Zero)
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(sign, TValue.Zero, exponent);
            }

            // A UInt128 has at most 39 decimal digits; leave room for the terminating null. The NumberBuffer
            // constructor rewrites Digits[0] as part of initialization, so the digits must be written into the
            // buffer's span after construction rather than before.
            Span<byte> digits = stackalloc byte[UInt128NumberBufferLength + 1];
            NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, digits);

            int digitsCount = WriteDecimalDigits(magnitude, number.Digits);
            number.DigitsCount = digitsCount;
            number.Scale = digitsCount + exponent;
            number.IsNegative = sign;
            number.CheckConsistency();

            return NumberToDecimalIeee754Bits<TDecimal, TValue>(ref number);
        }

        /// <summary>
        /// Writes the decimal digits of the non-zero <paramref name="magnitude"/> into <paramref name="digits"/>
        /// (most-significant digit first, no leading zeros) followed by a terminating null, returning the digit count.
        /// </summary>
        private static int WriteDecimalDigits(UInt128 magnitude, Span<byte> digits)
        {
            Debug.Assert(magnitude != UInt128.Zero);

            // Emit least-significant digit first into the tail of a scratch buffer, then compact to the front.
            Span<byte> scratch = stackalloc byte[UInt128NumberBufferLength];
            int index = scratch.Length;

            while (magnitude != UInt128.Zero)
            {
                (magnitude, UInt128 digit) = UInt128.DivRem(magnitude, 10);
                scratch[--index] = (byte)('0' + (int)digit);
            }

            int count = scratch.Length - index;
            scratch.Slice(index, count).CopyTo(digits);
            digits[count] = (byte)'\0';
            return count;
        }

        /// <summary>
        /// Converts a decimal value from the source format to the target format. Widening conversions are exact;
        /// narrowing conversions round to the target precision. NaN and infinities are propagated with their sign.
        /// </summary>
        internal static TTargetValue ConvertDecimalIeee754<TSourceDecimal, TSourceValue, TTargetDecimal, TTargetValue>(TSourceValue decimalBits)
            where TSourceDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TSourceDecimal, TSourceValue>
            where TSourceValue : unmanaged, IBinaryInteger<TSourceValue>
            where TTargetDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TTargetDecimal, TTargetValue>
            where TTargetValue : unmanaged, IBinaryInteger<TTargetValue>
        {
            bool isNegative = (decimalBits & TSourceDecimal.SignMask) != TSourceValue.Zero;

            if (TSourceDecimal.IsNaN(decimalBits))
            {
                return isNegative ? (TTargetDecimal.NaN | TTargetDecimal.SignMask) : TTargetDecimal.NaN;
            }

            if (TSourceDecimal.IsInfinity(decimalBits))
            {
                return isNegative ? TTargetDecimal.NegativeInfinity : TTargetDecimal.PositiveInfinity;
            }

            DecodedDecimalIeee754<TSourceValue> decoded = UnpackDecimalIeee754<TSourceDecimal, TSourceValue>(decimalBits);

            if (TSourceValue.IsZero(decoded.Significand))
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TTargetDecimal, TTargetValue>(decoded.Signed, TTargetValue.Zero, decoded.UnbiasedExponent);
            }

            UInt128 magnitude = UInt128.CreateTruncating(decoded.Significand);
            return DecimalIeee754FromMagnitude<TTargetDecimal, TTargetValue>(decoded.Signed, magnitude, decoded.UnbiasedExponent);
        }

        /// <summary>
        /// Converts a decimal value to the binary floating-point type <typeparamref name="TFloat"/>, correctly
        /// rounded. NaN and infinities propagate with their sign; finite values are rendered to their decimal
        /// digits and run through the shared binary parsing pipeline, which produces the correctly rounded result.
        /// </summary>
        internal static TFloat ConvertDecimalIeee754ToFloat<TDecimal, TValue, TFloat>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
            where TFloat : unmanaged, IBinaryFloatParseAndFormatInfo<TFloat>
        {
            bool isNegative = (decimalBits & TDecimal.SignMask) != TValue.Zero;

            if (TDecimal.IsNaN(decimalBits))
            {
                return isNegative ? -TFloat.NaN : TFloat.NaN;
            }

            if (TDecimal.IsInfinity(decimalBits))
            {
                return isNegative ? TFloat.NegativeInfinity : TFloat.PositiveInfinity;
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(decimalBits);

            if (TValue.IsZero(decoded.Significand))
            {
                return decoded.Signed ? -TFloat.Zero : TFloat.Zero;
            }

            // Fast path: when the significand fits a ulong (always for Decimal32/64, and for Decimal128 up to
            // ~19 digits) we already hold it as an integer mantissa, so we can feed the string-free
            // Clinger/Eisel-Lemire fast paths directly instead of rendering to ASCII and re-parsing.
            if (decoded.Significand <= TValue.CreateTruncating(ulong.MaxValue))
            {
                ulong mantissa = ulong.CreateTruncating(decoded.Significand);
                int exponent = decoded.UnbiasedExponent;
                int scale = TDecimal.CountDigits(decoded.Significand) + exponent;

                TFloat result;

                if (scale < TFloat.MinDecimalExponent)
                {
                    result = TFloat.Zero;
                }
                else if (scale > TFloat.MaxDecimalExponent)
                {
                    result = TFloat.PositiveInfinity;
                }
                else if (TryFloatingPointBitsFromMantissa<TFloat>(mantissa, exponent, out ulong bits))
                {
                    result = TFloat.BitsToFloat(bits);
                }
                else
                {
                    goto Slow;
                }

                return decoded.Signed ? -result : result;
            }

        Slow:
            // The NumberBuffer constructor rewrites Digits[0] as part of initialization, so the digits must be
            // written into the buffer's span after construction rather than before.
            UInt128 magnitude = UInt128.CreateTruncating(decoded.Significand);
            Span<byte> digits = stackalloc byte[UInt128NumberBufferLength + 1];
            NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, digits);

            int digitsCount = WriteDecimalDigits(magnitude, number.Digits);
            number.DigitsCount = digitsCount;
            number.Scale = digitsCount + decoded.UnbiasedExponent;
            number.IsNegative = decoded.Signed;

            return NumberToFloat<TFloat>(ref number);
        }

        /// <summary>
        /// Converts a binary floating-point value to the decimal format, correctly rounded. NaN and infinities
        /// propagate with their sign; finite values are expanded to their exact decimal representation via Dragon4
        /// and rounded once to the target precision (IEEE convertFormat rounds the exact value, not the shortest
        /// round-trippable string).
        /// </summary>
        internal static TValue ConvertFloatToDecimalIeee754<TFloat, TDecimal, TValue>(TFloat value)
            where TFloat : unmanaged, IBinaryFloatParseAndFormatInfo<TFloat>
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            bool isNegative = TFloat.IsNegative(value);

            if (TFloat.IsNaN(value))
            {
                return isNegative ? (TDecimal.NaN | TDecimal.SignMask) : TDecimal.NaN;
            }

            if (TFloat.IsInfinity(value))
            {
                return isNegative ? TDecimal.NegativeInfinity : TDecimal.PositiveInfinity;
            }

            if (value == TFloat.Zero)
            {
                return DecimalIeee754FiniteNumberBinaryEncoding<TDecimal, TValue>(isNegative, TValue.Zero, 0);
            }

            Span<byte> digits = stackalloc byte[TFloat.NumberBufferLength];
            NumberBuffer number = new NumberBuffer(NumberBufferKind.FloatingPoint, digits);

            // Fast path: round straight to the target precision. Dragon4's significant-digit cutoff is correctly
            // rounded (round-half-even from the exact value), and because the coefficient then has at most Precision
            // digits the shared pipeline performs no second rounding of significant digits, so the result is singly
            // (correctly) rounded without materializing the full exact expansion.
            Dragon4<TFloat>(value, cutoffNumber: TDecimal.Precision, isSignificantDigits: true, ref number, out bool isExact);
            number.IsNegative = isNegative;

            // IEEE convertFormat delivers the preferred (quantum) exponent Scale - DigitsCount for an exact result and
            // Scale - Precision for an inexact one. Dragon4 gives the former directly. When the value is inexact its
            // cutoff coefficient normally already spans Precision digits, but a rounding carry can drop trailing digits
            // (for example 262143.99999999997 rounds to 262144), leaving DigitsCount < Precision and an exponent one or
            // more places too high; re-materialize those trailing zeros so the coefficient carries the full Precision
            // width. The subnormal decimal range is excluded because there the coefficient must round to fewer than
            // Precision digits, which would double round the cutoff result, so those values take the exact path below.
            if ((number.Scale - TDecimal.Precision) >= TDecimal.MinAdjustedExponent)
            {
                if (!isExact && (number.DigitsCount < TDecimal.Precision))
                {
                    int end = TDecimal.Precision;
                    digits.Slice(number.DigitsCount, end - number.DigitsCount).Fill((byte)'0');
                    digits[end] = (byte)'\0';
                    number.DigitsCount = end;
                }

                MaterializePreferredZeros(ref number, digits);
                number.CheckConsistency();
                return NumberToDecimalIeee754Bits<TDecimal, TValue>(ref number);
            }

            // Subnormal decimal range: produce the full exact expansion and let the pipeline round once to the reduced
            // precision the clamped quantum allows. Passing a length-based cutoff of int.MaxValue makes the buffer size
            // the limiting factor, and NumberBufferLength is large enough to hold the full expansion so the result is
            // exact and a single rounding to precision follows.
            Dragon4<TFloat>(value, cutoffNumber: int.MaxValue, isSignificantDigits: false, ref number);
            number.IsNegative = isNegative;

            MaterializePreferredZeros(ref number, digits);
            number.CheckConsistency();

            return NumberToDecimalIeee754Bits<TDecimal, TValue>(ref number);

            // For an exact result IEEE convertFormat delivers the representable exponent closest to zero from below.
            // Dragon4 strips trailing zeros, which can push the exponent above zero (e.g. 1000 -> digits "1", Scale 4,
            // exponent 3). Re-materialize those trailing zeros to bring the exponent down to zero so integer-valued
            // inputs keep quantum one (matching the decimal parse path); the shared pipeline then rounds when the
            // coefficient exceeds the target precision.
            static void MaterializePreferredZeros(ref NumberBuffer number, Span<byte> digits)
            {
                int preferredZeros = number.Scale - number.DigitsCount;
                if (preferredZeros > 0)
                {
                    int end = number.DigitsCount + preferredZeros;
                    digits.Slice(number.DigitsCount, preferredZeros).Fill((byte)'0');
                    digits[end] = (byte)'\0';
                    number.DigitsCount = end;
                }
            }
        }

        /// <summary>
        /// Converts a decimal value to <see cref="decimal"/> (System.Decimal). NaN and infinities cannot be
        /// represented and throw <see cref="OverflowException"/>; finite values are rendered to their decimal
        /// digits and run through the shared System.Decimal conversion pipeline, which rounds to the System.Decimal
        /// precision and throws <see cref="OverflowException"/> when the value is outside the System.Decimal range.
        /// </summary>
        internal static decimal ConvertDecimalIeee754ToDecimal<TDecimal, TValue>(TValue decimalBits)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            if (TDecimal.IsNaN(decimalBits) || TDecimal.IsInfinity(decimalBits))
            {
                throw new OverflowException(SR.Overflow_Decimal);
            }

            DecodedDecimalIeee754<TValue> decoded = UnpackDecimalIeee754<TDecimal, TValue>(decimalBits);

            if (TValue.IsZero(decoded.Significand))
            {
                // System.Decimal has no infinite quantum range: clamp the preferred exponent into the [0, -28]
                // scale range the way the parse pipeline does for a zero coefficient.
                return new decimal(0, 0, 0, decoded.Signed, (byte)Math.Clamp(-decoded.UnbiasedExponent, 0, 28));
            }

            UInt128 magnitude = UInt128.CreateTruncating(decoded.Significand);
            Span<byte> digits = stackalloc byte[UInt128NumberBufferLength + 1];
            NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, digits);

            int digitsCount = WriteDecimalDigits(magnitude, number.Digits);
            number.DigitsCount = digitsCount;
            number.Scale = digitsCount + decoded.UnbiasedExponent;
            number.IsNegative = decoded.Signed;
            number.CheckConsistency();

            decimal result = default;

            if (!TryNumberToDecimal(ref number, ref result))
            {
                throw new OverflowException(SR.Overflow_Decimal);
            }

            return result;
        }

        /// <summary>
        /// Converts a <see cref="decimal"/> (System.Decimal) value to the decimal format, correctly rounded. The
        /// System.Decimal digits and scale are rendered into a NumberBuffer and run through the shared rounding
        /// pipeline, which rounds to the format precision and preserves the source quantum (IEEE convertFormat).
        /// </summary>
        internal static TValue ConvertDecimalToDecimalIeee754<TDecimal, TValue>(decimal value)
            where TDecimal : unmanaged, IDecimalIeee754ParseAndFormatInfo<TDecimal, TValue>
            where TValue : unmanaged, IBinaryInteger<TValue>
        {
            Span<byte> digits = stackalloc byte[DecimalNumberBufferLength];
            NumberBuffer number = new NumberBuffer(NumberBufferKind.Decimal, digits);

            DecimalToNumber(ref value, ref number);

            return NumberToDecimalIeee754Bits<TDecimal, TValue>(ref number);
        }
    }
}