1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Diagnostics;
7 using System.Runtime.CompilerServices;
8 using System.Runtime.InteropServices;
9 using Internal.Runtime.CompilerServices;
10 using X86 = System.Runtime.Intrinsics.X86;
14 public partial struct Decimal
16 // Low level accessors used by a DecCalc and formatting
17 internal uint High => (uint)hi;
18 internal uint Low => (uint)lo;
19 internal uint Mid => (uint)mid;
21 internal bool IsNegative => flags < 0;
23 internal int Scale => (byte)(flags >> ScaleShift);
26 private ulong Low64 => ((ulong)Mid << 32) | Low;
28 private ulong Low64 => Unsafe.As<int, ulong>(ref Unsafe.AsRef(in lo));
31 private static ref DecCalc AsMutable(ref decimal d) => ref Unsafe.As<decimal, DecCalc>(ref d);
33 #region APIs need by number formatting.
35 internal static uint DecDivMod1E9(ref decimal value)
37 return DecCalc.DecDivMod1E9(ref AsMutable(ref value));
43 /// Class that contains all the mathematical calculations for decimal. Most of which have been ported from oleaut32.
45 [StructLayout(LayoutKind.Explicit)]
46 private struct DecCalc
48 // NOTE: Do not change the offsets of these fields. This structure must have the same layout as Decimal.
59 /// The low and mid fields combined in little-endian order
62 private ulong ulomidLE;
82 private bool IsNegative => (int)uflags < 0;
84 private int Scale => (byte)(uflags >> ScaleShift);
89 get { return ((ulong)umid << 32) | ulo; }
90 set { umid = (uint)(value >> 32); ulo = (uint)value; }
93 set => ulomidLE = value;
97 private const uint SignMask = 0x80000000;
98 private const uint ScaleMask = 0x00FF0000;
100 private const int DEC_SCALE_MAX = 28;
102 private const uint TenToPowerNine = 1000000000;
103 private const ulong TenToPowerEighteen = 1000000000000000000;
105 // The maximum power of 10 that a 32 bit integer can store
106 private const int MaxInt32Scale = 9;
107 // The maximum power of 10 that a 64 bit integer can store
108 private const int MaxInt64Scale = 19;
110 // Fast access for 10^n where n is 0-9
111 private static readonly uint[] s_powers10 = new uint[] {
124 // Fast access for 10^n where n is 1-19
125 private static readonly ulong[] s_ulongPowers10 = new ulong[] {
144 10000000000000000000,
147 private static readonly double[] s_doublePowers10 = new double[] {
148 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
149 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
150 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
151 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
152 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
153 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
154 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
155 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
159 // Used to fill uninitialized stack variables with non-zero pattern in debug builds
160 [Conditional("DEBUG")]
161 private static unsafe void DebugPoison<T>(ref T s) where T: unmanaged
163 MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref s, 1)).Fill(0xCD);
166 #region Decimal Math Helpers
168 private static unsafe uint GetExponent(float f)
170 // Based on pulling out the exp from this single struct layout
177 return (byte)(*(uint*)&f >> 23);
180 private static unsafe uint GetExponent(double d)
182 // Based on pulling out the exp from this double struct layout
184 // DWORDLONG mant:52;
185 // DWORDLONG signexp:12;
188 return (uint)(*(ulong*)&d >> 52) & 0x7FFu;
191 private static ulong UInt32x32To64(uint a, uint b)
193 return (ulong)a * (ulong)b;
196 private static void UInt64x64To128(ulong a, ulong b, ref DecCalc result)
198 ulong low = UInt32x32To64((uint)a, (uint)b); // lo partial prod
199 ulong mid = UInt32x32To64((uint)a, (uint)(b >> 32)); // mid 1 partial prod
200 ulong high = UInt32x32To64((uint)(a >> 32), (uint)(b >> 32));
203 if (low < mid) // test for carry
206 mid = UInt32x32To64((uint)(a >> 32), (uint)b);
209 if (low < mid) // test for carry
212 if (high > uint.MaxValue)
213 Number.ThrowOverflowException(TypeCode.Decimal);
215 result.High = (uint)high;
219 /// Do full divide, yielding 96-bit result and 32-bit remainder.
221 /// <param name="bufNum">96-bit dividend as array of uints, least-sig first</param>
222 /// <param name="den">32-bit divisor</param>
223 /// <returns>Returns remainder. Quotient overwrites dividend.</returns>
224 private static uint Div96By32(ref Buf12 bufNum, uint den)
226 // TODO: https://github.com/dotnet/coreclr/issues/3439
233 tmp = ((tmp - (uint)div * den) << 32) | bufNum.U0;
236 uint div32 = (uint)(tmp / den);
238 return (uint)tmp - div32 * den;
246 return (uint)(tmp - div * den);
249 [MethodImpl(MethodImplOptions.AggressiveInlining)]
250 private static bool Div96ByConst(ref ulong high64, ref uint low, uint pow)
253 ulong div64 = high64 / pow;
254 uint div = (uint)((((high64 - div64 * pow) << 32) + low) / pow);
255 if (low == div * pow)
262 // 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
263 Debug.Assert(pow <= ushort.MaxValue);
264 uint num, mid32, low16, div;
265 if (high64 <= uint.MaxValue)
269 num = (num - mid32 * pow) << 16;
273 num = (num - low16 * pow) << 16;
277 if (num == div * pow)
280 low = (low16 << 16) + div;
286 num = (uint)(high64 >> 32);
287 uint high32 = num / pow;
288 num = (num - high32 * pow) << 16;
290 num += (uint)high64 >> 16;
292 num = (num - mid32 * pow) << 16;
294 num += (ushort)high64;
296 num = (num - div * pow) << 16;
297 mid32 = div + (mid32 << 16);
301 num = (num - low16 * pow) << 16;
305 if (num == div * pow)
307 high64 = ((ulong)high32 << 32) | mid32;
308 low = (low16 << 16) + div;
317 /// Normalize (unscale) the number by trying to divide out 10^8, 10^4, 10^2, and 10^1.
318 /// If a division by one of these powers returns a zero remainder, then we keep the quotient.
320 [MethodImpl(MethodImplOptions.AggressiveInlining)]
321 private static void Unscale(ref uint low, ref ulong high64, ref int scale)
323 // Since 10 = 2 * 5, there must be a factor of 2 for every power of 10 we can extract.
324 // We use this as a quick test on whether to try a given power.
327 while ((byte)low == 0 && scale >= 8 && Div96ByConst(ref high64, ref low, 100000000))
330 if ((low & 0xF) == 0 && scale >= 4 && Div96ByConst(ref high64, ref low, 10000))
333 while ((low & 0xF) == 0 && scale >= 4 && Div96ByConst(ref high64, ref low, 10000))
337 if ((low & 3) == 0 && scale >= 2 && Div96ByConst(ref high64, ref low, 100))
340 if ((low & 1) == 0 && scale >= 1 && Div96ByConst(ref high64, ref low, 10))
345 /// Do partial divide, yielding 32-bit result and 64-bit remainder.
346 /// Divisor must be larger than upper 64 bits of dividend.
348 /// <param name="bufNum">96-bit dividend as array of uints, least-sig first</param>
349 /// <param name="den">64-bit divisor</param>
350 /// <returns>Returns quotient. Remainder overwrites lower 64-bits of dividend.</returns>
351 private static uint Div96By64(ref Buf12 bufNum, ulong den)
353 Debug.Assert(den > bufNum.High64);
356 uint num2 = bufNum.U2;
361 // Result is zero. Entire dividend is remainder.
364 // TODO: https://github.com/dotnet/coreclr/issues/3439
365 quo = (uint)(num / den);
366 num -= quo * den; // remainder
371 uint denHigh32 = (uint)(den >> 32);
372 if (num2 >= denHigh32)
374 // Divide would overflow. Assume a quotient of 2^32, and set
375 // up remainder accordingly.
381 // Remainder went negative. Add divisor back in until it's positive,
388 } while (num >= den);
394 // Hardware divide won't overflow
396 ulong num64 = bufNum.High64;
397 if (num64 < denHigh32)
398 // Result is zero. Entire dividend is remainder.
402 // TODO: https://github.com/dotnet/coreclr/issues/3439
403 quo = (uint)(num64 / denHigh32);
404 num = bufNum.U0 | ((num64 - quo * denHigh32) << 32); // remainder
406 // Compute full remainder, rem = dividend - (quo * divisor).
408 ulong prod = UInt32x32To64(quo, (uint)den); // quo * lo divisor
413 // Remainder went negative. Add divisor back in until it's positive,
420 } while (num >= den);
428 /// Do partial divide, yielding 32-bit result and 96-bit remainder.
429 /// Top divisor uint must be larger than top dividend uint. This is
430 /// assured in the initial call because the divisor is normalized
431 /// and the dividend can't be. In subsequent calls, the remainder
432 /// is multiplied by 10^9 (max), so it can be no more than 1/4 of
433 /// the divisor which is effectively multiplied by 2^32 (4 * 10^9).
435 /// <param name="bufNum">128-bit dividend as array of uints, least-sig first</param>
436 /// <param name="bufDen">96-bit divisor</param>
437 /// <returns>Returns quotient. Remainder overwrites lower 96-bits of dividend.</returns>
438 private static uint Div128By96(ref Buf16 bufNum, ref Buf12 bufDen)
440 Debug.Assert(bufDen.U2 > bufNum.U3);
441 ulong dividend = bufNum.High64;
442 uint den = bufDen.U2;
444 // Result is zero. Entire dividend is remainder.
448 // TODO: https://github.com/dotnet/coreclr/issues/3439
449 uint quo = (uint)(dividend / den);
450 uint remainder = (uint)dividend - quo * den;
452 // Compute full remainder, rem = dividend - (quo * divisor).
454 ulong prod1 = UInt32x32To64(quo, bufDen.U0); // quo * lo divisor
455 ulong prod2 = UInt32x32To64(quo, bufDen.U1); // quo * mid divisor
456 prod2 += prod1 >> 32;
457 prod1 = (uint)prod1 | (prod2 << 32);
460 ulong num = bufNum.Low64;
462 remainder -= (uint)prod2;
469 if (remainder < ~(uint)prod2)
472 else if (remainder <= ~(uint)prod2)
475 // Remainder went negative. Add divisor back in until it's positive,
478 prod1 = bufDen.Low64;
488 // Detected carry. Check for carry out of top
489 // before adding it in.
491 if (remainder++ < den)
495 break; // detected carry
501 bufNum.U2 = remainder;
506 /// Multiply the two numbers. The low 96 bits of the result overwrite
507 /// the input. The last 32 bits of the product are the return value.
509 /// <param name="bufNum">96-bit number as array of uints, least-sig first</param>
510 /// <param name="power">Scale factor to multiply by</param>
511 /// <returns>Returns highest 32 bits of product</returns>
512 private static uint IncreaseScale(ref Buf12 bufNum, uint power)
514 ulong tmp = UInt32x32To64(bufNum.U0, power);
515 bufNum.U0 = (uint)tmp;
517 tmp += UInt32x32To64(bufNum.U1, power);
518 bufNum.U1 = (uint)tmp;
520 tmp += UInt32x32To64(bufNum.U2, power);
521 bufNum.U2 = (uint)tmp;
522 return (uint)(tmp >> 32);
525 private static void IncreaseScale64(ref Buf12 bufNum, uint power)
527 ulong tmp = UInt32x32To64(bufNum.U0, power);
528 bufNum.U0 = (uint)tmp;
530 tmp += UInt32x32To64(bufNum.U1, power);
535 /// See if we need to scale the result to fit it in 96 bits.
536 /// Perform needed scaling. Adjust scale factor accordingly.
538 /// <param name="bufRes">Array of uints with value, least-significant first</param>
539 /// <param name="hiRes">Index of last non-zero value in bufRes</param>
540 /// <param name="scale">Scale factor for this value, range 0 - 2 * DEC_SCALE_MAX</param>
541 /// <returns>Returns new scale factor. bufRes updated in place, always 3 uints.</returns>
542 private static unsafe int ScaleResult(Buf24* bufRes, uint hiRes, int scale)
544 Debug.Assert(hiRes < bufRes->Length);
545 uint* result = (uint*)bufRes;
547 // See if we need to scale the result. The combined scale must
548 // be <= DEC_SCALE_MAX and the upper 96 bits must be zero.
550 // Start by figuring a lower bound on the scaling needed to make
551 // the upper 96 bits zero. hiRes is the index into result[]
552 // of the highest non-zero uint.
557 newScale = (int)hiRes * 32 - 64 - 1;
558 newScale -= BitOperations.LeadingZeroCount(result[hiRes]);
560 // Multiply bit position by log10(2) to figure it's power of 10.
561 // We scale the log by 256. log(2) = .30103, * 256 = 77. Doing this
562 // with a multiply saves a 96-byte lookup table. The power returned
563 // is <= the power of the number, so we must add one power of 10
564 // to make it's integer part zero after dividing by 256.
566 // Note: the result of this multiplication by an approximation of
567 // log10(2) have been exhaustively checked to verify it gives the
568 // correct result. (There were only 95 to check...)
570 newScale = ((newScale * 77) >> 8) + 1;
572 // newScale = min scale factor to make high 96 bits zero, 0 - 29.
573 // This reduces the scale factor of the result. If it exceeds the
574 // current scale of the result, we'll overflow.
576 if (newScale > scale)
580 // Make sure we scale by enough to bring the current scale factor
583 if (newScale < scale - DEC_SCALE_MAX)
584 newScale = scale - DEC_SCALE_MAX;
588 // Scale by the power of 10 given by newScale. Note that this is
589 // NOT guaranteed to bring the number within 96 bits -- it could
590 // be 1 power of 10 short.
594 uint quotient, remainder = 0;
598 sticky |= remainder; // record remainder as sticky bit
601 // Scaling loop specialized for each power of 10 because division by constant is an order of magnitude faster (especially for 64-bit division that's actually done by 128bit DIV on x64)
605 power = DivByConst(result, hiRes, out quotient, out remainder, 10);
608 power = DivByConst(result, hiRes, out quotient, out remainder, 100);
611 power = DivByConst(result, hiRes, out quotient, out remainder, 1000);
614 power = DivByConst(result, hiRes, out quotient, out remainder, 10000);
618 power = DivByConst(result, hiRes, out quotient, out remainder, 100000);
621 power = DivByConst(result, hiRes, out quotient, out remainder, 1000000);
624 power = DivByConst(result, hiRes, out quotient, out remainder, 10000000);
627 power = DivByConst(result, hiRes, out quotient, out remainder, 100000000);
630 power = DivByConst(result, hiRes, out quotient, out remainder, TenToPowerNine);
637 result[hiRes] = quotient;
638 // If first quotient was 0, update hiRes.
640 if (quotient == 0 && hiRes != 0)
644 newScale -= MaxInt32Scale;
649 continue; // scale some more
651 // If we scaled enough, hiRes would be 2 or less. If not,
652 // divide by 10 more.
660 continue; // scale by 10
663 // Round final result. See if remainder >= 1/2 of divisor.
664 // If remainder == 1/2 divisor, round up if odd or sticky bit set.
666 power >>= 1; // power of 10 always even
667 if (power <= remainder && (power < remainder || ((result[0] & 1) | sticky) != 0) && ++result[0] == 0)
672 Debug.Assert(cur + 1 < bufRes->Length);
674 while (++result[++cur] == 0);
678 // The rounding caused us to carry beyond 96 bits.
684 sticky = 0; // no sticky bit
685 remainder = 0; // or remainder
688 continue; // scale by 10
698 Number.ThrowOverflowException(TypeCode.Decimal);
702 [MethodImpl(MethodImplOptions.AggressiveInlining)]
703 private static unsafe uint DivByConst(uint* result, uint hiRes, out uint quotient, out uint remainder, uint power)
705 uint high = result[hiRes];
706 remainder = high - (quotient = high / power) * power;
707 for (uint i = hiRes - 1; (int)i >= 0; i--)
710 ulong num = result[i] + ((ulong)remainder << 32);
711 remainder = (uint)num - (result[i] = (uint)(num / power)) * power;
713 // 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
714 Debug.Assert(power <= ushort.MaxValue);
716 const int low16 = 2, high16 = 0;
718 const int low16 = 0, high16 = 2;
720 // byte* is used here because Roslyn doesn't do constant propagation for pointer arithmetic
721 uint num = *(ushort*)((byte*)result + i * 4 + high16) + (remainder << 16);
722 uint div = num / power;
723 remainder = num - div * power;
724 *(ushort*)((byte*)result + i * 4 + high16) = (ushort)div;
726 num = *(ushort*)((byte*)result + i * 4 + low16) + (remainder << 16);
728 remainder = num - div * power;
729 *(ushort*)((byte*)result + i * 4 + low16) = (ushort)div;
736 /// Adjust the quotient to deal with an overflow.
737 /// We need to divide by 10, feed in the high bit to undo the overflow and then round as required.
739 private static int OverflowUnscale(ref Buf12 bufQuo, int scale, bool sticky)
742 Number.ThrowOverflowException(TypeCode.Decimal);
744 Debug.Assert(bufQuo.U2 == 0);
746 // We have overflown, so load the high bit with a one.
747 const ulong highbit = 1UL << 32;
748 bufQuo.U2 = (uint)(highbit / 10);
749 ulong tmp = ((highbit % 10) << 32) + bufQuo.U1;
750 uint div = (uint)(tmp / 10);
752 tmp = ((tmp - div * 10) << 32) + bufQuo.U0;
753 div = (uint)(tmp / 10);
755 uint remainder = (uint)(tmp - div * 10);
756 // The remainder is the last digit that does not fit, so we can use it to work out if we need to round up
757 if (remainder > 5 || remainder == 5 && (sticky || (bufQuo.U0 & 1) != 0))
758 Add32To96(ref bufQuo, 1);
763 /// Determine the max power of 10, <= 9, that the quotient can be scaled
764 /// up by and still fit in 96 bits.
766 /// <param name="bufQuo">96-bit quotient</param>
767 /// <param name="scale ">Scale factor of quotient, range -DEC_SCALE_MAX to DEC_SCALE_MAX-1</param>
768 /// <returns>power of 10 to scale by</returns>
769 private static int SearchScale(ref Buf12 bufQuo, int scale)
771 const uint OVFL_MAX_9_HI = 4;
772 const uint OVFL_MAX_8_HI = 42;
773 const uint OVFL_MAX_7_HI = 429;
774 const uint OVFL_MAX_6_HI = 4294;
775 const uint OVFL_MAX_5_HI = 42949;
776 const uint OVFL_MAX_4_HI = 429496;
777 const uint OVFL_MAX_3_HI = 4294967;
778 const uint OVFL_MAX_2_HI = 42949672;
779 const uint OVFL_MAX_1_HI = 429496729;
780 const ulong OVFL_MAX_9_MIDLO = 5441186219426131129;
782 uint resHi = bufQuo.U2;
783 ulong resMidLo = bufQuo.Low64;
786 // Quick check to stop us from trying to scale any more.
788 if (resHi > OVFL_MAX_1_HI)
793 var powerOvfl = PowerOvflValues;
794 if (scale > DEC_SCALE_MAX - 9)
796 // We can't scale by 10^9 without exceeding the max scale factor.
797 // See if we can scale to the max. If not, we'll fall into
798 // standard search for scale factor.
800 curScale = DEC_SCALE_MAX - scale;
801 if (resHi < powerOvfl[curScale - 1].Hi)
804 else if (resHi < OVFL_MAX_9_HI || resHi == OVFL_MAX_9_HI && resMidLo <= OVFL_MAX_9_MIDLO)
807 // Search for a power to scale by < 9. Do a binary search.
809 if (resHi > OVFL_MAX_5_HI)
811 if (resHi > OVFL_MAX_3_HI)
814 if (resHi > OVFL_MAX_2_HI)
820 if (resHi > OVFL_MAX_4_HI)
826 if (resHi > OVFL_MAX_7_HI)
829 if (resHi > OVFL_MAX_6_HI)
835 if (resHi > OVFL_MAX_8_HI)
840 // In all cases, we already found we could not use the power one larger.
841 // So if we can use this power, it is the biggest, and we're done. If
842 // we can't use this power, the one below it is correct for all cases
843 // unless it's 10^1 -- we might have to go to 10^0 (no scaling).
845 if (resHi == powerOvfl[curScale - 1].Hi && resMidLo > powerOvfl[curScale - 1].MidLo)
849 // curScale = largest power of 10 we can scale by without overflow,
850 // curScale < 9. See if this is enough to make scale factor
851 // positive if it isn't already.
853 if (curScale + scale < 0)
854 Number.ThrowOverflowException(TypeCode.Decimal);
860 /// Add a 32-bit uint to an array of 3 uints representing a 96-bit integer.
862 /// <returns>Returns false if there is an overflow</returns>
863 private static bool Add32To96(ref Buf12 bufNum, uint value)
865 if ((bufNum.Low64 += value) < value)
867 if (++bufNum.U2 == 0)
874 /// Adds or subtracts two decimal values.
875 /// On return, d1 contains the result of the operation and d2 is trashed.
877 /// <param name="sign">True means subtract and false means add.</param>
878 internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign)
880 ulong low64 = d1.Low64;
881 uint high = d1.High, flags = d1.uflags, d2flags = d2.uflags;
883 uint xorflags = d2flags ^ flags;
884 sign ^= (xorflags & SignMask) != 0;
886 if ((xorflags & ScaleMask) == 0)
888 // Scale factors are equal, no alignment necessary.
894 // Scale factors are not equal. Assume that a larger scale
895 // factor (more decimal places) is likely to mean that number
896 // is smaller. Start by guessing that the right operand has
897 // the larger scale factor. The result will have the larger
900 uint d1flags = flags;
901 flags = d2flags & ScaleMask | flags & SignMask; // scale factor of "smaller", but sign of "larger"
902 int scale = (int)(flags - d1flags) >> ScaleShift;
906 // Guessed scale factor wrong. Swap operands.
920 // d1 will need to be multiplied by 10^scale so
921 // it will have the same scale as d2. We could be
922 // extending it to up to 192 bits of precision.
924 // Scan for zeros in the upper words.
928 if (low64 <= uint.MaxValue)
930 if ((uint)low64 == 0)
932 // Left arg is zero, return right.
934 uint signFlags = flags & SignMask;
936 signFlags ^= SignMask;
938 d1.uflags = d2.uflags & ScaleMask | signFlags;
944 if (scale <= MaxInt32Scale)
946 low64 = UInt32x32To64((uint)low64, s_powers10[scale]);
949 scale -= MaxInt32Scale;
950 low64 = UInt32x32To64((uint)low64, TenToPowerNine);
951 } while (low64 <= uint.MaxValue);
956 power = TenToPowerNine;
957 if (scale < MaxInt32Scale)
958 power = s_powers10[scale];
959 tmpLow = UInt32x32To64((uint)low64, power);
960 tmp64 = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32);
961 low64 = (uint)tmpLow + (tmp64 << 32);
962 high = (uint)(tmp64 >> 32);
963 if ((scale -= MaxInt32Scale) <= 0)
970 // Scaling won't make it larger than 4 uints
972 power = TenToPowerNine;
973 if (scale < MaxInt32Scale)
974 power = s_powers10[scale];
975 tmpLow = UInt32x32To64((uint)low64, power);
976 tmp64 = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32);
977 low64 = (uint)tmpLow + (tmp64 << 32);
979 tmp64 += UInt32x32To64(high, power);
981 scale -= MaxInt32Scale;
982 if (tmp64 > uint.MaxValue)
986 // Result fits in 96 bits. Use standard aligned add.
991 // Have to scale by a bunch. Move the number to a buffer where it has room to grow as it's scaled.
994 _ = &bufNum; // workaround for CS0165
995 DebugPoison(ref bufNum);
997 bufNum.Low64 = low64;
998 bufNum.Mid64 = tmp64;
1001 // Scaling loop, up to 10^9 at a time. hiProd stays updated with index of highest non-zero uint.
1003 for (; scale > 0; scale -= MaxInt32Scale)
1005 power = TenToPowerNine;
1006 if (scale < MaxInt32Scale)
1007 power = s_powers10[scale];
1009 uint* rgulNum = (uint*)&bufNum;
1010 for (uint cur = 0; ;)
1012 Debug.Assert(cur < bufNum.Length);
1013 tmp64 += UInt32x32To64(rgulNum[cur], power);
1014 rgulNum[cur] = (uint)tmp64;
1021 if ((uint)tmp64 != 0)
1023 // We're extending the result by another uint.
1024 Debug.Assert(hiProd + 1 < bufNum.Length);
1025 rgulNum[++hiProd] = (uint)tmp64;
1029 // Scaling complete, do the add. Could be subtract if signs differ.
1031 tmp64 = bufNum.Low64;
1033 uint tmpHigh = bufNum.U2;
1038 // Signs differ, subtract.
1040 low64 = tmp64 - low64;
1041 high = tmpHigh - high;
1051 else if (high <= tmpHigh)
1054 // Carry the subtraction into the higher bits.
1056 uint* number = (uint*)&bufNum;
1060 Debug.Assert(cur < bufNum.Length);
1061 } while (number[cur++]-- == 0);
1062 Debug.Assert(hiProd < bufNum.Length);
1063 if (number[hiProd] == 0 && --hiProd <= 2)
1068 // Signs the same, add.
1081 else if (high >= tmpHigh)
1084 uint* number = (uint*)&bufNum;
1085 for (uint cur = 3; ++number[cur++] == 0;)
1087 Debug.Assert(cur < bufNum.Length);
1098 bufNum.Low64 = low64;
1100 scale = ScaleResult(&bufNum, hiProd, (byte)(flags >> ScaleShift));
1101 flags = (flags & ~ScaleMask) | ((uint)scale << ScaleShift);
1102 low64 = bufNum.Low64;
1109 // Got negative result. Flip its sign.
1112 low64 = (ulong)-(long)low64;
1120 // The addition carried above 96 bits.
1121 // Divide the value by 10, dropping the scale factor.
1123 if ((flags & ScaleMask) == 0)
1124 Number.ThrowOverflowException(TypeCode.Decimal);
1125 flags -= 1 << ScaleShift;
1127 const uint den = 10;
1128 ulong num = high + (1UL << 32);
1129 high = (uint)(num / den);
1130 num = ((num - high * den) << 32) + (low64 >> 32);
1131 uint div = (uint)(num / den);
1132 num = ((num - div * den) << 32) + (uint)low64;
1135 div = (uint)(num / den);
1137 div = (uint)num - div * den;
1139 // See if we need to round up.
1141 if (div >= 5 && (div > 5 || (low64 & 1) != 0))
1151 ulong d1Low64 = low64;
1155 // Signs differ - subtract
1157 low64 = d1Low64 - d2.Low64;
1158 high = d1High - d2.High;
1162 if (low64 > d1Low64)
1168 else if (high > d1High)
1173 // Signs are the same - add
1175 low64 = d1Low64 + d2.Low64;
1176 high = d1High + d2.High;
1180 if (low64 < d1Low64)
1186 else if (high < d1High)
1202 /// Convert Decimal to Currency (similar to OleAut32 api.)
1204 internal static long VarCyFromDec(ref DecCalc pdecIn)
1208 int scale = pdecIn.Scale - 4;
1209 // Need to scale to get 4 decimal places. -4 <= scale <= 24.
1213 if (pdecIn.High != 0)
1215 uint pwr = s_powers10[-scale];
1216 ulong high = UInt32x32To64(pwr, pdecIn.Mid);
1217 if (high > uint.MaxValue)
1219 ulong low = UInt32x32To64(pwr, pdecIn.Low);
1228 InternalRound(ref pdecIn, (uint)scale, MidpointRounding.ToEven);
1229 if (pdecIn.High != 0)
1231 value = (long)pdecIn.Low64;
1234 if (value < 0 && (value != long.MinValue || !pdecIn.IsNegative))
1237 if (pdecIn.IsNegative)
1243 throw new OverflowException(SR.Overflow_Currency);
1247 /// Decimal Compare updated to return values similar to ICompareTo
1249 internal static int VarDecCmp(in decimal d1, in decimal d2)
1251 if ((d2.Low | d2.Mid | d2.High) == 0)
1253 if ((d1.Low | d1.Mid | d1.High) == 0)
1255 return (d1.flags >> 31) | 1;
1257 if ((d1.Low | d1.Mid | d1.High) == 0)
1258 return -((d2.flags >> 31) | 1);
1260 int sign = (d1.flags >> 31) - (d2.flags >> 31);
1263 return VarDecCmpSub(in d1, in d2);
1266 private static int VarDecCmpSub(in decimal d1, in decimal d2)
1268 int flags = d2.flags;
1269 int sign = (flags >> 31) | 1;
1270 int scale = flags - d1.flags;
1272 ulong low64 = d1.Low64;
1273 uint high = d1.High;
1275 ulong d2Low64 = d2.Low64;
1276 uint d2High = d2.High;
1280 scale >>= ScaleShift;
1282 // Scale factors are not equal. Assume that a larger scale factor (more decimal places) is likely to mean that number is smaller.
1283 // Start by guessing that the right operand has the larger scale factor.
1286 // Guessed scale factor wrong. Swap operands.
1290 ulong tmp64 = low64;
1299 // d1 will need to be multiplied by 10^scale so it will have the same scale as d2.
1300 // Scaling loop, up to 10^9 at a time.
1303 uint power = scale >= MaxInt32Scale ? TenToPowerNine : s_powers10[scale];
1304 ulong tmpLow = UInt32x32To64((uint)low64, power);
1305 ulong tmp = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32);
1306 low64 = (uint)tmpLow + (tmp << 32);
1308 tmp += UInt32x32To64(high, power);
1309 // If the scaled value has more than 96 significant bits then it's greater than d2
1310 if (tmp > uint.MaxValue)
1313 } while ((scale -= MaxInt32Scale) > 0);
1316 uint cmpHigh = high - d2High;
1319 // check for overflow
1325 ulong cmpLow64 = low64 - d2Low64;
1328 // check for overflow
1329 else if (cmpLow64 > low64)
1335 /// Decimal Multiply
1337 internal static unsafe void VarDecMul(ref DecCalc d1, ref DecCalc d2)
1339 int scale = (byte)(d1.uflags + d2.uflags >> ScaleShift);
1344 _ = &bufProd; // workaround for CS0165
1345 DebugPoison(ref bufProd);
1347 if ((d1.High | d1.Mid) == 0)
1349 if ((d2.High | d2.Mid) == 0)
1351 // Upper 64 bits are zero.
1353 ulong low64 = UInt32x32To64(d1.Low, d2.Low);
1354 if (scale > DEC_SCALE_MAX)
1356 // Result scale is too big. Divide result by power of 10 to reduce it.
1357 // If the amount to divide by is > 19 the result is guaranteed
1358 // less than 1/2. [max value in 64 bits = 1.84E19]
1360 if (scale > DEC_SCALE_MAX + MaxInt64Scale)
1363 scale -= DEC_SCALE_MAX + 1;
1364 ulong power = s_ulongPowers10[scale];
1366 // TODO: https://github.com/dotnet/coreclr/issues/3439
1367 tmp = low64 / power;
1368 ulong remainder = low64 - tmp * power;
1371 // Round result. See if remainder >= 1/2 of divisor.
1372 // Divisor is a power of 10, so it is always even.
1375 if (remainder >= power && (remainder > power || ((uint)low64 & 1) > 0))
1378 scale = DEC_SCALE_MAX;
1381 d1.uflags = ((d2.uflags ^ d1.uflags) & SignMask) | ((uint)scale << ScaleShift);
1386 // Left value is 32-bit, result fits in 4 uints
1387 tmp = UInt32x32To64(d1.Low, d2.Low);
1388 bufProd.U0 = (uint)tmp;
1390 tmp = UInt32x32To64(d1.Low, d2.Mid) + (tmp >> 32);
1391 bufProd.U1 = (uint)tmp;
1396 tmp += UInt32x32To64(d1.Low, d2.High);
1397 if (tmp > uint.MaxValue)
1399 bufProd.Mid64 = tmp;
1404 bufProd.U2 = (uint)tmp;
1408 else if ((d2.High | d2.Mid) == 0)
1410 // Right value is 32-bit, result fits in 4 uints
1411 tmp = UInt32x32To64(d2.Low, d1.Low);
1412 bufProd.U0 = (uint)tmp;
1414 tmp = UInt32x32To64(d2.Low, d1.Mid) + (tmp >> 32);
1415 bufProd.U1 = (uint)tmp;
1420 tmp += UInt32x32To64(d2.Low, d1.High);
1421 if (tmp > uint.MaxValue)
1423 bufProd.Mid64 = tmp;
1428 bufProd.U2 = (uint)tmp;
1433 // Both operands have bits set in the upper 64 bits.
1435 // Compute and accumulate the 9 partial products into a
1436 // 192-bit (24-byte) result.
1438 // [l-h][l-m][l-l] left high, middle, low
1439 // x [r-h][r-m][r-l] right high, middle, low
1440 // ------------------------------
1442 // [0-h][0-l] l-l * r-l
1443 // [1ah][1al] l-l * r-m
1444 // [1bh][1bl] l-m * r-l
1445 // [2ah][2al] l-m * r-m
1446 // [2bh][2bl] l-l * r-h
1447 // [2ch][2cl] l-h * r-l
1448 // [3ah][3al] l-m * r-h
1449 // [3bh][3bl] l-h * r-m
1450 // [4-h][4-l] l-h * r-h
1451 // ------------------------------
1452 // [p-5][p-4][p-3][p-2][p-1][p-0] prod[] array
1455 tmp = UInt32x32To64(d1.Low, d2.Low);
1456 bufProd.U0 = (uint)tmp;
1458 ulong tmp2 = UInt32x32To64(d1.Low, d2.Mid) + (tmp >> 32);
1460 tmp = UInt32x32To64(d1.Mid, d2.Low);
1461 tmp += tmp2; // this could generate carry
1462 bufProd.U1 = (uint)tmp;
1463 if (tmp < tmp2) // detect carry
1464 tmp2 = (tmp >> 32) | (1UL << 32);
1468 tmp = UInt32x32To64(d1.Mid, d2.Mid) + tmp2;
1470 if ((d1.High | d2.High) > 0)
1472 // Highest 32 bits is non-zero. Calculate 5 more partial products.
1474 tmp2 = UInt32x32To64(d1.Low, d2.High);
1475 tmp += tmp2; // this could generate carry
1477 if (tmp < tmp2) // detect carry
1480 tmp2 = UInt32x32To64(d1.High, d2.Low);
1481 tmp += tmp2; // this could generate carry
1482 bufProd.U2 = (uint)tmp;
1483 if (tmp < tmp2) // detect carry
1485 tmp2 = ((ulong)tmp3 << 32) | (tmp >> 32);
1487 tmp = UInt32x32To64(d1.Mid, d2.High);
1488 tmp += tmp2; // this could generate carry
1490 if (tmp < tmp2) // detect carry
1493 tmp2 = UInt32x32To64(d1.High, d2.Mid);
1494 tmp += tmp2; // this could generate carry
1495 bufProd.U3 = (uint)tmp;
1496 if (tmp < tmp2) // detect carry
1498 tmp = ((ulong)tmp3 << 32) | (tmp >> 32);
1500 bufProd.High64 = UInt32x32To64(d1.High, d2.High) + tmp;
1506 bufProd.Mid64 = tmp;
1511 // Check for leading zero uints on the product
1513 uint* product = (uint*)&bufProd;
1514 while (product[(int)hiProd] == 0)
1522 if (hiProd > 2 || scale > DEC_SCALE_MAX)
1524 scale = ScaleResult(&bufProd, hiProd, scale);
1527 d1.Low64 = bufProd.Low64;
1528 d1.High = bufProd.U2;
1529 d1.uflags = ((d2.uflags ^ d1.uflags) & SignMask) | ((uint)scale << ScaleShift);
1537 /// Convert float to Decimal
1539 internal static void VarDecFromR4(float input, out DecCalc result)
1543 // The most we can scale by is 10^28, which is just slightly more
1544 // than 2^93. So a float with an exponent of -94 could just
1545 // barely reach 0.5, but smaller exponents will always round to zero.
1547 const uint SNGBIAS = 126;
1548 int exp = (int)(GetExponent(input) - SNGBIAS);
1550 return; // result should be zeroed out
1553 Number.ThrowOverflowException(TypeCode.Decimal);
1562 // Round the input to a 7-digit integer. The R4 format has
1563 // only 7 digits of precision, and we want to keep garbage digits
1564 // out of the Decimal were making.
1566 // Calculate max power of 10 input value could have by multiplying
1567 // the exponent by log10(2). Using scaled integer multiplcation,
1568 // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
1571 int power = 6 - ((exp * 19728) >> 16);
1572 // power is between -22 and 35
1576 // We have less than 7 digits, scale input up.
1578 if (power > DEC_SCALE_MAX)
1579 power = DEC_SCALE_MAX;
1581 dbl *= s_doublePowers10[power];
1585 if (power != -1 || dbl >= 1E7)
1586 dbl /= s_doublePowers10[-power];
1588 power = 0; // didn't scale it
1591 Debug.Assert(dbl < 1E7);
1592 if (dbl < 1E6 && power < DEC_SCALE_MAX)
1596 Debug.Assert(dbl >= 1E6);
1602 // with SSE4.1 support ROUNDSD can be used
1603 if (X86.Sse41.IsSupported)
1604 mant = (uint)(int)Math.Round(dbl);
1607 mant = (uint)(int)dbl;
1608 dbl -= (int)mant; // difference between input & integer
1609 if (dbl > 0.5 || dbl == 0.5 && (mant & 1) != 0)
1614 return; // result should be zeroed out
1618 // Add -power factors of 10, -power <= (29 - 7) = 22.
1623 result.Low64 = UInt32x32To64(mant, s_powers10[power]);
1627 // Have a big power of 10.
1631 ulong low64 = UInt32x32To64(mant, s_powers10[power - 18]);
1632 UInt64x64To128(low64, TenToPowerEighteen, ref result);
1636 ulong low64 = UInt32x32To64(mant, s_powers10[power - 9]);
1637 ulong hi64 = UInt32x32To64(TenToPowerNine, (uint)(low64 >> 32));
1638 low64 = UInt32x32To64(TenToPowerNine, (uint)low64);
1639 result.Low = (uint)low64;
1640 hi64 += low64 >> 32;
1641 result.Mid = (uint)hi64;
1643 result.High = (uint)hi64;
1649 // Factor out powers of 10 to reduce the scale, if possible.
1650 // The maximum number we could factor out would be 6. This
1651 // comes from the fact we have a 7-digit number, and the
1652 // MSD must be non-zero -- but the lower 6 digits could be
1653 // zero. Note also the scale factor is never negative, so
1654 // we can't scale by any more than the power we used to
1661 if ((mant & 0xF) == 0 && lmax >= 4)
1663 const uint den = 10000;
1664 uint div = mant / den;
1665 if (mant == div * den)
1673 if ((mant & 3) == 0 && lmax >= 2)
1675 const uint den = 100;
1676 uint div = mant / den;
1677 if (mant == div * den)
1685 if ((mant & 1) == 0 && lmax >= 1)
1687 const uint den = 10;
1688 uint div = mant / den;
1689 if (mant == div * den)
1696 flags |= (uint)power << ScaleShift;
1700 result.uflags = flags;
1704 /// Convert double to Decimal
1706 internal static void VarDecFromR8(double input, out DecCalc result)
1710 // The most we can scale by is 10^28, which is just slightly more
1711 // than 2^93. So a float with an exponent of -94 could just
1712 // barely reach 0.5, but smaller exponents will always round to zero.
1714 const uint DBLBIAS = 1022;
1715 int exp = (int)(GetExponent(input) - DBLBIAS);
1717 return; // result should be zeroed out
1720 Number.ThrowOverflowException(TypeCode.Decimal);
1729 // Round the input to a 15-digit integer. The R8 format has
1730 // only 15 digits of precision, and we want to keep garbage digits
1731 // out of the Decimal were making.
1733 // Calculate max power of 10 input value could have by multiplying
1734 // the exponent by log10(2). Using scaled integer multiplcation,
1735 // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
1738 int power = 14 - ((exp * 19728) >> 16);
1739 // power is between -14 and 43
1743 // We have less than 15 digits, scale input up.
1745 if (power > DEC_SCALE_MAX)
1746 power = DEC_SCALE_MAX;
1748 dbl *= s_doublePowers10[power];
1752 if (power != -1 || dbl >= 1E15)
1753 dbl /= s_doublePowers10[-power];
1755 power = 0; // didn't scale it
1758 Debug.Assert(dbl < 1E15);
1759 if (dbl < 1E14 && power < DEC_SCALE_MAX)
1763 Debug.Assert(dbl >= 1E14);
1769 // with SSE4.1 support ROUNDSD can be used
1770 if (X86.Sse41.IsSupported)
1771 mant = (ulong)(long)Math.Round(dbl);
1774 mant = (ulong)(long)dbl;
1775 dbl -= (long)mant; // difference between input & integer
1776 if (dbl > 0.5 || dbl == 0.5 && (mant & 1) != 0)
1781 return; // result should be zeroed out
1785 // Add -power factors of 10, -power <= (29 - 15) = 14.
1790 var pow10 = s_powers10[power];
1791 ulong low64 = UInt32x32To64((uint)mant, pow10);
1792 ulong hi64 = UInt32x32To64((uint)(mant >> 32), pow10);
1793 result.Low = (uint)low64;
1794 hi64 += low64 >> 32;
1795 result.Mid = (uint)hi64;
1797 result.High = (uint)hi64;
1801 // Have a big power of 10.
1803 Debug.Assert(power <= 14);
1804 UInt64x64To128(mant, s_ulongPowers10[power - 1], ref result);
1809 // Factor out powers of 10 to reduce the scale, if possible.
1810 // The maximum number we could factor out would be 14. This
1811 // comes from the fact we have a 15-digit number, and the
1812 // MSD must be non-zero -- but the lower 14 digits could be
1813 // zero. Note also the scale factor is never negative, so
1814 // we can't scale by any more than the power we used to
1821 if ((byte)mant == 0 && lmax >= 8)
1823 const uint den = 100000000;
1824 ulong div = mant / den;
1825 if ((uint)mant == (uint)(div * den))
1833 if (((uint)mant & 0xF) == 0 && lmax >= 4)
1835 const uint den = 10000;
1836 ulong div = mant / den;
1837 if ((uint)mant == (uint)(div * den))
1845 if (((uint)mant & 3) == 0 && lmax >= 2)
1847 const uint den = 100;
1848 ulong div = mant / den;
1849 if ((uint)mant == (uint)(div * den))
1857 if (((uint)mant & 1) == 0 && lmax >= 1)
1859 const uint den = 10;
1860 ulong div = mant / den;
1861 if ((uint)mant == (uint)(div * den))
1868 flags |= (uint)power << ScaleShift;
1869 result.Low64 = mant;
1872 result.uflags = flags;
1876 /// Convert Decimal to float
1878 internal static float VarR4FromDec(in decimal value)
1880 return (float)VarR8FromDec(in value);
1884 /// Convert Decimal to double
1886 internal static double VarR8FromDec(in decimal value)
1888 // Value taken via reverse engineering the double that corresponds to 2^64. (oleaut32 has ds2to64 = DEFDS(0, 0, DBLBIAS + 65, 0))
1889 const double ds2to64 = 1.8446744073709552e+019;
1891 double dbl = ((double)value.Low64 +
1892 (double)value.High * ds2to64) / s_doublePowers10[value.Scale];
1894 if (value.IsNegative)
1900 internal static int GetHashCode(in decimal d)
1902 if ((d.Low | d.Mid | d.High) == 0)
1905 uint flags = (uint)d.flags;
1906 if ((flags & ScaleMask) == 0 || (d.Low & 1) != 0)
1907 return (int)(flags ^ d.High ^ d.Mid ^ d.Low);
1909 int scale = (byte)(flags >> ScaleShift);
1911 ulong high64 = ((ulong)d.High << 32) | d.Mid;
1913 Unscale(ref low, ref high64, ref scale);
1915 flags = ((flags) & ~ScaleMask) | (uint)scale << ScaleShift;
1916 return (int)(flags ^ (uint)(high64 >> 32) ^ (uint)high64 ^ low);
1920 /// Divides two decimal values.
1921 /// On return, d1 contains the result of the operation.
1923 internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2)
1926 _ = &bufQuo; // workaround for CS0165
1927 DebugPoison(ref bufQuo);
1932 int scale = (sbyte)(d1.uflags - d2.uflags >> ScaleShift);
1933 bool unscale = false;
1936 if ((d2.High | d2.Mid) == 0)
1938 // Divisor is only 32 bits. Easy divide.
1942 throw new DivideByZeroException();
1944 bufQuo.Low64 = d1.Low64;
1945 bufQuo.U2 = d1.High;
1946 uint remainder = Div96By32(ref bufQuo, den);
1954 curScale = Math.Min(9, -scale);
1960 // We need to unscale if and only if we have a non-zero remainder
1963 // We have computed a quotient based on the natural scale
1964 // ( <dividend scale> - <divisor scale> ). We have a non-zero
1965 // remainder, so now we should increase the scale if possible to
1966 // include more quotient bits.
1968 // If it doesn't cause overflow, we'll loop scaling by 10^9 and
1969 // computing more quotient bits as long as the remainder stays
1970 // non-zero. If scaling by that much would cause overflow, we'll
1971 // drop out of the loop and scale by as much as we can.
1973 // Scaling by 10^9 will overflow if bufQuo[2].bufQuo[1] >= 2^32 / 10^9
1974 // = 4.294 967 296. So the upper limit is bufQuo[2] == 4 and
1975 // bufQuo[1] == 0.294 967 296 * 2^32 = 1,266,874,889.7+. Since
1976 // quotient bits in bufQuo[0] could be all 1's, then 1,266,874,888
1977 // is the largest value in bufQuo[1] (when bufQuo[2] == 4) that is
1978 // assured not to overflow.
1980 if (scale == DEC_SCALE_MAX || (curScale = SearchScale(ref bufQuo, scale)) == 0)
1982 // No more scaling to be done, but remainder is non-zero.
1985 tmp = remainder << 1;
1986 if (tmp < remainder || tmp >= den && (tmp > den || (bufQuo.U0 & 1) != 0))
1992 power = s_powers10[curScale];
1995 if (IncreaseScale(ref bufQuo, power) != 0)
1998 ulong num = UInt32x32To64(remainder, power);
1999 // TODO: https://github.com/dotnet/coreclr/issues/3439
2000 uint div = (uint)(num / den);
2001 remainder = (uint)num - div * den;
2003 if (!Add32To96(ref bufQuo, div))
2005 scale = OverflowUnscale(ref bufQuo, scale, remainder != 0);
2012 // Divisor has bits set in the upper 64 bits.
2014 // Divisor must be fully normalized (shifted so bit 31 of the most
2015 // significant uint is 1). Locate the MSB so we know how much to
2016 // normalize by. The dividend will be shifted by the same amount so
2017 // the quotient is not changed.
2023 curScale = BitOperations.LeadingZeroCount(tmp);
2025 // Shift both dividend and divisor left by curScale.
2028 _ = &bufRem; // workaround for CS0165
2029 DebugPoison(ref bufRem);
2031 bufRem.Low64 = d1.Low64 << curScale;
2032 bufRem.High64 = (d1.Mid + ((ulong)d1.High << 32)) >> (32 - curScale);
2034 ulong divisor = d2.Low64 << curScale;
2038 // Have a 64-bit divisor in sdlDivisor. The remainder
2039 // (currently 96 bits spread over 4 uints) will be < divisor.
2042 bufQuo.U1 = Div96By64(ref *(Buf12*)&bufRem.U1, divisor);
2043 bufQuo.U0 = Div96By64(ref *(Buf12*)&bufRem, divisor);
2047 if (bufRem.Low64 == 0)
2051 curScale = Math.Min(9, -scale);
2057 // We need to unscale if and only if we have a non-zero remainder
2060 // Remainder is non-zero. Scale up quotient and remainder by
2061 // powers of 10 so we can compute more significant bits.
2063 if (scale == DEC_SCALE_MAX || (curScale = SearchScale(ref bufQuo, scale)) == 0)
2065 // No more scaling to be done, but remainder is non-zero.
2068 ulong tmp64 = bufRem.Low64;
2069 if ((long)tmp64 < 0 || (tmp64 <<= 1) > divisor ||
2070 (tmp64 == divisor && (bufQuo.U0 & 1) != 0))
2076 power = s_powers10[curScale];
2079 if (IncreaseScale(ref bufQuo, power) != 0)
2082 IncreaseScale64(ref *(Buf12*)&bufRem, power);
2083 tmp = Div96By64(ref *(Buf12*)&bufRem, divisor);
2084 if (!Add32To96(ref bufQuo, tmp))
2086 scale = OverflowUnscale(ref bufQuo, scale, bufRem.Low64 != 0);
2093 // Have a 96-bit divisor in bufDivisor.
2095 // Start by finishing the shift left by curScale.
2098 _ = &bufDivisor; // workaround for CS0165
2099 DebugPoison(ref bufDivisor);
2101 bufDivisor.Low64 = divisor;
2102 bufDivisor.U2 = (uint)((d2.Mid + ((ulong)d2.High << 32)) >> (32 - curScale));
2104 // The remainder (currently 96 bits spread over 4 uints) will be < divisor.
2106 bufQuo.Low64 = Div128By96(ref bufRem, ref bufDivisor);
2111 if ((bufRem.Low64 | bufRem.U2) == 0)
2115 curScale = Math.Min(9, -scale);
2121 // We need to unscale if and only if we have a non-zero remainder
2124 // Remainder is non-zero. Scale up quotient and remainder by
2125 // powers of 10 so we can compute more significant bits.
2127 if (scale == DEC_SCALE_MAX || (curScale = SearchScale(ref bufQuo, scale)) == 0)
2129 // No more scaling to be done, but remainder is non-zero.
2132 if ((int)bufRem.U2 < 0)
2137 tmp = bufRem.U1 >> 31;
2139 bufRem.U2 = (bufRem.U2 << 1) + tmp;
2141 if (bufRem.U2 > bufDivisor.U2 || bufRem.U2 == bufDivisor.U2 &&
2142 (bufRem.Low64 > bufDivisor.Low64 || bufRem.Low64 == bufDivisor.Low64 &&
2143 (bufQuo.U0 & 1) != 0))
2149 power = s_powers10[curScale];
2152 if (IncreaseScale(ref bufQuo, power) != 0)
2155 bufRem.U3 = IncreaseScale(ref *(Buf12*)&bufRem, power);
2156 tmp = Div128By96(ref bufRem, ref bufDivisor);
2157 if (!Add32To96(ref bufQuo, tmp))
2159 scale = OverflowUnscale(ref bufQuo, scale, (bufRem.Low64 | bufRem.High64) != 0);
2169 uint low = bufQuo.U0;
2170 ulong high64 = bufQuo.High64;
2171 Unscale(ref low, ref high64, ref scale);
2173 d1.Mid = (uint)high64;
2174 d1.High = (uint)(high64 >> 32);
2178 d1.Low64 = bufQuo.Low64;
2179 d1.High = bufQuo.U2;
2182 d1.uflags = ((d1.uflags ^ d2.uflags) & SignMask) | ((uint)scale << ScaleShift);
2187 if (++bufQuo.Low64 == 0 && ++bufQuo.U2 == 0)
2189 scale = OverflowUnscale(ref bufQuo, scale, true);
2195 Number.ThrowOverflowException(TypeCode.Decimal);
2199 /// Computes the remainder between two decimals.
2200 /// On return, d1 contains the result of the operation and d2 is trashed.
2202 internal static void VarDecMod(ref DecCalc d1, ref DecCalc d2)
2204 if ((d2.ulo | d2.umid | d2.uhi) == 0)
2205 throw new DivideByZeroException();
2207 if ((d1.ulo | d1.umid | d1.uhi) == 0)
2210 // In the operation x % y the sign of y does not matter. Result will have the sign of x.
2211 d2.uflags = (d2.uflags & ~SignMask) | (d1.uflags & SignMask);
2213 int cmp = VarDecCmpSub(in Unsafe.As<DecCalc, decimal>(ref d1), in Unsafe.As<DecCalc, decimal>(ref d2));
2219 if (d2.uflags > d1.uflags)
2220 d1.uflags = d2.uflags;
2223 if ((cmp ^ (int)(d1.uflags & SignMask)) < 0)
2226 // The divisor is smaller than the dividend and both are non-zero. Calculate the integer remainder using the larger scaling factor.
2228 int scale = (sbyte)(d1.uflags - d2.uflags >> ScaleShift);
2231 // Divisor scale can always be increased to dividend scale for remainder calculation.
2234 uint power = scale >= MaxInt32Scale ? TenToPowerNine : s_powers10[scale];
2235 ulong tmp = UInt32x32To64(d2.Low, power);
2238 tmp += (d2.Mid + ((ulong)d2.High << 32)) * power;
2240 d2.High = (uint)(tmp >> 32);
2241 } while ((scale -= MaxInt32Scale) > 0);
2249 d1.uflags = d2.uflags;
2250 // Try to scale up dividend to match divisor.
2252 unsafe { _ = &bufQuo; } // workaround for CS0165
2253 DebugPoison(ref bufQuo);
2255 bufQuo.Low64 = d1.Low64;
2256 bufQuo.U2 = d1.High;
2259 int iCurScale = SearchScale(ref bufQuo, DEC_SCALE_MAX + scale);
2262 uint power = iCurScale >= MaxInt32Scale ? TenToPowerNine : s_powers10[iCurScale];
2264 ulong tmp = UInt32x32To64(bufQuo.U0, power);
2265 bufQuo.U0 = (uint)tmp;
2267 bufQuo.High64 = tmp + bufQuo.High64 * power;
2268 if (power != TenToPowerNine)
2272 d1.Low64 = bufQuo.Low64;
2273 d1.High = bufQuo.U2;
2278 Debug.Assert(d2.High == 0);
2279 Debug.Assert(scale == 0);
2280 d1.Low64 %= d2.Low64;
2283 else if ((d2.High | d2.Mid) == 0)
2286 ulong tmp = ((ulong)d1.High << 32) | d1.Mid;
2287 tmp = ((tmp % den) << 32) | d1.Low;
2288 d1.Low64 = tmp % den;
2293 VarDecModFull(ref d1, ref d2, scale);
2296 } while (scale < 0);
2299 private static unsafe void VarDecModFull(ref DecCalc d1, ref DecCalc d2, int scale)
2301 // Divisor has bits set in the upper 64 bits.
2303 // Divisor must be fully normalized (shifted so bit 31 of the most significant uint is 1).
2304 // Locate the MSB so we know how much to normalize by.
2305 // The dividend will be shifted by the same amount so the quotient is not changed.
2310 int shift = BitOperations.LeadingZeroCount(tmp);
2313 _ = &b; // workaround for CS0165
2316 b.Buf24.Low64 = d1.Low64 << shift;
2317 b.Buf24.Mid64 = (d1.Mid + ((ulong)d1.High << 32)) >> (32 - shift);
2319 // The dividend might need to be scaled up to 221 significant bits.
2320 // Maximum scaling is required when the divisor is 2^64 with scale 28 and is left shifted 31 bits
2321 // and the dividend is decimal.MaxValue: (2^96 - 1) * 10^28 << 31 = 221 bits.
2325 uint power = scale <= -MaxInt32Scale ? TenToPowerNine : s_powers10[-scale];
2326 uint* buf = (uint*)&b;
2327 ulong tmp64 = UInt32x32To64(b.Buf24.U0, power);
2328 b.Buf24.U0 = (uint)tmp64;
2329 for (int i = 1; i <= high; i++)
2332 tmp64 += UInt32x32To64(buf[i], power);
2333 buf[i] = (uint)tmp64;
2335 // The high bit of the dividend must not be set.
2336 if (tmp64 > int.MaxValue)
2338 Debug.Assert(high + 1 < b.Length);
2339 buf[++high] = (uint)(tmp64 >> 32);
2342 scale += MaxInt32Scale;
2347 ulong divisor = d2.Low64 << shift;
2351 Div96By64(ref *(Buf12*)&b.Buf24.U4, divisor);
2354 Div96By64(ref *(Buf12*)&b.Buf24.U3, divisor);
2357 Div96By64(ref *(Buf12*)&b.Buf24.U2, divisor);
2360 Div96By64(ref *(Buf12*)&b.Buf24.U1, divisor);
2361 Div96By64(ref *(Buf12*)&b, divisor);
2363 d1.Low64 = b.Buf24.Low64 >> shift;
2369 _ = &bufDivisor; // workaround for CS0165
2370 DebugPoison(ref bufDivisor);
2372 bufDivisor.Low64 = d2.Low64 << shift;
2373 bufDivisor.U2 = (uint)((d2.Mid + ((ulong)d2.High << 32)) >> (32 - shift));
2378 Div128By96(ref *(Buf16*)&b.Buf24.U3, ref bufDivisor);
2381 Div128By96(ref *(Buf16*)&b.Buf24.U2, ref bufDivisor);
2384 Div128By96(ref *(Buf16*)&b.Buf24.U1, ref bufDivisor);
2387 Div128By96(ref *(Buf16*)&b, ref bufDivisor);
2389 d1.Low64 = (b.Buf24.Low64 >> shift) + ((ulong)b.Buf24.U2 << (32 - shift) << 32);
2390 d1.High = b.Buf24.U2 >> shift;
2394 // Does an in-place round by the specified scale
2395 internal static void InternalRound(ref DecCalc d, uint scale, MidpointRounding mode)
2397 // the scale becomes the desired decimal count
2398 d.uflags -= scale << ScaleShift;
2400 uint remainder, sticky = 0, power;
2401 // First divide the value by constant 10^9 up to three times
2402 while (scale >= MaxInt32Scale)
2404 scale -= MaxInt32Scale;
2406 const uint divisor = TenToPowerNine;
2410 ulong tmp = d.Low64;
2411 ulong div = tmp / divisor;
2413 remainder = (uint)(tmp - div * divisor);
2418 d.uhi = q = n / divisor;
2419 remainder = n - q * divisor;
2421 if ((n | remainder) != 0)
2423 d.umid = q = (uint)((((ulong)remainder << 32) | n) / divisor);
2424 remainder = n - q * divisor;
2427 if ((n | remainder) != 0)
2429 d.ulo = q = (uint)((((ulong)remainder << 32) | n) / divisor);
2430 remainder = n - q * divisor;
2435 goto checkRemainder;
2436 sticky |= remainder;
2440 power = s_powers10[scale];
2441 // TODO: https://github.com/dotnet/coreclr/issues/3439
2445 ulong tmp = d.Low64;
2448 if (mode <= MidpointRounding.ToZero)
2451 goto checkRemainder;
2453 ulong div = tmp / power;
2455 remainder = (uint)(tmp - div * power);
2460 d.uhi = q = n / power;
2461 remainder = n - q * power;
2463 if ((n | remainder) != 0)
2465 d.umid = q = (uint)((((ulong)remainder << 32) | n) / power);
2466 remainder = n - q * power;
2469 if ((n | remainder) != 0)
2471 d.ulo = q = (uint)((((ulong)remainder << 32) | n) / power);
2472 remainder = n - q * power;
2478 if (mode == MidpointRounding.ToZero)
2480 else if (mode == MidpointRounding.ToEven)
2482 // To do IEEE rounding, we add LSB of result to sticky bits so either causes round up if remainder * 2 == last divisor.
2484 if ((sticky | d.ulo & 1) != 0)
2486 if (power >= remainder)
2489 else if (mode == MidpointRounding.AwayFromZero)
2491 // Round away from zero at the mid point.
2493 if (power > remainder)
2496 else if (mode == MidpointRounding.ToNegativeInfinity)
2498 // Round toward -infinity if we have chopped off a non-zero amount from a negative value.
2499 if ((remainder | sticky) == 0 || !d.IsNegative)
2504 Debug.Assert(mode == MidpointRounding.ToPositiveInfinity);
2505 // Round toward infinity if we have chopped off a non-zero amount from a positive value.
2506 if ((remainder | sticky) == 0 || d.IsNegative)
2515 internal static uint DecDivMod1E9(ref DecCalc value)
2517 ulong high64 = ((ulong)value.uhi << 32) + value.umid;
2518 ulong div64 = high64 / TenToPowerNine;
2519 value.uhi = (uint)(div64 >> 32);
2520 value.umid = (uint)div64;
2522 ulong num = ((high64 - (uint)div64 * TenToPowerNine) << 32) + value.ulo;
2523 uint div = (uint)(num / TenToPowerNine);
2525 return (uint)num - div * TenToPowerNine;
2530 public readonly uint Hi;
2531 public readonly ulong MidLo;
2533 public PowerOvfl(uint hi, uint mid, uint lo)
2536 MidLo = ((ulong)mid << 32) + lo;
2540 static readonly PowerOvfl[] PowerOvflValues = new[]
2542 // This is a table of the largest values that can be in the upper two
2543 // uints of a 96-bit number that will not overflow when multiplied
2544 // by a given power. For the upper word, this is a table of
2545 // 2^32 / 10^n for 1 <= n <= 8. For the lower word, this is the
2546 // remaining fraction part * 2^32. 2^32 = 4294967296.
2548 new PowerOvfl(429496729, 2576980377, 2576980377), // 10^1 remainder 0.6
2549 new PowerOvfl(42949672, 4123168604, 687194767), // 10^2 remainder 0.16
2550 new PowerOvfl(4294967, 1271310319, 2645699854), // 10^3 remainder 0.616
2551 new PowerOvfl(429496, 3133608139, 694066715), // 10^4 remainder 0.1616
2552 new PowerOvfl(42949, 2890341191, 2216890319), // 10^5 remainder 0.51616
2553 new PowerOvfl(4294, 4154504685, 2369172679), // 10^6 remainder 0.551616
2554 new PowerOvfl(429, 2133437386, 4102387834), // 10^7 remainder 0.9551616
2555 new PowerOvfl(42, 4078814305, 410238783), // 10^8 remainder 0.09991616
2558 [StructLayout(LayoutKind.Explicit)]
2559 private struct Buf12
2561 [FieldOffset(0 * 4)]
2563 [FieldOffset(1 * 4)]
2565 [FieldOffset(2 * 4)]
2569 private ulong ulo64LE;
2571 private ulong uhigh64LE;
2576 get => ((ulong)U1 << 32) | U0;
2577 set { U1 = (uint)(value >> 32); U0 = (uint)value; }
2580 set => ulo64LE = value;
2585 /// U1-U2 combined (overlaps with Low64)
2590 get => ((ulong)U2 << 32) | U1;
2591 set { U2 = (uint)(value >> 32); U1 = (uint)value; }
2594 set => uhigh64LE = value;
2599 [StructLayout(LayoutKind.Explicit)]
2600 private struct Buf16
2602 [FieldOffset(0 * 4)]
2604 [FieldOffset(1 * 4)]
2606 [FieldOffset(2 * 4)]
2608 [FieldOffset(3 * 4)]
2611 [FieldOffset(0 * 8)]
2612 private ulong ulo64LE;
2613 [FieldOffset(1 * 8)]
2614 private ulong uhigh64LE;
2619 get => ((ulong)U1 << 32) | U0;
2620 set { U1 = (uint)(value >> 32); U0 = (uint)value; }
2623 set => ulo64LE = value;
2630 get => ((ulong)U3 << 32) | U2;
2631 set { U3 = (uint)(value >> 32); U2 = (uint)value; }
2634 set => uhigh64LE = value;
2639 [StructLayout(LayoutKind.Explicit)]
2640 private struct Buf24
2642 [FieldOffset(0 * 4)]
2644 [FieldOffset(1 * 4)]
2646 [FieldOffset(2 * 4)]
2648 [FieldOffset(3 * 4)]
2650 [FieldOffset(4 * 4)]
2652 [FieldOffset(5 * 4)]
2655 [FieldOffset(0 * 8)]
2656 private ulong ulo64LE;
2657 [FieldOffset(1 * 8)]
2658 private ulong umid64LE;
2659 [FieldOffset(2 * 8)]
2660 private ulong uhigh64LE;
2665 get => ((ulong)U1 << 32) | U0;
2666 set { U1 = (uint)(value >> 32); U0 = (uint)value; }
2669 set => ulo64LE = value;
2676 get => ((ulong)U3 << 32) | U2;
2677 set { U3 = (uint)(value >> 32); U2 = (uint)value; }
2680 set => umid64LE = value;
2687 get => ((ulong)U5 << 32) | U4;
2688 set { U5 = (uint)(value >> 32); U4 = (uint)value; }
2691 set => uhigh64LE = value;
2695 public int Length => 6;
2698 private struct Buf28
2703 public int Length => 7;