1 //------------------------------------------------------------------------------
2 // <copyright file="XPathConvert.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
9 * Routines used to manipulate IEEE 754 double-precision numbers, taken from JScript codebase.
11 * Define NOPARSE if you do not need FloatingDecimal -> double conversions
15 using System.Diagnostics;
16 using System.Globalization;
18 namespace System.Xml.Xsl {
21 * Converts according to XPath/XSLT rules.
23 internal static class XPathConvert {
25 public static uint DblHi(double dbl) {
26 return (uint)(BitConverter.DoubleToInt64Bits(dbl) >> 32);
29 public static uint DblLo(double dbl) {
30 return (uint)BitConverter.DoubleToInt64Bits(dbl);
33 // Returns true if value is infinite or NaN (exponent bits are all ones)
34 public static bool IsSpecial(double dbl) {
35 return 0 == (~DblHi(dbl) & 0x7FF00000);
39 // Returns the next representable neighbor of x in the direction toward y
40 public static double NextAfter(double x, double y) {
43 if (Double.IsNaN(x)) {
46 if (Double.IsNaN(y)) {
53 bits = BitConverter.DoubleToInt64Bits(y) & 1L<<63;
54 return BitConverter.Int64BitsToDouble(bits | 1);
57 // At this point x!=y, and x!=0. x can be treated as a 64bit
58 // integer in sign/magnitude representation. To get the next
59 // representable neighbor we add or subtract one from this
62 bits = BitConverter.DoubleToInt64Bits(x);
63 if (0 < x && x < y || 0 > x && x > y) {
68 return BitConverter.Int64BitsToDouble(bits);
71 public static double Succ(double x) {
72 return NextAfter(x, Double.PositiveInfinity);
75 public static double Pred(double x) {
76 return NextAfter(x, Double.NegativeInfinity);
80 // Small powers of ten. These are all the powers of ten that have an exact
81 // representation in IEEE double precision format.
82 public static readonly double[] C10toN = {
83 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
84 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
88 // Returns 1 if argument is non-zero, and 0 otherwise
89 public static uint NotZero(uint u) {
90 return 0 != u ? 1u : 0u;
93 /* ----------------------------------------------------------------------------
96 Add two unsigned ints and return the carry bit.
98 public static uint AddU(ref uint u1, uint u2) {
100 return u1 < u2 ? 1u : 0u;
103 /* ----------------------------------------------------------------------------
106 Multiply two unsigned ints. Return the low uint and fill uHi with
109 public static uint MulU(uint u1, uint u2, out uint uHi) {
110 ulong result = (ulong)u1 * u2;
111 uHi = (uint)(result >> 32);
115 /* ----------------------------------------------------------------------------
118 Return a count of the number of leading 0 bits in u.
120 public static int CbitZeroLeft(uint u) {
123 if (0 == (u & 0xFFFF0000)) {
127 if (0 == (u & 0xFF000000)) {
131 if (0 == (u & 0xF0000000)) {
135 if (0 == (u & 0xC0000000)) {
139 if (0 == (u & 0x80000000)) {
143 Debug.Assert(0 != (u & 0x80000000));
148 /* ----------------------------------------------------------------------------
151 If dbl is a whole number in the range of INT_MIN to INT_MAX, return true
152 and the integer in value. Otherwise, return false.
154 public static bool IsInteger(double dbl, out int value) {
155 if (!IsSpecial(dbl)) {
157 double dblRound = (double) i;
159 if (dbl == dblRound) {
169 * Implementation of a big floating point number used to ensure adequate
170 * precision when performing calculations.
175 private struct BigNumber {
181 // This is a bound on the absolute value of the error. It is based at
182 // one bit before the least significant bit of u0.
185 public uint Error { get { return error; } }
187 public BigNumber(uint u0, uint u1, uint u2, int exp, uint error) {
195 #if !NOPARSE || DEBUG
196 // Set the value from floating decimal
197 public BigNumber(FloatingDecimal dec) {
198 Debug.Assert(dec.MantissaSize > 0);
200 int ib, exponent, mantissaSize, wT;
202 BigNumber[] TenPowers;
205 exponent = dec.Exponent;
206 mantissaSize = dec.MantissaSize;
208 // Record the first digit
209 Debug.Assert(dec[ib] > 0 && dec[ib] <= 9);
210 this.u2 = (uint)(dec[ib]) << 28;
218 while (++ib < mantissaSize) {
219 Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
220 uExtra = MulTenAdd(dec[ib]);
223 // We've filled up our precision.
225 if (ib < mantissaSize - 1) {
226 // There are more digits, so add another error bit just for
234 // Now multiply by 10^exp
240 TenPowers = TenPowersNeg;
241 exponent = -exponent;
243 TenPowers = TenPowersPos;
246 Debug.Assert(exponent > 0 && exponent < 512);
247 wT = exponent & 0x1F;
249 Mul(ref TenPowers[wT - 1]);
252 wT = (exponent >> 5) & 0x0F;
254 Mul(ref TenPowers[wT + 30]);
258 // Multiply by ten and add a base 10 digit.
259 private unsafe uint MulTenAdd(uint digit) {
260 Debug.Assert(digit <= 9);
261 Debug.Assert(0 != (this.u2 & 0x80000000));
263 // First "multipy" by eight
265 Debug.Assert(this.exp >= 4);
267 // Initialize the carry values based on digit and exp.
268 uint *rgu = stackalloc uint[5];
269 for (int i = 0; i < 5; i++) {
273 int idx = 3 - (this.exp >> 5);
277 int ibit = this.exp & 0x1F;
279 rgu[idx + 1] = digit >> ibit;
281 rgu[idx] = digit << (32 - ibit);
284 rgu[idx] = digit << (32 - ibit);
289 // Shift and add to multiply by ten.
290 rgu[1] += AddU(ref rgu[0], this.u0 << 30);
291 rgu[2] += AddU(ref this.u0, (this.u0 >> 2) + (this.u1 << 30));
293 rgu[2] += AddU(ref this.u0, rgu[1]);
295 rgu[3] += AddU(ref this.u1, (this.u1 >> 2) + (this.u2 << 30));
297 rgu[3] += AddU(ref this.u1, rgu[2]);
299 rgu[4] = AddU(ref this.u2, (this.u2 >> 2) + rgu[3]);
301 // Handle the final carry.
303 Debug.Assert(1 == rgu[4]);
304 rgu[0] = (rgu[0] >> 1) | (rgu[0] & 1) | (this.u0 << 31);
305 this.u0 = (this.u0 >> 1) | (this.u1 << 31);
306 this.u1 = (this.u1 >> 1) | (this.u2 << 31);
307 this.u2 = (this.u2 >> 1) | 0x80000000;
314 // Round based on the given extra data using IEEE round to nearest rule.
315 private void Round(uint uExtra) {
316 if (0 == (uExtra & 0x80000000) || 0 == (uExtra & 0x7FFFFFFF) && 0 == (this.u0 & 1)) {
325 if (0 != AddU(ref this.u0, 1) && 0 != AddU(ref this.u1, 1) && 0 != AddU(ref this.u2, 1)) {
326 Debug.Assert(this.IsZero);
327 this.u2 = 0x80000000;
333 // Test to see if the num is zero. This works even if we're not normalized.
334 private bool IsZero {
336 return (0 == this.u2) && (0 == this.u1) && (0 == this.u0);
340 /* ----------------------------------------------------------------------------
343 Normalize the big number - make sure the high bit is 1 or everything is zero
344 (including the exponent).
346 private void Normalize() {
349 // Normalize mantissa
367 if (0 != (w1 = CbitZeroLeft(this.u2))) {
369 this.u2 = (this.u2 << w1) | (this.u1 >> w2);
370 this.u1 = (this.u1 << w1) | (this.u0 >> w2);
371 this.u0 = (this.u0 << w1);
376 /* ----------------------------------------------------------------------------
379 Multiply this big number by another big number.
381 private void Mul(ref BigNumber numOp) {
382 Debug.Assert(0 != (this.u2 & 0x80000000));
383 Debug.Assert(0 != (numOp.u2 & 0x80000000));
385 //uint *rgu = stackalloc uint[6];
386 uint rgu0 = 0, rgu1 = 0, rgu2 = 0, rgu3 = 0, rgu4 = 0, rgu5 = 0;
390 if (0 != (uT = this.u0)) {
391 uLo = MulU(uT, numOp.u0, out uHi);
395 uLo = MulU(uT, numOp.u1, out uHi);
396 Debug.Assert(uHi < 0xFFFFFFFF);
397 wCarry = AddU(ref rgu1, uLo);
398 AddU(ref rgu2, uHi + wCarry);
400 uLo = MulU(uT, numOp.u2, out uHi);
401 Debug.Assert(uHi < 0xFFFFFFFF);
402 wCarry = AddU(ref rgu2, uLo);
403 AddU(ref rgu3, uHi + wCarry);
406 if (0 != (uT = this.u1)) {
407 uLo = MulU(uT, numOp.u0, out uHi);
408 Debug.Assert(uHi < 0xFFFFFFFF);
409 wCarry = AddU(ref rgu1, uLo);
410 wCarry = AddU(ref rgu2, uHi + wCarry);
411 if (0 != wCarry && 0 != AddU(ref rgu3, 1)) {
414 uLo = MulU(uT, numOp.u1, out uHi);
415 Debug.Assert(uHi < 0xFFFFFFFF);
416 wCarry = AddU(ref rgu2, uLo);
417 wCarry = AddU(ref rgu3, uHi + wCarry);
421 uLo = MulU(uT, numOp.u2, out uHi);
422 Debug.Assert(uHi < 0xFFFFFFFF);
423 wCarry = AddU(ref rgu3, uLo);
424 AddU(ref rgu4, uHi + wCarry);
428 Debug.Assert(0 != uT);
429 uLo = MulU(uT, numOp.u0, out uHi);
430 Debug.Assert(uHi < 0xFFFFFFFF);
431 wCarry = AddU(ref rgu2, uLo);
432 wCarry = AddU(ref rgu3, uHi + wCarry);
433 if (0 != wCarry && 0 != AddU(ref rgu4, 1)) {
436 uLo = MulU(uT, numOp.u1, out uHi);
437 Debug.Assert(uHi < 0xFFFFFFFF);
438 wCarry = AddU(ref rgu3, uLo);
439 wCarry = AddU(ref rgu4, uHi + wCarry);
443 uLo = MulU(uT, numOp.u2, out uHi);
444 Debug.Assert(uHi < 0xFFFFFFFF);
445 wCarry = AddU(ref rgu4, uLo);
446 AddU(ref rgu5, uHi + wCarry);
448 // Compute the new exponent
449 this.exp += numOp.exp;
451 // Accumulate the error. Adding doesn't necessarily give an accurate
452 // bound if both of the errors are bigger than 2.
453 Debug.Assert(this.error <= 2 || numOp.error <= 2);
454 this.error += numOp.error;
456 // Handle rounding and normalize.
457 if (0 == (rgu5 & 0x80000000)) {
458 if (0 != (rgu2 & 0x40000000) &&
459 (0 != (rgu2 & 0xBFFFFFFF) || 0 != rgu1 || 0 != rgu0)) {
461 if (0 != AddU(ref rgu2, 0x40000000)
462 && 0 != AddU(ref rgu3, 1)
463 && 0 != AddU(ref rgu4, 1)
466 if (0 != (rgu5 & 0x80000000)) {
472 // have to shift by one
473 Debug.Assert(0 != (rgu5 & 0x40000000));
474 this.u2 = (rgu5 << 1) | (rgu4 >> 31);
475 this.u1 = (rgu4 << 1) | (rgu3 >> 31);
476 this.u0 = (rgu3 << 1) | (rgu2 >> 31);
480 // Add one for the error.
481 if (0 != (rgu2 & 0x7FFFFFFF) || 0 != rgu1 || 0 != rgu0) {
486 if (0 != (rgu2 & 0x80000000) &&
487 (0 != (rgu3 & 1) || 0 != (rgu2 & 0x7FFFFFFF) ||
488 0 != rgu1 || 0 != rgu0)) {
490 if (0 != AddU(ref rgu3, 1) && 0 != AddU(ref rgu4, 1) && 0 != AddU(ref rgu5, 1)) {
491 Debug.Assert(0 == rgu3);
492 Debug.Assert(0 == rgu4);
493 Debug.Assert(0 == rgu5);
505 // Add one for the error.
506 if (0 != rgu2 || 0 != rgu1 || 0 != rgu0) {
511 // Get the double value.
512 public static explicit operator double(BigNumber bn) {
517 Debug.Assert(0 != (bn.u2 & 0x80000000));
521 return Double.PositiveInfinity;
524 // Round after filling in the bits. In the extra uint, we set the low bit
525 // if there are any extra non-zero bits. This is for breaking the tie when
526 // deciding whether to round up or down.
529 dblHi = ((uint)exp << 20) | ((bn.u2 & 0x7FFFFFFF) >> 11);
530 dblLo = bn.u2 << 21 | bn.u1 >> 11;
531 uEx = bn.u1 << 21 | NotZero(bn.u0);
532 } else if (exp > -20) {
533 // Denormal with some high bits.
535 Debug.Assert(wT >= 12 && wT < 32);
538 dblLo = (bn.u2 << (32 - wT)) | (bn.u1 >> wT);
539 uEx = (bn.u1 << (32 - wT)) | NotZero(bn.u0);
540 } else if (exp == -20) {
541 // Denormal with no high bits.
544 uEx = bn.u1 | (uint)(0 != bn.u0 ? 1 : 0);
545 } else if (exp > -52) {
546 // Denormal with no high bits.
548 Debug.Assert(wT > 0 && wT < 32);
552 uEx = bn.u2 << (32 - wT) | NotZero(bn.u1) | NotZero(bn.u0);
553 } else if (exp == -52) {
554 // Zero unless we round up below.
557 uEx = bn.u2 | NotZero(bn.u1) | NotZero(bn.u0);
563 if (0 != (uEx & 0x80000000) && (0 != (uEx & 0x7FFFFFFF) || 0 != (dblLo & 1))) {
564 // Round up. Note that this works even when we overflow into the
566 if (0 != AddU(ref dblLo, 1)) {
570 return BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
573 // Lop off the integer part and return it.
574 private uint UMod1() {
578 Debug.Assert(this.exp <= 32);
579 uint uT = this.u2 >> (32 - this.exp);
580 this.u2 &= (uint)0x7FFFFFFF >> (this.exp - 1);
585 // If error is not zero, add it and set error to zero.
586 public void MakeUpperBound() {
587 Debug.Assert(this.error < 0xFFFFFFFF);
588 uint uT = (this.error + 1) >> 1;
590 if (0 != uT && 0 != AddU(ref this.u0, uT) && 0 != AddU(ref this.u1, 1) && 0 != AddU(ref this.u2, 1)) {
591 Debug.Assert(0 == this.u2 && 0 == this.u1);
592 this.u2 = 0x80000000;
593 this.u0 = (this.u0 >> 1) + (this.u0 & 1);
599 // If error is not zero, subtract it and set error to zero.
600 public void MakeLowerBound() {
601 Debug.Assert(this.error < 0xFFFFFFFF);
602 uint uT = (this.error + 1) >> 1;
604 if (0 != uT && 0 == AddU(ref this.u0, (uint)-(int)uT) && 0 == AddU(ref this.u1, 0xFFFFFFFF)) {
605 AddU(ref this.u2, 0xFFFFFFFF);
606 if (0 == (0x80000000 & this.u2)) {
613 /* ----------------------------------------------------------------------------
616 Get mantissa bytes (BCD).
618 public static bool DblToRgbFast(double dbl, byte[] mantissa, out int exponent, out int mantissaSize) {
619 BigNumber numHH, numHL, numLH, numLL;
624 byte bHH, bHL, bLH, bLL;
625 uint uHH, uHL, uLH, uLL;
626 int wExp2, wExp10 = 0;
633 // Caller should take care of 0, negative and non-finite values.
634 Debug.Assert(!IsSpecial(dbl));
635 Debug.Assert(0 < dbl);
637 // Get numHH and numLL such that numLL < dbl < numHH and the
638 // difference between adjacent values is half the distance to the next
639 // representable value (in a double).
640 wExp2 = (int)((dblHi >> 20) & 0x07FF);
642 // See if dbl is a small integer.
643 if (wExp2 >= 1023 && wExp2 <= 1075 && dbl == Math.Floor(dbl)) {
648 numBase.u2 = 0x80000000 | ((dblHi & 0x000FFFFFF) << 11) | (dblLo >> 21);
649 numBase.u1 = dblLo << 11;
651 numBase.exp = wExp2 - 1022;
654 // Get the upper bound
656 numHH.u1 |= (1 << 10);
658 // Get the lower bound. A power of 2 must be special cased.
660 if (0x80000000 == numLL.u2 && 0 == numLL.u1) {
661 // Subtract (0x00000000, 0x00000200, 0x00000000). Same as adding
662 // (0xFFFFFFFF, 0xFFFFFE00, 0x00000000)
665 // Subtract (0x00000000, 0x00000400, 0x00000000). Same as adding
666 // (0xFFFFFFFF, 0xFFFFFC00, 0x00000000)
669 if (0 == AddU(ref numLL.u1, uT)) {
670 AddU(ref numLL.u2, 0xFFFFFFFF);
671 if (0 == (0x80000000 & numLL.u2)) {
677 numBase.u2 = dblHi & 0x000FFFFF;
683 // Get the upper bound
685 numHH.u0 = 0x80000000;
687 // Get the lower bound
689 if (0 == AddU(ref numLL.u1, 0xFFFFFFFF)) {
690 AddU(ref numLL.u2, 0xFFFFFFFF);
698 // Multiply by powers of ten until 0 < numHH.exp < 32.
699 if (numHH.exp >= 32) {
700 iT = (numHH.exp - 25) * 15 / -TenPowersNeg[45].exp;
701 Debug.Assert(iT >= 0 && iT < 16);
703 tenPower = TenPowersNeg[30 + iT];
704 Debug.Assert(numHH.exp + tenPower.exp > 1);
705 numHH.Mul(ref tenPower);
706 numLL.Mul(ref tenPower);
710 if (numHH.exp >= 32) {
711 iT = (numHH.exp - 25) * 32 / -TenPowersNeg[31].exp;
712 Debug.Assert(iT > 0 && iT <= 32);
713 tenPower = TenPowersNeg[iT - 1];
714 Debug.Assert(numHH.exp + tenPower.exp > 1);
715 numHH.Mul(ref tenPower);
716 numLL.Mul(ref tenPower);
719 } else if (numHH.exp < 1) {
720 iT = (25 - numHH.exp) * 15 / TenPowersPos[45].exp;
721 Debug.Assert(iT >= 0 && iT < 16);
723 tenPower = TenPowersPos[30 + iT];
724 Debug.Assert(numHH.exp + tenPower.exp <= 32);
725 numHH.Mul(ref tenPower);
726 numLL.Mul(ref tenPower);
731 iT = (25 - numHH.exp) * 32 / TenPowersPos[31].exp;
732 Debug.Assert(iT > 0 && iT <= 32);
733 tenPower = TenPowersPos[iT - 1];
734 Debug.Assert(numHH.exp + tenPower.exp <= 32);
735 numHH.Mul(ref tenPower);
736 numLL.Mul(ref tenPower);
741 Debug.Assert(numHH.exp > 0 && numHH.exp < 32);
743 // Get the upper and lower bounds for these.
745 numHH.MakeUpperBound();
746 numHL.MakeLowerBound();
750 numLH.MakeUpperBound();
751 numLL.MakeLowerBound();
754 Debug.Assert(uLL <= uLH && uLH <= uHL && uHL <= uHH);
756 // Find the starting scale
758 if (uHH >= 100000000) {
766 if (uHH >= 100 * uScale) {
771 if (uHH >= 10 * uScale) {
776 Debug.Assert(uHH >= uScale && uHH / uScale < 10);
779 Debug.Assert(uLL <= uHH);
780 bHH = (byte)(uHH / uScale);
782 bLL = (byte)(uLL / uScale);
789 Debug.Assert(0 != uHH || !numHH.IsZero);
790 mantissa[ib++] = bHH;
796 numHH.Mul(ref TenPowersPos[7]);
797 numHH.MakeUpperBound();
799 if (uHH >= 100000000) {
802 numHL.Mul(ref TenPowersPos[7]);
803 numHL.MakeLowerBound();
806 numLH.Mul(ref TenPowersPos[7]);
807 numLH.MakeUpperBound();
809 numLL.Mul(ref TenPowersPos[7]);
810 numLL.MakeLowerBound();
817 // LL and HH diverged. Get the digit values for LH and HL.
818 Debug.Assert(0 <= bLL && bLL < bHH && bHH <= 9);
819 bLH = (byte)((uLH / uScale) % 10);
821 bHL = (byte)((uHL / uScale) % 10);
828 // LH and HL also diverged.
830 // We can get by with one fewer digit if: LL == LH and bLH is zero
831 // and the current value of LH is zero and the least significant bit of
832 // the double is zero. In this case, we have exactly the digit sequence
833 // for the original numLL and IEEE and will rounds numLL up to the double.
834 if (0 == bLH && 0 == uLH && numLH.IsZero && 0 == (dblLo & 1)) {
836 else if (bHL - bLH > 1) {
837 // HL and LH differ by at least two in this digit, so split
839 mantissa[ib++] = (byte)((bHL + bLH + 1) / 2);
840 } else if (0 != uHL || !numHL.IsZero || 0 == (dblLo & 1)) {
841 // We can just use bHL because this guarantees that we're bigger than
842 // LH and less than HL, so must convert to the double.
843 mantissa[ib++] = bHL;
853 // dbl should be an integer from 1 to (2^53 - 1).
855 Debug.Assert(dblInt == Math.Floor(dblInt) && 1 <= dblInt && dblInt <= 9007199254740991.0d);
858 if (dblInt >= C10toN[iT + 8]) {
861 if (dblInt >= C10toN[iT + 4]) {
864 if (dblInt >= C10toN[iT + 2]) {
867 if (dblInt >= C10toN[iT + 1]) {
870 Debug.Assert(iT >= 0 && iT <= 15);
871 Debug.Assert(dblInt >= C10toN[iT] && dblInt < C10toN[iT + 1]);
874 for (ib = 0; 0 != dblInt; iT--) {
875 Debug.Assert(iT >= 0);
876 bHH = (byte)(dblInt / C10toN[iT]);
877 dblInt -= bHH * C10toN[iT];
878 Debug.Assert(dblInt == Math.Floor(dblInt) && 0 <= dblInt && dblInt < C10toN[iT]);
879 mantissa[ib++] = bHH;
886 // Verify that precise is working and gives the same answer
887 if (mantissaSize > 0) {
888 byte[] mantissaPrec = new byte[20];
889 int exponentPrec, mantissaSizePrec, idx;
891 DblToRgbPrecise(dbl, mantissaPrec, out exponentPrec, out mantissaSizePrec);
892 Debug.Assert(exponent == exponentPrec && mantissaSize == mantissaSizePrec);
893 // Assert(!memcmp(mantissa, mantissaPrec, mantissaSizePrec - 1));
895 for (idx = 0; idx < mantissaSize; idx++) {
897 (mantissa[idx] == mantissaPrec[idx]) ||
898 (idx == mantissaSize - 1) && Math.Abs(mantissa[idx] - mantissaPrec[idx]) <= 1
901 Debug.Assert(equal, "DblToRgbFast and DblToRgbPrecise should give the same result");
908 exponent = mantissaSize = 0;
912 /* ----------------------------------------------------------------------------
915 Uses big integer arithmetic to get the sequence of digits.
917 public static void DblToRgbPrecise(double dbl, byte[] mantissa, out int exponent, out int mantissaSize) {
920 BigInteger biNum = new BigInteger();
921 BigInteger biDen = new BigInteger();
922 BigInteger biHi = new BigInteger();
923 BigInteger biLo = new BigInteger();
924 BigInteger biT = new BigInteger();
929 int wExp10, wExp2, w1, w2;
930 int c2Num, c2Den, c5Num, c5Den;
932 //uint *rgu = stackalloc uint[2];
939 // Caller should take care of 0, negative and non-finite values.
940 Debug.Assert(!IsSpecial(dbl));
941 Debug.Assert(0 < dbl);
943 // Init the Denominator, Hi error and Lo error bigints.
944 biDen.InitFromDigits(1, 0, 1);
945 biHi.InitFromDigits(1, 0, 1);
947 wExp2 = (int)(((dblHi & 0x7FF00000) >> 20) - 1075);
948 rgu1 = dblHi & 0x000FFFFF;
952 if (wExp2 == -1075) {
953 // dbl is denormalized.
954 Debug.Assert(0 == (dblHi & 0x7FF00000));
959 // Get dblT such that dbl / dblT is a power of 2 and 1 <= dblT < 2.
960 // First multiply by a power of 2 to get a normalized value.
961 dblT = BitConverter.Int64BitsToDouble(0x4FF00000L << 32);
963 Debug.Assert(0 != (DblHi(dblT) & 0x7FF00000));
965 // This is the power of 2.
966 w1 = (int)((DblHi(dblT) & 0x7FF00000) >> 20) - (256 + 1023);
971 dblT = BitConverter.Int64BitsToDouble((long)dblHi << 32 | DblLo(dblT));
973 // Adjust wExp2 because we don't have the implicit bit.
976 // Get dblT such that dbl / dblT is a power of 2 and 1 <= dblT < 2.
977 // First multiply by a power of 2 to get a normalized value.
980 dblT = BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
982 // This is the power of 2.
985 if (0 == rgu0 && 0 == rgu1 && wExp2 > -1074) {
986 // Power of 2 bigger than smallest normal. The next smaller
987 // representable value is closer than the next larger value.
992 // Normalized and not a power of 2 or the smallest normal. The
993 // representable values on either side are the same distance away.
998 // Compute an approximation to the base 10 log. This is borrowed from
999 // David ----'s paper.
1000 Debug.Assert(1 <= dblT && dblT < 2);
1001 dblT = (dblT - 1.5) * 0.289529654602168 + 0.1760912590558 +
1002 w1 * 0.301029995663981;
1004 if (dblT < 0 && dblT != wExp10) {
1026 if (c2Num > 0 && c2Den > 0) {
1027 w1 = c2Num < c2Den ? c2Num : c2Den;
1031 // We need a bit for the Hi and Lo values.
1035 // Initialize biNum and multiply by powers of 5.
1037 Debug.Assert(0 == c5Den);
1038 biHi.MulPow5(c5Num);
1039 biNum.InitFromBigint(biHi);
1041 biNum.MulAdd(rgu0, 0);
1043 biNum.MulAdd(rgu1, 0);
1044 biNum.ShiftLeft(32);
1046 biT.InitFromBigint(biHi);
1047 biT.MulAdd(rgu0, 0);
1052 Debug.Assert(cu <= 2);
1053 biNum.InitFromDigits(rgu0, rgu1, cu);
1055 biDen.MulPow5(c5Den);
1059 // BigInteger.DivRem only works if the 4 high bits of the divisor are 0.
1060 // It works most efficiently if there are exactly 4 zero high bits.
1061 // Adjust c2Den and c2Num to guarantee this.
1062 w1 = CbitZeroLeft(biDen[biDen.Length - 1]);
1063 w1 = (w1 + 28 - c2Den) & 0x1F;
1067 // Multiply by powers of 2.
1068 Debug.Assert(c2Num > 0 && c2Den > 0);
1069 biNum.ShiftLeft(c2Num);
1071 biHi.ShiftLeft(c2Num - 1);
1073 biDen.ShiftLeft(c2Den);
1074 Debug.Assert(0 == (biDen[biDen.Length - 1] & 0xF0000000));
1075 Debug.Assert(0 != (biDen[biDen.Length - 1] & 0x08000000));
1077 // Get biHiLo and handle the power of 2 case where biHi needs to be doubled.
1080 biHiLo.InitFromBigint(biHi);
1087 bT = (byte)biNum.DivRem(biDen);
1088 if (0 == ib && 0 == bT) {
1089 // Our estimate of wExp10 was too big. Oh well.
1094 // w1 = sign(biNum - biHiLo).
1095 w1 = biNum.CompareTo(biHiLo);
1097 // w2 = sign(biNum + biHi - biDen).
1098 if (biDen.CompareTo(biHi) < 0) {
1102 biT.InitFromBigint(biDen);
1104 w2 = biNum.CompareTo(biT);
1107 // if (biNum + biHi == biDen && even)
1108 if (0 == w2 && 0 == (dblLo & 1)) {
1109 // Rounding up this digit produces exactly (biNum + biHi) which
1110 // StrToDbl will round down to dbl.
1117 mantissa[ib++] = bT;
1121 // if (biNum < biHiLo || biNum == biHiLo && even)
1122 if (w1 < 0 || 0 == w1 && 0 == (dblLo & 1)) {
1123 // if (biNum + biHi > biDen)
1125 // Decide whether to round up.
1127 w2 = biNum.CompareTo(biDen);
1128 if ((w2 > 0 || 0 == w2 && (0 != (bT & 1))) && bT++ == 9) {
1132 mantissa[ib++] = bT;
1136 // if (biNum + biHi > biDen)
1138 // Round up and be done with it.
1140 mantissa[ib++] = (byte)(bT + 1);
1147 mantissa[ib++] = bT;
1150 biNum.MulAdd(10, 0);
1152 if ((object) biHiLo != (object) biHi) {
1153 biHiLo.MulAdd(10, 0);
1159 if (mantissa[--ib] != 9) {
1170 exponent = wExp10 + 1;
1174 #region Powers of ten
1175 private static readonly BigNumber[] TenPowersPos = new BigNumber[46] {
1176 // Positive powers of 10 to 96 bits precision.
1177 new BigNumber( 0x00000000, 0x00000000, 0xA0000000, 4, 0 ), // 10^1
1178 new BigNumber( 0x00000000, 0x00000000, 0xC8000000, 7, 0 ), // 10^2
1179 new BigNumber( 0x00000000, 0x00000000, 0xFA000000, 10, 0 ), // 10^3
1180 new BigNumber( 0x00000000, 0x00000000, 0x9C400000, 14, 0 ), // 10^4
1181 new BigNumber( 0x00000000, 0x00000000, 0xC3500000, 17, 0 ), // 10^5
1182 new BigNumber( 0x00000000, 0x00000000, 0xF4240000, 20, 0 ), // 10^6
1183 new BigNumber( 0x00000000, 0x00000000, 0x98968000, 24, 0 ), // 10^7
1184 new BigNumber( 0x00000000, 0x00000000, 0xBEBC2000, 27, 0 ), // 10^8
1185 new BigNumber( 0x00000000, 0x00000000, 0xEE6B2800, 30, 0 ), // 10^9
1186 new BigNumber( 0x00000000, 0x00000000, 0x9502F900, 34, 0 ), // 10^10
1187 new BigNumber( 0x00000000, 0x00000000, 0xBA43B740, 37, 0 ), // 10^11
1188 new BigNumber( 0x00000000, 0x00000000, 0xE8D4A510, 40, 0 ), // 10^12
1189 new BigNumber( 0x00000000, 0x00000000, 0x9184E72A, 44, 0 ), // 10^13
1190 new BigNumber( 0x00000000, 0x80000000, 0xB5E620F4, 47, 0 ), // 10^14
1191 new BigNumber( 0x00000000, 0xA0000000, 0xE35FA931, 50, 0 ), // 10^15
1192 new BigNumber( 0x00000000, 0x04000000, 0x8E1BC9BF, 54, 0 ), // 10^16
1193 new BigNumber( 0x00000000, 0xC5000000, 0xB1A2BC2E, 57, 0 ), // 10^17
1194 new BigNumber( 0x00000000, 0x76400000, 0xDE0B6B3A, 60, 0 ), // 10^18
1195 new BigNumber( 0x00000000, 0x89E80000, 0x8AC72304, 64, 0 ), // 10^19
1196 new BigNumber( 0x00000000, 0xAC620000, 0xAD78EBC5, 67, 0 ), // 10^20
1197 new BigNumber( 0x00000000, 0x177A8000, 0xD8D726B7, 70, 0 ), // 10^21
1198 new BigNumber( 0x00000000, 0x6EAC9000, 0x87867832, 74, 0 ), // 10^22
1199 new BigNumber( 0x00000000, 0x0A57B400, 0xA968163F, 77, 0 ), // 10^23
1200 new BigNumber( 0x00000000, 0xCCEDA100, 0xD3C21BCE, 80, 0 ), // 10^24
1201 new BigNumber( 0x00000000, 0x401484A0, 0x84595161, 84, 0 ), // 10^25
1202 new BigNumber( 0x00000000, 0x9019A5C8, 0xA56FA5B9, 87, 0 ), // 10^26
1203 new BigNumber( 0x00000000, 0xF4200F3A, 0xCECB8F27, 90, 0 ), // 10^27
1204 new BigNumber( 0x40000000, 0xF8940984, 0x813F3978, 94, 0 ), // 10^28
1205 new BigNumber( 0x50000000, 0x36B90BE5, 0xA18F07D7, 97, 0 ), // 10^29
1206 new BigNumber( 0xA4000000, 0x04674EDE, 0xC9F2C9CD, 100, 0 ), // 10^30
1207 new BigNumber( 0x4D000000, 0x45812296, 0xFC6F7C40, 103, 0 ), // 10^31
1208 new BigNumber( 0xF0200000, 0x2B70B59D, 0x9DC5ADA8, 107, 0 ), // 10^32
1209 new BigNumber( 0x3CBF6B72, 0xFFCFA6D5, 0xC2781F49, 213, 1 ), // 10^64 (rounded up)
1210 new BigNumber( 0xC5CFE94F, 0xC59B14A2, 0xEFB3AB16, 319, 1 ), // 10^96 (rounded up)
1211 new BigNumber( 0xC66F336C, 0x80E98CDF, 0x93BA47C9, 426, 1 ), // 10^128
1212 new BigNumber( 0x577B986B, 0x7FE617AA, 0xB616A12B, 532, 1 ), // 10^160
1213 new BigNumber( 0x85BBE254, 0x3927556A, 0xE070F78D, 638, 1 ), // 10^192 (rounded up)
1214 new BigNumber( 0x82BD6B71, 0xE33CC92F, 0x8A5296FF, 745, 1 ), // 10^224 (rounded up)
1215 new BigNumber( 0xDDBB901C, 0x9DF9DE8D, 0xAA7EEBFB, 851, 1 ), // 10^256 (rounded up)
1216 new BigNumber( 0x73832EEC, 0x5C6A2F8C, 0xD226FC19, 957, 1 ), // 10^288
1217 new BigNumber( 0xE6A11583, 0xF2CCE375, 0x81842F29, 1064, 1 ), // 10^320
1218 new BigNumber( 0x5EBF18B7, 0xDB900AD2, 0x9FA42700, 1170, 1 ), // 10^352 (rounded up)
1219 new BigNumber( 0x1027FFF5, 0xAEF8AA17, 0xC4C5E310, 1276, 1 ), // 10^384
1220 new BigNumber( 0xB5E54F71, 0xE9B09C58, 0xF28A9C07, 1382, 1 ), // 10^416
1221 new BigNumber( 0xA7EA9C88, 0xEBF7F3D3, 0x957A4AE1, 1489, 1 ), // 10^448
1222 new BigNumber( 0x7DF40A74, 0x0795A262, 0xB83ED8DC, 1595, 1 ), // 10^480
1225 private static readonly BigNumber[] TenPowersNeg = new BigNumber[46] {
1226 // Negative powers of 10 to 96 bits precision.
1227 new BigNumber( 0xCCCCCCCD, 0xCCCCCCCC, 0xCCCCCCCC, -3, 1 ), // 10^-1 (rounded up)
1228 new BigNumber( 0x3D70A3D7, 0x70A3D70A, 0xA3D70A3D, -6, 1 ), // 10^-2
1229 new BigNumber( 0x645A1CAC, 0x8D4FDF3B, 0x83126E97, -9, 1 ), // 10^-3
1230 new BigNumber( 0xD3C36113, 0xE219652B, 0xD1B71758, -13, 1 ), // 10^-4
1231 new BigNumber( 0x0FCF80DC, 0x1B478423, 0xA7C5AC47, -16, 1 ), // 10^-5
1232 new BigNumber( 0xA63F9A4A, 0xAF6C69B5, 0x8637BD05, -19, 1 ), // 10^-6 (rounded up)
1233 new BigNumber( 0x3D329076, 0xE57A42BC, 0xD6BF94D5, -23, 1 ), // 10^-7
1234 new BigNumber( 0xFDC20D2B, 0x8461CEFC, 0xABCC7711, -26, 1 ), // 10^-8
1235 new BigNumber( 0x31680A89, 0x36B4A597, 0x89705F41, -29, 1 ), // 10^-9 (rounded up)
1236 new BigNumber( 0xB573440E, 0xBDEDD5BE, 0xDBE6FECE, -33, 1 ), // 10^-10
1237 new BigNumber( 0xF78F69A5, 0xCB24AAFE, 0xAFEBFF0B, -36, 1 ), // 10^-11
1238 new BigNumber( 0xF93F87B7, 0x6F5088CB, 0x8CBCCC09, -39, 1 ), // 10^-12
1239 new BigNumber( 0x2865A5F2, 0x4BB40E13, 0xE12E1342, -43, 1 ), // 10^-13
1240 new BigNumber( 0x538484C2, 0x095CD80F, 0xB424DC35, -46, 1 ), // 10^-14 (rounded up)
1241 new BigNumber( 0x0F9D3701, 0x3AB0ACD9, 0x901D7CF7, -49, 1 ), // 10^-15
1242 new BigNumber( 0x4C2EBE68, 0xC44DE15B, 0xE69594BE, -53, 1 ), // 10^-16
1243 new BigNumber( 0x09BEFEBA, 0x36A4B449, 0xB877AA32, -56, 1 ), // 10^-17 (rounded up)
1244 new BigNumber( 0x3AFF322E, 0x921D5D07, 0x9392EE8E, -59, 1 ), // 10^-18
1245 new BigNumber( 0x2B31E9E4, 0xB69561A5, 0xEC1E4A7D, -63, 1 ), // 10^-19 (rounded up)
1246 new BigNumber( 0x88F4BB1D, 0x92111AEA, 0xBCE50864, -66, 1 ), // 10^-20 (rounded up)
1247 new BigNumber( 0xD3F6FC17, 0x74DA7BEE, 0x971DA050, -69, 1 ), // 10^-21 (rounded up)
1248 new BigNumber( 0x5324C68B, 0xBAF72CB1, 0xF1C90080, -73, 1 ), // 10^-22
1249 new BigNumber( 0x75B7053C, 0x95928A27, 0xC16D9A00, -76, 1 ), // 10^-23
1250 new BigNumber( 0xC4926A96, 0x44753B52, 0x9ABE14CD, -79, 1 ), // 10^-24
1251 new BigNumber( 0x3A83DDBE, 0xD3EEC551, 0xF79687AE, -83, 1 ), // 10^-25 (rounded up)
1252 new BigNumber( 0x95364AFE, 0x76589DDA, 0xC6120625, -86, 1 ), // 10^-26
1253 new BigNumber( 0x775EA265, 0x91E07E48, 0x9E74D1B7, -89, 1 ), // 10^-27 (rounded up)
1254 new BigNumber( 0x8BCA9D6E, 0x8300CA0D, 0xFD87B5F2, -93, 1 ), // 10^-28
1255 new BigNumber( 0x096EE458, 0x359A3B3E, 0xCAD2F7F5, -96, 1 ), // 10^-29
1256 new BigNumber( 0xA125837A, 0x5E14FC31, 0xA2425FF7, -99, 1 ), // 10^-30 (rounded up)
1257 new BigNumber( 0x80EACF95, 0x4B43FCF4, 0x81CEB32C, -102, 1 ), // 10^-31 (rounded up)
1258 new BigNumber( 0x67DE18EE, 0x453994BA, 0xCFB11EAD, -106, 1 ), // 10^-32 (rounded up)
1259 new BigNumber( 0x3F2398D7, 0xA539E9A5, 0xA87FEA27, -212, 1 ), // 10^-64
1260 new BigNumber( 0x11DBCB02, 0xFD75539B, 0x88B402F7, -318, 1 ), // 10^-96
1261 new BigNumber( 0xAC7CB3F7, 0x64BCE4A0, 0xDDD0467C, -425, 1 ), // 10^-128 (rounded up)
1262 new BigNumber( 0x59ED2167, 0xDB73A093, 0xB3F4E093, -531, 1 ), // 10^-160
1263 new BigNumber( 0x7B6306A3, 0x5423CC06, 0x91FF8377, -637, 1 ), // 10^-192
1264 new BigNumber( 0xA4F8BF56, 0x4A314EBD, 0xECE53CEC, -744, 1 ), // 10^-224
1265 new BigNumber( 0xFA911156, 0x637A1939, 0xC0314325, -850, 1 ), // 10^-256 (rounded up)
1266 new BigNumber( 0x4EE367F9, 0x836AC577, 0x9BECCE62, -956, 1 ), // 10^-288
1267 new BigNumber( 0x8920B099, 0x478238D0, 0xFD00B897, -1063, 1 ), // 10^-320 (rounded up)
1268 new BigNumber( 0x0092757C, 0x46F34F7D, 0xCD42A113, -1169, 1 ), // 10^-352 (rounded up)
1269 new BigNumber( 0x88DBA000, 0xB11B0857, 0xA686E3E8, -1275, 1 ), // 10^-384 (rounded up)
1270 new BigNumber( 0x1A4EB007, 0x3FFC68A6, 0x871A4981, -1381, 1 ), // 10^-416 (rounded up)
1271 new BigNumber( 0x84C663CF, 0xB6074244, 0xDB377599, -1488, 1 ), // 10^-448 (rounded up)
1272 new BigNumber( 0x61EB52E2, 0x79007736, 0xB1D983B4, -1594, 1 ), // 10^-480
1277 /***************************************************************************
1278 This is JScript code to compute the BigNumber values in the tables above.
1279 ***************************************************************************/
1281 var cbitsExact = 96;
1282 var arrPos = new Array;
1283 var arrNeg = new Array;
1297 for (i = 0; i < arrPos.length; i++)
1300 for (i = 0; i < arrNeg.length; i++)
1304 function Compute(p, n)
1311 for (i = 0; i < p; i++)
1314 str = Mul(str, str);
1321 for (i = 2; i <= n; i++)
1324 PrintNum(t, i * exp);
1325 PrintInv(t, i * exp);
1337 if (a.length > b.length)
1347 for (i = 1; i <= len; i++)
1349 if (a.charAt(len - i) == '1')
1350 res = Add(res, add);
1363 var lena = a.length;
1364 var lenb = b.length;
1365 var lenm = Math.max(lena, lenb);
1367 for (i = 1; i <= lenm; i++)
1369 bit = (a.charAt(lena - i) == '1') + (b.charAt(lenb - i) == '1') + c;
1382 function PrintNum(a, n)
1384 arrPos[arrPos.length] = PrintHex(a, a.length, n);
1387 function PrintHex(a, e, n)
1392 var fRoundUp = false;
1396 for (i = 0; i < cbitsExact; )
1399 if (a.charAt(i) == '1')
1401 if (0 == (++i & 0x1F) && i < cbitsExact)
1403 strT = dig.toString(16).toUpperCase();
1404 res += ' 0x' + '00000000'.substring(strT.length) + strT;
1409 if (a.charAt(cbitsExact) == '1')
1411 // Round up. Don't have to worry about overflowing.
1415 strT = dig.toString(16).toUpperCase();
1416 res += ' 0x' + '00000000'.substring(strT.length) + strT;
1418 arr = res.split(' ');
1419 res = '\t{ ' + arr[3];
1420 res += ', ' + arr[2];
1421 res += ', ' + arr[1];
1422 strT = '' + (e + n);
1423 res += ', ' + ' '.substring(strT.length) + strT;
1424 res += ', ' + (a.length <= cbitsExact ? 0 : 1);
1426 res += ' ), // 10^' + strT;
1428 res += ' '.substring(strT.length) + '(rounded up)';
1434 function PrintInv(a, n)
1442 for (exp = 0; div.length <= len; exp++)
1445 for (cdig = 0; cdig < cbits; cdig++)
1447 if (div.length > len || div.length == len && div >= a)
1457 arrNeg[arrNeg.length] = PrintHex(res, -exp + 1, -n);
1466 var lena = a.length;
1467 var lenb = b.length;
1471 for (i = 1; i <= lena; i++)
1473 ad = (a.charAt(lena - i) == '1');
1474 bd = (b.charAt(lenb - i) == '1');
1490 return res.substring(res.length - cch, res.length);
1496 * Implementation of very large variable-precision non-negative integers.
1501 private class BigInteger : IComparable {
1502 // Make this big enough that we rarely have to reallocate.
1503 private const int InitCapacity = 30;
1505 private int capacity;
1507 private uint[] digits;
1509 public BigInteger() {
1510 capacity = InitCapacity;
1512 digits = new uint[InitCapacity];
1517 get { return length; }
1520 public uint this[int idx] {
1523 Debug.Assert(0 <= idx && idx < length);
1528 [Conditional("DEBUG")]
1529 private void AssertValidNoVal() {
1530 Debug.Assert(capacity >= InitCapacity);
1531 Debug.Assert(length >= 0 && length <= capacity);
1534 [Conditional("DEBUG")]
1535 private void AssertValid() {
1537 Debug.Assert(0 == length || 0 != digits[length - 1]);
1540 private void Ensure(int cu) {
1543 if (cu <= capacity) {
1548 uint[] newDigits = new uint[cu];
1549 digits.CopyTo(newDigits, 0);
1556 /* ----------------------------------------------------------------------------
1559 Initialize this big integer from an array of uint values.
1561 public void InitFromRgu(uint[] rgu, int cu) {
1563 Debug.Assert(cu >= 0);
1568 for (int i = 0; i < cu; i++) {
1574 /* ----------------------------------------------------------------------------
1577 Initialize this big integer from 0, 1, or 2 uint values.
1579 public void InitFromDigits(uint u0, uint u1, int cu) {
1581 Debug.Assert(2 <= capacity);
1589 /* ----------------------------------------------------------------------------
1592 Initialize this big integer from another BigInteger object.
1594 public void InitFromBigint(BigInteger biSrc) {
1596 biSrc.AssertValid();
1597 Debug.Assert((object)this != (object)biSrc);
1599 InitFromRgu(biSrc.digits, biSrc.length);
1602 #if !NOPARSE || DEBUG
1603 /* ----------------------------------------------------------------------------
1604 InitFromFloatingDecimal()
1606 Initialize this big integer from a FloatingDecimal object.
1608 public void InitFromFloatingDecimal(FloatingDecimal dec) {
1610 Debug.Assert(dec.MantissaSize >= 0);
1613 int cu = (dec.MantissaSize + 8) / 9;
1614 int mantissaSize = dec.MantissaSize;
1621 for (int ib = 0; ib < mantissaSize; ib++) {
1622 Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
1623 if (1000000000 == uMul) {
1629 uAdd = uAdd * 10 + dec[ib];
1631 Debug.Assert(1 < uMul);
1638 public void MulAdd(uint uMul, uint uAdd) {
1640 Debug.Assert(0 != uMul);
1642 for (int i = 0; i < length; i++) {
1644 d = MulU(digits[i], uMul, out uT);
1646 uT += AddU(ref d, uAdd);
1653 digits[length++] = uAdd;
1658 public void MulPow5(int c5) {
1660 Debug.Assert(c5 >= 0);
1662 const uint C5to13 = 1220703125;
1663 int cu = (c5 + 12) / 13;
1665 if (0 == length || 0 == c5) {
1669 Ensure(length + cu);
1671 for ( ; c5 >= 13; c5 -= 13) {
1677 for (uT = 5; --c5 > 0; ) {
1685 public void ShiftLeft(int cbit) {
1687 Debug.Assert(cbit >= 0);
1692 if (0 == cbit || 0 == length) {
1701 uExtra = digits[idx] >> (32 - cbit);
1704 digits[idx] <<= cbit;
1708 digits[idx] |= digits[idx - 1] >> (32 - cbit);
1714 if (cu > 0 || 0 != uExtra) {
1715 // Make sure there's enough room.
1716 idx = length + (0 != uExtra ? 1 : 0) + cu;
1720 // Shift the digits.
1722 for (int i = length; 0 != i--; ) {
1723 digits[cu + i] = digits[i];
1726 for (int i = 0; i < cu; i++) {
1732 // Throw on the extra one.
1734 digits[length++] = uExtra;
1740 public void ShiftUsRight(int cu) {
1742 Debug.Assert(cu >= 0);
1746 } else if (cu > 0) {
1748 for (int i = 0; i < length - cu; i++) {
1749 digits[i] = digits[cu + i];
1756 public void ShiftRight(int cbit) {
1758 Debug.Assert(cbit >= 0);
1768 if (0 == cbit || 0 == length) {
1774 digits[idx] >>= cbit;
1775 if (++idx >= length) {
1777 if (0 == digits[idx - 1]) {
1782 digits[idx - 1] |= digits[idx] << (32 - cbit);
1787 public int CompareTo(object obj) {
1788 BigInteger bi = (BigInteger)obj;
1792 if (length > bi.length) {
1794 } else if (length < bi.length) {
1796 } else if (0 == length) {
1802 for (idx = length - 1; digits[idx] == bi.digits[idx]; idx--) {
1807 Debug.Assert(idx >= 0 && idx < length);
1808 Debug.Assert(digits[idx] != bi.digits[idx]);
1810 return (digits[idx] > bi.digits[idx]) ? 1 : -1;
1813 public void Add(BigInteger bi) {
1816 Debug.Assert((object)this != (object)bi);
1818 int idx, cuMax, cuMin;
1821 if ((cuMax = length) < (cuMin = bi.length)) {
1828 for (idx = 0; idx < cuMin; idx++) {
1830 wCarry = AddU(ref digits[idx], wCarry);
1832 wCarry += AddU(ref digits[idx], bi.digits[idx]);
1835 if (length < bi.length) {
1836 for ( ; idx < cuMax; idx++) {
1837 digits[idx] = bi.digits[idx];
1839 wCarry = AddU(ref digits[idx], wCarry);
1844 for ( ; 0 != wCarry && idx < cuMax; idx++) {
1845 wCarry = AddU(ref digits[idx], wCarry);
1851 digits[length++] = wCarry;
1856 public void Subtract(BigInteger bi) {
1859 Debug.Assert((object)this != (object)bi);
1864 if (length < bi.length) {
1869 for (idx = 0; idx < bi.length; idx++) {
1870 Debug.Assert(0 == wCarry || 1 == wCarry);
1871 uT = bi.digits[idx];
1873 // NOTE: We should really do:
1874 // wCarry = AddU(ref digits[idx], wCarry);
1875 // wCarry += AddU(ref digits[idx], ~uT);
1876 // The only case where this is different than
1877 // wCarry = AddU(ref digits[idx], ~uT + wCarry);
1878 // is when 0 == uT and 1 == wCarry, in which case we don't
1879 // need to add anything and wCarry should still be 1, so we can
1880 // just skip the operations.
1882 if (0 != uT || 0 == wCarry) {
1883 wCarry = AddU(ref digits[idx], ~uT + wCarry);
1886 while (0 == wCarry && idx < length) {
1887 wCarry = AddU(ref digits[idx], 0xFFFFFFFF);
1891 if (idx == length) {
1893 while (--idx >= 0 && 0 == digits[idx]) {
1902 // bi was bigger than this.
1903 Debug.Assert(false, "Who's subtracting to negative?");
1908 public uint DivRem(BigInteger bi) {
1911 Debug.Assert((object)this != (object)bi);
1919 Debug.Assert(length <= cu);
1924 // Get a lower bound on the quotient.
1925 uQuo = (uint)(digits[cu - 1] / (bi.digits[cu - 1] + 1));
1926 Debug.Assert(uQuo >= 0 && uQuo <= 9);
1928 // Handle 0 and 1 as special cases.
1938 for (idx = 0; idx < cu; idx++) {
1939 Debug.Assert(0 == wCarry || 1 == wCarry);
1941 // Compute the product.
1942 uLo = MulU(uQuo, bi.digits[idx], out uT);
1943 uHi = uT + AddU(ref uLo, uHi);
1945 // Subtract the product. See note in BigInteger.Subtract.
1946 if (0 != uLo || 0 == wCarry) {
1947 wCarry = AddU(ref digits[idx], ~uLo + wCarry);
1950 Debug.Assert(1 == wCarry);
1951 Debug.Assert(idx == cu);
1954 while (--idx >= 0 && 0 == digits[idx]) {
1960 if (uQuo < 9 && (wT = CompareTo(bi)) >= 0) {
1961 // Quotient was off too small (by one).
1969 Debug.Assert(CompareTo(bi) < 0);
1975 public static explicit operator double(BigInteger bi) {
1982 switch (bi.length) {
1986 return bi.digits[0];
1988 return (ulong)bi.digits[1] << 32 | bi.digits[0];
1991 Debug.Assert(3 <= bi.length);
1992 if (bi.length > 32) {
1993 // Result is infinite.
1994 return BitConverter.Int64BitsToDouble(0x7FF00000L << 32);
1997 u1 = bi.digits[bi.length - 1];
1998 u2 = bi.digits[bi.length - 2];
1999 u3 = bi.digits[bi.length - 3];
2000 Debug.Assert(0 != u1);
2001 cbit = 31 - CbitZeroLeft(u1);
2007 uHi = (u1 << (32 - cbit)) | (u2 >> cbit);
2008 // Or 1 if there are any remaining nonzero bits in u3, so we take
2009 // them into account when rounding.
2010 uLo = (u2 << (32 - cbit)) | (u3 >> cbit) | NotZero(u3 << (32 - cbit));
2013 // Set the mantissa bits.
2015 dblLo = (uHi << 20) | (uLo >> 12);
2017 // Set the exponent field.
2018 dblHi |= (uint)(0x03FF + cbit + (bi.length - 1) * 0x0020) << 20;
2020 // Do IEEE rounding.
2021 if (0 != (uLo & 0x0800)) {
2022 if (0 != (uLo & 0x07FF) || 0 != (dblLo & 1)) {
2027 // If there are any non-zero bits in digits from 0 to length - 4,
2029 for (idx = bi.length - 4; idx >= 0; idx--) {
2030 if (0 != bi.digits[idx]) {
2039 return BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
2045 * Floating point number represented in base-10.
2047 private class FloatingDecimal {
2048 public const int MaxDigits = 50;
2049 private const int MaxExp10 = 310; // Upper bound on base 10 exponent
2050 private const int MinExp10 = -325; // Lower bound on base 10 exponent
2052 private int exponent; // Base-10 scaling factor (0 means decimal point immediately precedes first digit)
2053 private int sign; // Sign is -1 or 1, depending on sign of number
2054 private int mantissaSize; // Size of mantissa
2055 private byte[] mantissa = new byte[MaxDigits]; // Array of base-10 digits
2057 public int Exponent { get { return exponent; } set { exponent = value; } }
2058 public int Sign { get { return sign; } set { sign = value; } }
2059 public byte[] Mantissa { get { return mantissa; } }
2061 public int MantissaSize {
2063 return mantissaSize;
2066 Debug.Assert(value <= MaxDigits);
2067 mantissaSize = value;
2071 public byte this[int ib] {
2073 Debug.Assert(0 <= ib && ib < mantissaSize);
2074 return mantissa[ib];
2078 public FloatingDecimal() {
2084 public FloatingDecimal(double dbl) {
2085 InitFromDouble(dbl);
2088 if (0 != mantissaSize) {
2089 Debug.Assert(dbl == (double)this);
2091 FloatingDecimal decAfter = new FloatingDecimal();
2092 decAfter.InitFromDouble(Succ(dbl));
2093 // Assert(memcmp(this, &decAfter, sizeof(*this) - MaxDigits + mantissaSize));
2094 Debug.Assert(!this.Equals(decAfter));
2096 FloatingDecimal decBefore = new FloatingDecimal();
2097 decBefore.InitFromDouble(Pred(dbl));
2098 // Assert(memcmp(this, &decBefore, sizeof(*this) - MaxDigits + mantissaSize));
2099 Debug.Assert(!this.Equals(decBefore));
2105 private bool Equals(FloatingDecimal other) {
2106 if (exponent != other.exponent || sign != other.sign || mantissaSize != other.mantissaSize) {
2109 for (int idx = 0; idx < mantissaSize; idx++) {
2110 if (mantissa[idx] != other.mantissa[idx]) {
2119 /* ----------------------------------------------------------------------------
2122 Rounds off the BCD representation of a number to a specified number of digits.
2123 This may result in the exponent being incremented (e.g. if digits were 999).
2125 public void RoundTo(int sizeMantissa) {
2126 if (sizeMantissa >= mantissaSize) {
2127 // No change required
2131 if (sizeMantissa >= 0) {
2132 bool fRoundUp = mantissa[sizeMantissa] >= 5;
2133 mantissaSize = sizeMantissa;
2135 // Round up if necessary and trim trailing zeros
2136 for (int idx = mantissaSize - 1; idx >= 0; idx--) {
2138 if (++(mantissa[idx]) <= 9) {
2139 // Trailing digit is non-zero, so break
2143 } else if (mantissa[idx] > 0) {
2144 // Trailing digit is non-zero, so break
2148 // Trim trailing zeros
2153 // Number consisted only of 9's
2154 Debug.Assert(0 == mantissaSize);
2160 // Number was rounded past any significant digits (e.g. 0.001 rounded to 1 fractional place), so round to 0.0
2164 if (0 == mantissaSize) {
2172 #if !NOPARSE || DEBUG
2173 /* ----------------------------------------------------------------------------
2174 explicit operator double()
2176 Returns the double value of this floating decimal.
2178 public static explicit operator double(FloatingDecimal dec) {
2179 BigNumber num, numHi, numLo;
2182 double dbl, dblLowPrec, dblLo;
2183 int mantissaSize = dec.mantissaSize;
2185 // Verify that there are no leading or trailing zeros in the mantissa
2186 Debug.Assert(0 != mantissaSize && 0 != dec[0] && 0 != dec[mantissaSize - 1]);
2188 // See if we can just use IEEE double arithmetic.
2189 scale = dec.exponent - mantissaSize;
2190 if (mantissaSize <= 15 && scale >= -22 && dec.exponent <= 37) {
2191 // These calculations are all exact since mantissaSize <= 15.
2192 if (mantissaSize <= 9) {
2193 // Can use the ALU to perform fast integer arithmetic
2195 for (int ib = 0; ib < mantissaSize; ib++) {
2196 Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
2197 ul = ul * 10 + dec[ib];
2201 // Use floating point arithmetic
2203 for (int ib = 0; ib < mantissaSize; ib++) {
2204 Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
2205 dbl = dbl * 10.0 + dec[ib];
2209 // This is the only (potential) rounding operation and we assume
2210 // the compiler does the correct IEEE rounding.
2212 // Need to scale upwards by powers of 10
2214 // This one is exact. We're using the fact that mantissaSize < 15
2215 // to handle exponents bigger than 22.
2216 dbl *= C10toN[scale - 22];
2219 dbl *= C10toN[scale];
2221 } else if (scale < 0) {
2222 // Scale number by negative power of 10
2223 dbl /= C10toN[-scale];
2227 // In the debug version, execute the high precision code also and
2228 // verify that the results are the same.
2232 dblLowPrec = Double.NaN;
2239 if (dec.exponent >= MaxExp10) {
2240 // Overflow to infinity.
2241 dbl = Double.PositiveInfinity;
2245 if (dec.exponent <= MinExp10) {
2251 // Convert to a big number.
2252 num = new BigNumber(dec);
2254 // If there is no error in the big number, just convert it to a double.
2255 if (0 == num.Error) {
2258 dblLo = dec.AdjustDbl(dbl);
2259 Debug.Assert(dbl == dblLo);
2264 // The big number has error in it, so see if the error matters.
2265 // Get the upper bound and lower bound. If they convert to the same
2266 // double we're done.
2268 numHi.MakeUpperBound();
2270 numLo.MakeLowerBound();
2272 dbl = (double)numHi;
2273 dblLo = (double)numLo;
2276 Debug.Assert(dbl == (double)num);
2277 dblLo = dec.AdjustDbl(dbl);
2278 Debug.Assert(dbl == dblLo || Double.IsNaN(dblLo));
2283 // Need to use big integer arithmetic. There's too much error in
2284 // our result and it's close to a boundary value. This is rare,
2285 // but does happen. Eg,
2286 // x = 1.2345678901234568347913049445e+200;
2288 dbl = dec.AdjustDbl((double)num);
2291 // This assert was removed because it would fire on VERY rare occasions. Not
2292 // repro on all machines and very hard to repro even on machines that could repro it.
2293 // The numbers (dblLowPrec and dbl) were different in their two least sig bits only
2294 // which is _probably_ within expected errror. I did not take the time to fully
2295 // investigate whether this really does meet the ECMA spec...
2297 Debug.Assert(Double.IsNaN(dblLowPrec) || dblLowPrec == dbl);
2298 return dec.sign < 0 ? -dbl : dbl;
2301 /* ----------------------------------------------------------------------------
2304 The double contains a binary value, M * 2^n, which is off by at most 1
2305 in the least significant bit; this class' members represent a decimal
2308 The general scheme is to find an integer N (the smaller the better) such
2309 that N * M * 2^n and N * D * 10^e are both integers. We then compare
2310 N * M * 2^n to N * D * 10^e (at full precision). If the binary value is
2311 greater, we adjust it to be exactly half way to the next value that can
2312 come from a double. We then compare again to decided whether to bump the
2313 double up to the next value. Similary if the binary value is smaller,
2314 we adjust it to be exactly half way to the previous representable value
2317 private double AdjustDbl(double dbl) {
2318 BigInteger biDec = new BigInteger();
2319 BigInteger biDbl = new BigInteger();
2325 //uint *rgu = stackalloc uint[2];
2329 biDec.InitFromFloatingDecimal(this);
2330 lwExp = exponent - mantissaSize;
2332 // lwExp is a base 10 exponent.
2334 c5Dec = c2Dec = lwExp;
2338 c5Dbl = c2Dbl = -lwExp;
2343 wExp2 = (int)(rgu1 >> 20) & 0x07FF;
2347 // Normal, so add implicit bit.
2348 if (0 == rgu1 && 0 == rgu0 && 1 != wExp2) {
2349 // Power of 2 (and not adjacent to the first denormal), so the
2350 // adjacent low value is closer than the high value.
2362 // Shift left by 1 bit : the adjustment values need the next lower bit.
2363 rgu1 = (rgu1 << 1) | (rgu0 >> 31);
2366 // We must determine how many words of significant digits this requires.
2367 if (0 == rgu0 && 0 == rgu1) {
2369 } else if (0 == rgu1) {
2375 biDbl.InitFromDigits(rgu0, rgu1, cu);
2383 // Eliminate common powers of 2.
2384 if (c2Dbl > c2Dec) {
2388 // See if biDec has some powers of 2 that we can get rid of.
2389 for (iT = 0; c2Dbl >= 32 && 0 == biDec[iT]; iT++) {
2393 biDec.ShiftUsRight(iT);
2395 Debug.Assert(c2Dbl < 32 || 0 != biDec[0]);
2397 for (iT = 0; iT < c2Dbl && 0 == (uT & (1L << iT)); iT++) {
2401 biDec.ShiftRight(iT);
2408 // There are no common powers of 2 or common powers of 5.
2409 Debug.Assert(0 == c2Dbl || 0 == c2Dec);
2410 Debug.Assert(0 == c5Dbl || 0 == c5Dec);
2412 // Fold in the powers of 5.
2414 biDbl.MulPow5(c5Dbl);
2415 } else if (c5Dec > 0) {
2416 biDec.MulPow5(c5Dec);
2419 // Fold in the powers of 2.
2421 biDbl.ShiftLeft(c2Dbl);
2422 } else if (c2Dec > 0) {
2423 biDec.ShiftLeft(c2Dec);
2426 // Now determine whether biDbl is above or below biDec.
2427 wT = biDbl.CompareTo(biDec);
2431 } else if (wT > 0) {
2432 // biDbl is greater. Recompute with the dbl minus half the distance
2433 // to the next smaller double.
2434 if (0 == AddU(ref rgu0, 0xFFFFFFFF)) {
2435 AddU(ref rgu1, 0xFFFFFFFF);
2437 biDbl.InitFromDigits(rgu0, rgu1, 1 + (0 != rgu1 ? 1 : 0));
2439 biDbl.MulPow5(c5Dbl);
2442 biDbl.ShiftLeft(c2Dbl);
2445 wT = biDbl.CompareTo(biDec);
2446 if (wT > 0 || 0 == wT && 0 != (DblLo(dbl) & 1)) {
2447 // Return the next lower value.
2448 dbl = BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(dbl) - 1);
2451 // biDbl is smaller. Recompute with the dbl plus half the distance
2452 // to the next larger double.
2453 if (0 != AddU(ref rgu0, wAddHi)) {
2456 biDbl.InitFromDigits(rgu0, rgu1, 1 + (0 != rgu1 ? 1 : 0));
2458 biDbl.MulPow5(c5Dbl);
2461 biDbl.ShiftLeft(c2Dbl);
2464 wT = biDbl.CompareTo(biDec);
2465 if (wT < 0 || 0 == wT && 0 != (DblLo(dbl) & 1)) {
2466 // Return the next higher value.
2467 dbl = BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(dbl) + 1);
2474 private void InitFromDouble(double dbl) {
2475 if (0.0 == dbl || IsSpecial(dbl)) {
2488 if (!BigNumber.DblToRgbFast(dbl, mantissa, out exponent, out mantissaSize)) {
2489 BigNumber.DblToRgbPrecise(dbl, mantissa, out exponent, out mantissaSize);
2495 /* ----------------------------------------------------------------------------
2498 Converts an integer to a string according to XPath rules.
2500 private static unsafe string IntToString(int val) {
2501 // The maximum number of characters needed to represent any int value is 11
2502 const int BufSize = 12;
2503 char *pBuf = stackalloc char[BufSize];
2504 char *pch = pBuf += BufSize;
2505 uint u = (uint)(val < 0 ? -val : val);
2508 // Fast division by 10
2509 uint quot = (uint)((0x66666667L * u) >> 32) >> 2;
2510 *(--pch) = (char)((u - quot * 10) + '0');
2514 *(--pch) = (char)(u + '0');
2520 return new string(pch, 0, (int)(pBuf - pch));
2523 /* ----------------------------------------------------------------------------
2526 Converts a floating point number to a string according to XPath rules.
2528 public static string DoubleToString(double dbl) {
2529 Debug.Assert(('0' & 0xF) == 0, "We use (char)(d |'0') to convert digit to char");
2530 int maxSize, sizeInt, sizeFract, cntDigits, ib;
2533 if (IsInteger(dbl, out iVal)) {
2534 return IntToString(iVal);
2537 // Handle NaN and infinity
2538 if (IsSpecial(dbl)) {
2539 if (Double.IsNaN(dbl)) {
2543 Debug.Assert(Double.IsInfinity(dbl));
2544 return dbl < 0 ? "-Infinity" : "Infinity";
2547 // Get decimal digits
2548 FloatingDecimal dec = new FloatingDecimal(dbl);
2549 Debug.Assert(0 != dec.MantissaSize);
2551 // If exponent is negative, size of fraction increases
2552 sizeFract = dec.MantissaSize - dec.Exponent;
2554 if (sizeFract > 0) {
2555 // Decimal consists of a fraction part + possible integer part
2556 sizeInt = (dec.Exponent > 0) ? dec.Exponent : 0;
2558 // Decimal consists of just an integer part
2559 sizeInt = dec.Exponent;
2563 // Sign + integer + fraction + decimal point + leading zero + terminating null
2564 maxSize = sizeInt + sizeFract + 4;
2567 // Allocate output memory
2568 char *pBuf = stackalloc char[maxSize];
2575 cntDigits = dec.MantissaSize;
2580 if (0 != cntDigits) {
2581 // Still mantissa digits left to consume
2582 Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
2583 *pch++ = (char)(dec[ib++] | '0');
2586 // Add trailing zeros
2589 } while (0 != --sizeInt);
2594 if (0 != sizeFract) {
2595 Debug.Assert(0 != cntDigits);
2596 Debug.Assert(sizeFract == cntDigits || sizeFract > cntDigits && pch[-1] == '0');
2599 while (sizeFract > cntDigits) {
2600 // Add leading zeros
2605 Debug.Assert(sizeFract == cntDigits);
2606 while (0 != cntDigits) {
2607 // Output remaining mantissa digits
2608 Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
2609 *pch++ = (char)(dec[ib++] | '0');
2614 Debug.Assert(0 == sizeInt && 0 == cntDigits);
2615 return new string(pBuf, 0, (int)(pch - pBuf));
2619 private static bool IsAsciiDigit(char ch) {
2620 return (uint)(ch - '0') <= 9;
2623 private static bool IsWhitespace(char ch) {
2624 return ch == '\x20' || ch == '\x9' || ch == '\xA' || ch == '\xD';
2627 private static unsafe char *SkipWhitespace(char *pch) {
2628 while (IsWhitespace(*pch)) {
2634 /* ----------------------------------------------------------------------------
2637 Converts a string to a floating point number according to XPath rules.
2638 NaN is returned if the entire string is not a valid number.
2640 This code was stolen from MSXML6 DecimalFormat::parse(). The implementation
2641 depends on the fact that the String objects are always zero-terminated.
2643 public static unsafe double StringToDouble(string s) {
2644 Debug.Assert(('0' & 0xF) == 0, "We use (ch & 0xF) to convert char to digit");
2645 // For the mantissa digits. After leaving the state machine, pchFirstDig
2646 // points to the first digit and pch points just past the last digit.
2647 // numDig is the number of digits. pch - pchFirstDig may be numDig + 1
2648 // (if there is a decimal point).
2650 fixed (char *pchStart = s) {
2652 char *pch = pchStart;
2653 char *pchFirstDig = null;
2656 int sign = 1; // sign of the mantissa
2657 int expAdj = 0; // exponent adjustment
2659 // Enter the state machine
2664 if (IsAsciiDigit(ch)) {
2676 if (IsAsciiDigit(*pch)) {
2681 // MSXML has a bug, we should not allow whitespace after a minus sign
2682 if (IsWhitespace(ch) && sign > 0) {
2683 pch = SkipWhitespace(pch);
2689 // Nothing digested - set the result to NaN and exit.
2693 // Get digits to the left of the decimal point
2696 // Trim leading zeros
2698 } while (ch == '0');
2700 if (!IsAsciiDigit(ch)) {
2701 goto LSkipNonZeroDigits;
2705 Debug.Assert(IsAsciiDigit(ch));
2706 pchFirstDig = pch - 1;
2709 } while (IsAsciiDigit(ch));
2710 numDig = (int)(pch - pchFirstDig) - 1;
2718 Debug.Assert(ch == '.');
2720 if (pchFirstDig == null) {
2721 // Count fractional leading zeros (e.g. six zeros in '0.0000005')
2726 pchFirstDig = pch - 1;
2729 while (IsAsciiDigit(ch)) {
2737 char *pchEnd = pchStart + s.Length;
2738 Debug.Assert(*pchEnd == '\0', "String objects must be zero-terminated");
2740 if (pch < pchEnd && SkipWhitespace(pch) < pchEnd) {
2741 // If we're not at the end of the string, this is not a valid number
2749 Debug.Assert(pchFirstDig != null);
2752 // Assert(StrRChrW(pchFirstDig, &pchFirstDig[numDig], '.') == null);
2754 // Detect special case where number is an integer
2756 Debug.Assert(pchFirstDig != pch);
2757 int iNum = *pchFirstDig & 0xF; // - '0'
2758 while (--numDig != 0) {
2760 Debug.Assert(IsAsciiDigit(*pchFirstDig));
2761 iNum = iNum * 10 + (*pchFirstDig & 0xF); // - '0'
2763 return (double)(sign < 0 ? -iNum : iNum);
2766 // The number has a fractional part
2767 Debug.Assert(expAdj < 0);
2768 // Assert(StrRChrW(pchStart, pch, '.') != null);
2771 // Limit to 50 digits (double is only precise up to 17 or so digits)
2772 if (numDig > FloatingDecimal.MaxDigits) {
2773 pch -= (numDig - FloatingDecimal.MaxDigits);
2774 expAdj += (numDig - FloatingDecimal.MaxDigits);
2775 numDig = FloatingDecimal.MaxDigits;
2778 // Remove trailing zero's from mantissa
2779 Debug.Assert(IsAsciiDigit(*pchFirstDig) && *pchFirstDig != '0');
2781 if (*--pch == '0') {
2784 } else if (*pch != '.') {
2785 Debug.Assert(IsAsciiDigit(*pch) && *pch != '0');
2790 Debug.Assert(pch - pchFirstDig == numDig || pch - pchFirstDig == numDig + 1);
2793 // Construct a floating decimal from the array of digits
2794 Debug.Assert(numDig > 0 && numDig <= FloatingDecimal.MaxDigits);
2796 FloatingDecimal dec = new FloatingDecimal();
2797 dec.Exponent = expAdj + numDig;
2799 dec.MantissaSize = numDig;
2801 fixed (byte *pin = dec.Mantissa) {
2802 byte *mantissa = pin;
2803 while (pchFirstDig < pch) {
2804 if (*pchFirstDig != '.') {
2805 *mantissa = (byte)(*pchFirstDig & 0xF); // - '0'