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.
4 
5 /**
6 * Routines used to manipulate IEEE 754 double-precision numbers, taken from JScript codebase.
7 *
8 * Define NOPARSE if you do not need FloatingDecimal -> double conversions
9 *
10 */
11 
12 using System.Diagnostics;
13 using System.Globalization;
14 
15 namespace System.Xml.Xsl
16 {
17     /**
18     * Converts according to XPath/XSLT rules.
19     */
20     internal static class XPathConvert
21     {
DblHi(double dbl)22         public static uint DblHi(double dbl)
23         {
24             return (uint)(BitConverter.DoubleToInt64Bits(dbl) >> 32);
25         }
26 
DblLo(double dbl)27         public static uint DblLo(double dbl)
28         {
29             return unchecked((uint)BitConverter.DoubleToInt64Bits(dbl));
30         }
31 
32         // Returns true if value is infinite or NaN (exponent bits are all ones)
IsSpecial(double dbl)33         public static bool IsSpecial(double dbl)
34         {
35             return 0 == (~DblHi(dbl) & 0x7FF00000);
36         }
37 
38 #if DEBUG
39         // Returns the next representable neighbor of x in the direction toward y
NextAfter(double x, double y)40         public static double NextAfter(double x, double y)
41         {
42             long bits;
43 
44             if (Double.IsNaN(x))
45             {
46                 return x;
47             }
48             if (Double.IsNaN(y))
49             {
50                 return y;
51             }
52             if (x == y)
53             {
54                 return y;
55             }
56             if (x == 0)
57             {
58                 bits = BitConverter.DoubleToInt64Bits(y) & 1L << 63;
59                 return BitConverter.Int64BitsToDouble(bits | 1);
60             }
61 
62             // At this point x!=y, and x!=0. x can be treated as a 64bit
63             // integer in sign/magnitude representation. To get the next
64             // representable neighbor we add or subtract one from this
65             // integer.
66 
67             bits = BitConverter.DoubleToInt64Bits(x);
68             if (0 < x && x < y || 0 > x && x > y)
69             {
70                 bits++;
71             }
72             else
73             {
74                 bits--;
75             }
76             return BitConverter.Int64BitsToDouble(bits);
77         }
78 
Succ(double x)79         public static double Succ(double x)
80         {
81             return NextAfter(x, Double.PositiveInfinity);
82         }
83 
Pred(double x)84         public static double Pred(double x)
85         {
86             return NextAfter(x, Double.NegativeInfinity);
87         }
88 #endif
89 
90         // Small powers of ten. These are all the powers of ten that have an exact
91         // representation in IEEE double precision format.
92         public static readonly double[] C10toN = {
93             1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
94             1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
95             1e20, 1e21, 1e22,
96         };
97 
98         // Returns 1 if argument is non-zero, and 0 otherwise
NotZero(uint u)99         public static uint NotZero(uint u)
100         {
101             return 0 != u ? 1u : 0u;
102         }
103 
104         /*  ----------------------------------------------------------------------------
105             AddU()
106 
107             Add two unsigned ints and return the carry bit.
108         */
AddU(ref uint u1, uint u2)109         public static uint AddU(ref uint u1, uint u2)
110         {
111             u1 = unchecked(u1 + u2);
112             return u1 < u2 ? 1u : 0u;
113         }
114 
115         /*  ----------------------------------------------------------------------------
116             MulU()
117 
118             Multiply two unsigned ints. Return the low uint and fill uHi with
119             the high uint.
120         */
MulU(uint u1, uint u2, out uint uHi)121         public static uint MulU(uint u1, uint u2, out uint uHi)
122         {
123             ulong result = (ulong)u1 * u2;
124             uHi = (uint)(result >> 32);
125             return unchecked((uint)result);
126         }
127 
128         /*  ----------------------------------------------------------------------------
129             CbitZeroLeft()
130 
131             Return a count of the number of leading 0 bits in u.
132         */
CbitZeroLeft(uint u)133         public static int CbitZeroLeft(uint u)
134         {
135             int cbit = 0;
136 
137             if (0 == (u & 0xFFFF0000))
138             {
139                 cbit += 16;
140                 u <<= 16;
141             }
142             if (0 == (u & 0xFF000000))
143             {
144                 cbit += 8;
145                 u <<= 8;
146             }
147             if (0 == (u & 0xF0000000))
148             {
149                 cbit += 4;
150                 u <<= 4;
151             }
152             if (0 == (u & 0xC0000000))
153             {
154                 cbit += 2;
155                 u <<= 2;
156             }
157             if (0 == (u & 0x80000000))
158             {
159                 cbit += 1;
160                 u <<= 1;
161             }
162             Debug.Assert(0 != (u & 0x80000000));
163 
164             return cbit;
165         }
166 
167         /*  ----------------------------------------------------------------------------
168             IsInteger()
169 
170             If dbl is a whole number in the range of INT_MIN to INT_MAX, return true
171             and the integer in value.  Otherwise, return false.
172         */
IsInteger(double dbl, out int value)173         public static bool IsInteger(double dbl, out int value)
174         {
175             if (!IsSpecial(dbl))
176             {
177                 int i = (int)dbl;
178                 double dblRound = (double)i;
179 
180                 if (dbl == dblRound)
181                 {
182                     value = i;
183                     return true;
184                 }
185             }
186             value = 0;
187             return false;
188         }
189 
190         /**
191         * Implementation of a big floating point number used to ensure adequate
192         * precision when performing calculations.
193         *
194         * Hungarian: num
195         *
196         */
197         private struct BigNumber
198         {
199             private uint _u0;
200             private uint _u1;
201             private uint _u2;
202             private int _exp;
203 
204             // This is a bound on the absolute value of the error. It is based at
205             // one bit before the least significant bit of u0.
206             private uint _error;
207 
208             public uint Error { get { return _error; } }
209 
BigNumberSystem.Xml.Xsl.XPathConvert.BigNumber210             public BigNumber(uint u0, uint u1, uint u2, int exp, uint error)
211             {
212                 _u0 = u0;
213                 _u1 = u1;
214                 _u2 = u2;
215                 _exp = exp;
216                 _error = error;
217             }
218 
219 #if !NOPARSE || DEBUG
220             // Set the value from floating decimal
BigNumberSystem.Xml.Xsl.XPathConvert.BigNumber221             public BigNumber(FloatingDecimal dec)
222             {
223                 Debug.Assert(dec.MantissaSize > 0);
224 
225                 int ib, exponent, mantissaSize, wT;
226                 uint uExtra;
227                 BigNumber[] TenPowers;
228 
229                 ib = 0;
230                 exponent = dec.Exponent;
231                 mantissaSize = dec.MantissaSize;
232 
233                 // Record the first digit
234                 Debug.Assert(dec[ib] > 0 && dec[ib] <= 9);
235                 _u2 = (uint)(dec[ib]) << 28;
236                 _u1 = 0;
237                 _u0 = 0;
238                 _exp = 4;
239                 _error = 0;
240                 exponent--;
241                 Normalize();
242 
243                 while (++ib < mantissaSize)
244                 {
245                     Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
246                     uExtra = MulTenAdd(dec[ib]);
247                     exponent--;
248                     if (0 != uExtra)
249                     {
250                         // We've filled up our precision.
251                         Round(uExtra);
252                         if (ib < mantissaSize - 1)
253                         {
254                             // There are more digits, so add another error bit just for
255                             // safety's sake.
256                             _error++;
257                         }
258                         break;
259                     }
260                 }
261 
262                 // Now multiply by 10^exp
263                 if (0 == exponent)
264                 {
265                     return;
266                 }
267 
268                 if (exponent < 0)
269                 {
270                     TenPowers = s_tenPowersNeg;
271                     exponent = -exponent;
272                 }
273                 else
274                 {
275                     TenPowers = s_tenPowersPos;
276                 }
277 
278                 Debug.Assert(exponent > 0 && exponent < 512);
279                 wT = exponent & 0x1F;
280                 if (wT > 0)
281                 {
282                     Mul(ref TenPowers[wT - 1]);
283                 }
284 
285                 wT = (exponent >> 5) & 0x0F;
286                 if (wT > 0)
287                 {
288                     Mul(ref TenPowers[wT + 30]);
289                 }
290             }
291 
292             // Multiply by ten and add a base 10 digit.
MulTenAddSystem.Xml.Xsl.XPathConvert.BigNumber293             private unsafe uint MulTenAdd(uint digit)
294             {
295                 Debug.Assert(digit <= 9);
296                 Debug.Assert(0 != (_u2 & 0x80000000));
297 
298                 // First "multipy" by eight
299                 _exp += 3;
300                 Debug.Assert(_exp >= 4);
301 
302                 // Initialize the carry values based on digit and exp.
303                 uint* rgu = stackalloc uint[5];
304                 for (int i = 0; i < 5; i++)
305                 {
306                     rgu[i] = 0;
307                 }
308                 if (0 != digit)
309                 {
310                     int idx = 3 - (_exp >> 5);
311                     if (idx < 0)
312                     {
313                         rgu[0] = 1;
314                     }
315                     else
316                     {
317                         int ibit = _exp & 0x1F;
318                         if (ibit < 4)
319                         {
320                             rgu[idx + 1] = digit >> ibit;
321                             if (ibit > 0)
322                             {
323                                 rgu[idx] = digit << (32 - ibit);
324                             }
325                         }
326                         else
327                         {
328                             rgu[idx] = digit << (32 - ibit);
329                         }
330                     }
331                 }
332 
333                 // Shift and add to multiply by ten.
334                 rgu[1] += AddU(ref rgu[0], _u0 << 30);
335                 rgu[2] += AddU(ref _u0, (_u0 >> 2) + (_u1 << 30));
336                 if (0 != rgu[1])
337                 {
338                     rgu[2] += AddU(ref _u0, rgu[1]);
339                 }
340                 rgu[3] += AddU(ref _u1, (_u1 >> 2) + (_u2 << 30));
341                 if (0 != rgu[2])
342                 {
343                     rgu[3] += AddU(ref _u1, rgu[2]);
344                 }
345                 rgu[4] = AddU(ref _u2, (_u2 >> 2) + rgu[3]);
346 
347                 // Handle the final carry.
348                 if (0 != rgu[4])
349                 {
350                     Debug.Assert(1 == rgu[4]);
351                     rgu[0] = (rgu[0] >> 1) | (rgu[0] & 1) | (_u0 << 31);
352                     _u0 = (_u0 >> 1) | (_u1 << 31);
353                     _u1 = (_u1 >> 1) | (_u2 << 31);
354                     _u2 = (_u2 >> 1) | 0x80000000;
355                     _exp++;
356                 }
357 
358                 return rgu[0];
359             }
360 
361             // Round based on the given extra data using IEEE round to nearest rule.
RoundSystem.Xml.Xsl.XPathConvert.BigNumber362             private void Round(uint uExtra)
363             {
364                 if (0 == (uExtra & 0x80000000) || 0 == (uExtra & 0x7FFFFFFF) && 0 == (_u0 & 1))
365                 {
366                     if (0 != uExtra)
367                     {
368                         _error++;
369                     }
370                     return;
371                 }
372                 _error++;
373 
374                 // Round up.
375                 if (0 != AddU(ref _u0, 1) && 0 != AddU(ref _u1, 1) && 0 != AddU(ref _u2, 1))
376                 {
377                     Debug.Assert(this.IsZero);
378                     _u2 = 0x80000000;
379                     _exp++;
380                 }
381             }
382 #endif
383 
384             // Test to see if the num is zero. This works even if we're not normalized.
385             private bool IsZero
386             {
387                 get
388                 {
389                     return (0 == _u2) && (0 == _u1) && (0 == _u0);
390                 }
391             }
392 
393             /*  ----------------------------------------------------------------------------
394                 Normalize()
395 
396                 Normalize the big number - make sure the high bit is 1 or everything is zero
397                 (including the exponent).
398             */
NormalizeSystem.Xml.Xsl.XPathConvert.BigNumber399             private void Normalize()
400             {
401                 int w1, w2;
402 
403                 // Normalize mantissa
404                 if (0 == _u2)
405                 {
406                     if (0 == _u1)
407                     {
408                         if (0 == _u0)
409                         {
410                             _exp = 0;
411                             return;
412                         }
413                         _u2 = _u0;
414                         _u0 = 0;
415                         _exp -= 64;
416                     }
417                     else
418                     {
419                         _u2 = _u1;
420                         _u1 = _u0;
421                         _u0 = 0;
422                         _exp -= 32;
423                     }
424                 }
425 
426                 if (0 != (w1 = CbitZeroLeft(_u2)))
427                 {
428                     w2 = 32 - w1;
429                     _u2 = (_u2 << w1) | (_u1 >> w2);
430                     _u1 = (_u1 << w1) | (_u0 >> w2);
431                     _u0 = (_u0 << w1);
432                     _exp -= w1;
433                 }
434             }
435 
436             /*  ----------------------------------------------------------------------------
437                 Mul()
438 
439                 Multiply this big number by another big number.
440             */
MulSystem.Xml.Xsl.XPathConvert.BigNumber441             private void Mul(ref BigNumber numOp)
442             {
443                 Debug.Assert(0 != (_u2 & 0x80000000));
444                 Debug.Assert(0 != (numOp._u2 & 0x80000000));
445 
446                 //uint *rgu = stackalloc uint[6];
447                 uint rgu0 = 0, rgu1 = 0, rgu2 = 0, rgu3 = 0, rgu4 = 0, rgu5 = 0;
448                 uint uLo, uHi, uT;
449                 uint wCarry;
450 
451                 if (0 != (uT = _u0))
452                 {
453                     uLo = MulU(uT, numOp._u0, out uHi);
454                     rgu0 = uLo;
455                     rgu1 = uHi;
456 
457                     uLo = MulU(uT, numOp._u1, out uHi);
458                     Debug.Assert(uHi < 0xFFFFFFFF);
459                     wCarry = AddU(ref rgu1, uLo);
460                     AddU(ref rgu2, uHi + wCarry);
461 
462                     uLo = MulU(uT, numOp._u2, out uHi);
463                     Debug.Assert(uHi < 0xFFFFFFFF);
464                     wCarry = AddU(ref rgu2, uLo);
465                     AddU(ref rgu3, uHi + wCarry);
466                 }
467 
468                 if (0 != (uT = _u1))
469                 {
470                     uLo = MulU(uT, numOp._u0, out uHi);
471                     Debug.Assert(uHi < 0xFFFFFFFF);
472                     wCarry = AddU(ref rgu1, uLo);
473                     wCarry = AddU(ref rgu2, uHi + wCarry);
474                     if (0 != wCarry && 0 != AddU(ref rgu3, 1))
475                     {
476                         AddU(ref rgu4, 1);
477                     }
478                     uLo = MulU(uT, numOp._u1, out uHi);
479                     Debug.Assert(uHi < 0xFFFFFFFF);
480                     wCarry = AddU(ref rgu2, uLo);
481                     wCarry = AddU(ref rgu3, uHi + wCarry);
482                     if (0 != wCarry)
483                     {
484                         AddU(ref rgu4, 1);
485                     }
486                     uLo = MulU(uT, numOp._u2, out uHi);
487                     Debug.Assert(uHi < 0xFFFFFFFF);
488                     wCarry = AddU(ref rgu3, uLo);
489                     AddU(ref rgu4, uHi + wCarry);
490                 }
491 
492                 uT = _u2;
493                 Debug.Assert(0 != uT);
494                 uLo = MulU(uT, numOp._u0, out uHi);
495                 Debug.Assert(uHi < 0xFFFFFFFF);
496                 wCarry = AddU(ref rgu2, uLo);
497                 wCarry = AddU(ref rgu3, uHi + wCarry);
498                 if (0 != wCarry && 0 != AddU(ref rgu4, 1))
499                 {
500                     AddU(ref rgu5, 1);
501                 }
502                 uLo = MulU(uT, numOp._u1, out uHi);
503                 Debug.Assert(uHi < 0xFFFFFFFF);
504                 wCarry = AddU(ref rgu3, uLo);
505                 wCarry = AddU(ref rgu4, uHi + wCarry);
506                 if (0 != wCarry)
507                 {
508                     AddU(ref rgu5, 1);
509                 }
510                 uLo = MulU(uT, numOp._u2, out uHi);
511                 Debug.Assert(uHi < 0xFFFFFFFF);
512                 wCarry = AddU(ref rgu4, uLo);
513                 AddU(ref rgu5, uHi + wCarry);
514 
515                 // Compute the new exponent
516                 _exp += numOp._exp;
517 
518                 // Accumulate the error. Adding doesn't necessarily give an accurate
519                 // bound if both of the errors are bigger than 2.
520                 Debug.Assert(_error <= 2 || numOp._error <= 2);
521                 _error += numOp._error;
522 
523                 // Handle rounding and normalize.
524                 if (0 == (rgu5 & 0x80000000))
525                 {
526                     if (0 != (rgu2 & 0x40000000) &&
527                             (0 != (rgu2 & 0xBFFFFFFF) || 0 != rgu1 || 0 != rgu0))
528                     {
529                         // Round up by 1
530                         if (0 != AddU(ref rgu2, 0x40000000)
531                             && 0 != AddU(ref rgu3, 1)
532                             && 0 != AddU(ref rgu4, 1)
533                         )
534                         {
535                             AddU(ref rgu5, 1);
536                             if (0 != (rgu5 & 0x80000000))
537                             {
538                                 goto LNormalized;
539                             }
540                         }
541                     }
542 
543                     // have to shift by one
544                     Debug.Assert(0 != (rgu5 & 0x40000000));
545                     _u2 = (rgu5 << 1) | (rgu4 >> 31);
546                     _u1 = (rgu4 << 1) | (rgu3 >> 31);
547                     _u0 = (rgu3 << 1) | (rgu2 >> 31);
548                     _exp--;
549                     _error <<= 1;
550 
551                     // Add one for the error.
552                     if (0 != (rgu2 & 0x7FFFFFFF) || 0 != rgu1 || 0 != rgu0)
553                     {
554                         _error++;
555                     }
556                     return;
557                 }
558                 else
559                 {
560                     if (0 != (rgu2 & 0x80000000) &&
561                         (0 != (rgu3 & 1) || 0 != (rgu2 & 0x7FFFFFFF) ||
562                             0 != rgu1 || 0 != rgu0))
563                     {
564                         // Round up by 1
565                         if (0 != AddU(ref rgu3, 1) && 0 != AddU(ref rgu4, 1) && 0 != AddU(ref rgu5, 1))
566                         {
567                             Debug.Assert(0 == rgu3);
568                             Debug.Assert(0 == rgu4);
569                             Debug.Assert(0 == rgu5);
570                             rgu5 = 0x80000000;
571                             _exp++;
572                         }
573                     }
574                 }
575 
576             LNormalized:
577                 _u2 = rgu5;
578                 _u1 = rgu4;
579                 _u0 = rgu3;
580 
581                 // Add one for the error.
582                 if (0 != rgu2 || 0 != rgu1 || 0 != rgu0)
583                 {
584                     _error++;
585                 }
586             }
587 
588             // Get the double value.
operator doubleSystem.Xml.Xsl.XPathConvert.BigNumber589             public static explicit operator double (BigNumber bn)
590             {
591                 uint uEx;
592                 int exp;
593                 uint dblHi, dblLo;
594 
595                 Debug.Assert(0 != (bn._u2 & 0x80000000));
596 
597                 exp = bn._exp + 1022;
598                 if (exp >= 2047)
599                 {
600                     return Double.PositiveInfinity;
601                 }
602 
603                 // Round after filling in the bits. In the extra uint, we set the low bit
604                 // if there are any extra non-zero bits. This is for breaking the tie when
605                 // deciding whether to round up or down.
606                 if (exp > 0)
607                 {
608                     // Normalized.
609                     dblHi = ((uint)exp << 20) | ((bn._u2 & 0x7FFFFFFF) >> 11);
610                     dblLo = bn._u2 << 21 | bn._u1 >> 11;
611                     uEx = bn._u1 << 21 | NotZero(bn._u0);
612                 }
613                 else if (exp > -20)
614                 {
615                     // Denormal with some high bits.
616                     int wT = 12 - exp;
617                     Debug.Assert(wT >= 12 && wT < 32);
618 
619                     dblHi = bn._u2 >> wT;
620                     dblLo = (bn._u2 << (32 - wT)) | (bn._u1 >> wT);
621                     uEx = (bn._u1 << (32 - wT)) | NotZero(bn._u0);
622                 }
623                 else if (exp == -20)
624                 {
625                     // Denormal with no high bits.
626                     dblHi = 0;
627                     dblLo = bn._u2;
628                     uEx = bn._u1 | (uint)(0 != bn._u0 ? 1 : 0);
629                 }
630                 else if (exp > -52)
631                 {
632                     // Denormal with no high bits.
633                     int wT = -exp - 20;
634                     Debug.Assert(wT > 0 && wT < 32);
635 
636                     dblHi = 0;
637                     dblLo = bn._u2 >> wT;
638                     uEx = bn._u2 << (32 - wT) | NotZero(bn._u1) | NotZero(bn._u0);
639                 }
640                 else if (exp == -52)
641                 {
642                     // Zero unless we round up below.
643                     dblHi = 0;
644                     dblLo = 0;
645                     uEx = bn._u2 | NotZero(bn._u1) | NotZero(bn._u0);
646                 }
647                 else
648                 {
649                     return 0.0;
650                 }
651 
652                 // Handle rounding
653                 if (0 != (uEx & 0x80000000) && (0 != (uEx & 0x7FFFFFFF) || 0 != (dblLo & 1)))
654                 {
655                     // Round up. Note that this works even when we overflow into the
656                     // exponent.
657                     if (0 != AddU(ref dblLo, 1))
658                     {
659                         AddU(ref dblHi, 1);
660                     }
661                 }
662                 return BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
663             }
664 
665             // Lop off the integer part and return it.
UMod1System.Xml.Xsl.XPathConvert.BigNumber666             private uint UMod1()
667             {
668                 if (_exp <= 0)
669                 {
670                     return 0;
671                 }
672                 Debug.Assert(_exp <= 32);
673                 uint uT = _u2 >> (32 - _exp);
674                 _u2 &= (uint)0x7FFFFFFF >> (_exp - 1);
675                 Normalize();
676                 return uT;
677             }
678 
679             // If error is not zero, add it and set error to zero.
MakeUpperBoundSystem.Xml.Xsl.XPathConvert.BigNumber680             public void MakeUpperBound()
681             {
682                 Debug.Assert(_error < 0xFFFFFFFF);
683                 uint uT = (_error + 1) >> 1;
684 
685                 if (0 != uT && 0 != AddU(ref _u0, uT) && 0 != AddU(ref _u1, 1) && 0 != AddU(ref _u2, 1))
686                 {
687                     Debug.Assert(0 == _u2 && 0 == _u1);
688                     _u2 = 0x80000000;
689                     _u0 = (_u0 >> 1) + (_u0 & 1);
690                     _exp++;
691                 }
692                 _error = 0;
693             }
694 
695             // If error is not zero, subtract it and set error to zero.
MakeLowerBoundSystem.Xml.Xsl.XPathConvert.BigNumber696             public void MakeLowerBound()
697             {
698                 Debug.Assert(_error < 0xFFFFFFFF);
699                 uint uT = (_error + 1) >> 1;
700 
701                 if (0 != uT && 0 == AddU(ref _u0, unchecked((uint)-(int)uT)) && 0 == AddU(ref _u1, 0xFFFFFFFF))
702                 {
703                     AddU(ref _u2, 0xFFFFFFFF);
704                     if (0 == (0x80000000 & _u2))
705                     {
706                         Normalize();
707                     }
708                 }
709                 _error = 0;
710             }
711 
712             /*  ----------------------------------------------------------------------------
713                 DblToRgbFast()
714 
715                 Get mantissa bytes (BCD).
716             */
DblToRgbFastSystem.Xml.Xsl.XPathConvert.BigNumber717             public static bool DblToRgbFast(double dbl, byte[] mantissa, out int exponent, out int mantissaSize)
718             {
719                 BigNumber numHH, numHL, numLH, numLL;
720                 BigNumber numBase;
721                 BigNumber tenPower;
722                 int ib, iT;
723                 uint uT, uScale;
724                 byte bHH, bHL, bLH, bLL;
725                 uint uHH, uHL, uLH, uLL;
726                 int wExp2, wExp10 = 0;
727                 double dblInt;
728                 uint dblHi, dblLo;
729 
730                 dblHi = DblHi(dbl);
731                 dblLo = DblLo(dbl);
732 
733                 // Caller should take care of 0, negative and non-finite values.
734                 Debug.Assert(!IsSpecial(dbl));
735                 Debug.Assert(0 < dbl);
736 
737                 // Get numHH and numLL such that numLL < dbl < numHH and the
738                 // difference between adjacent values is half the distance to the next
739                 // representable value (in a double).
740                 wExp2 = (int)((dblHi >> 20) & 0x07FF);
741                 if (wExp2 > 0)
742                 {
743                     // See if dbl is a small integer.
744                     if (wExp2 >= 1023 && wExp2 <= 1075 && dbl == Math.Floor(dbl))
745                     {
746                         goto LSmallInt;
747                     }
748 
749                     // Normalized
750                     numBase._u2 = 0x80000000 | ((dblHi & 0x000FFFFFF) << 11) | (dblLo >> 21);
751                     numBase._u1 = dblLo << 11;
752                     numBase._u0 = 0;
753                     numBase._exp = wExp2 - 1022;
754                     numBase._error = 0;
755 
756                     // Get the upper bound
757                     numHH = numBase;
758                     numHH._u1 |= (1 << 10);
759 
760                     // Get the lower bound. A power of 2 must be special cased.
761                     numLL = numBase;
762                     if (0x80000000 == numLL._u2 && 0 == numLL._u1)
763                     {
764                         // Subtract (0x00000000, 0x00000200, 0x00000000). Same as adding
765                         // (0xFFFFFFFF, 0xFFFFFE00, 0x00000000)
766                         uT = 0xFFFFFE00;
767                     }
768                     else
769                     {
770                         // Subtract (0x00000000, 0x00000400, 0x00000000). Same as adding
771                         // (0xFFFFFFFF, 0xFFFFFC00, 0x00000000)
772                         uT = 0xFFFFFC00;
773                     }
774                     if (0 == AddU(ref numLL._u1, uT))
775                     {
776                         AddU(ref numLL._u2, 0xFFFFFFFF);
777                         if (0 == (0x80000000 & numLL._u2))
778                         {
779                             numLL.Normalize();
780                         }
781                     }
782                 }
783                 else
784                 {
785                     // Denormal
786                     numBase._u2 = dblHi & 0x000FFFFF;
787                     numBase._u1 = dblLo;
788                     numBase._u0 = 0;
789                     numBase._exp = -1010;
790                     numBase._error = 0;
791 
792                     // Get the upper bound
793                     numHH = numBase;
794                     numHH._u0 = 0x80000000;
795 
796                     // Get the lower bound
797                     numLL = numHH;
798                     if (0 == AddU(ref numLL._u1, 0xFFFFFFFF))
799                     {
800                         AddU(ref numLL._u2, 0xFFFFFFFF);
801                     }
802 
803                     numBase.Normalize();
804                     numHH.Normalize();
805                     numLL.Normalize();
806                 }
807 
808                 // Multiply by powers of ten until 0 < numHH.exp < 32.
809                 if (numHH._exp >= 32)
810                 {
811                     iT = (numHH._exp - 25) * 15 / -s_tenPowersNeg[45]._exp;
812                     Debug.Assert(iT >= 0 && iT < 16);
813                     if (iT > 0)
814                     {
815                         tenPower = s_tenPowersNeg[30 + iT];
816                         Debug.Assert(numHH._exp + tenPower._exp > 1);
817                         numHH.Mul(ref tenPower);
818                         numLL.Mul(ref tenPower);
819                         wExp10 += iT * 32;
820                     }
821 
822                     if (numHH._exp >= 32)
823                     {
824                         iT = (numHH._exp - 25) * 32 / -s_tenPowersNeg[31]._exp;
825                         Debug.Assert(iT > 0 && iT <= 32);
826                         tenPower = s_tenPowersNeg[iT - 1];
827                         Debug.Assert(numHH._exp + tenPower._exp > 1);
828                         numHH.Mul(ref tenPower);
829                         numLL.Mul(ref tenPower);
830                         wExp10 += iT;
831                     }
832                 }
833                 else if (numHH._exp < 1)
834                 {
835                     iT = (25 - numHH._exp) * 15 / s_tenPowersPos[45]._exp;
836                     Debug.Assert(iT >= 0 && iT < 16);
837                     if (iT > 0)
838                     {
839                         tenPower = s_tenPowersPos[30 + iT];
840                         Debug.Assert(numHH._exp + tenPower._exp <= 32);
841                         numHH.Mul(ref tenPower);
842                         numLL.Mul(ref tenPower);
843                         wExp10 -= iT * 32;
844                     }
845 
846                     if (numHH._exp < 1)
847                     {
848                         iT = (25 - numHH._exp) * 32 / s_tenPowersPos[31]._exp;
849                         Debug.Assert(iT > 0 && iT <= 32);
850                         tenPower = s_tenPowersPos[iT - 1];
851                         Debug.Assert(numHH._exp + tenPower._exp <= 32);
852                         numHH.Mul(ref tenPower);
853                         numLL.Mul(ref tenPower);
854                         wExp10 -= iT;
855                     }
856                 }
857 
858                 Debug.Assert(numHH._exp > 0 && numHH._exp < 32);
859 
860                 // Get the upper and lower bounds for these.
861                 numHL = numHH;
862                 numHH.MakeUpperBound();
863                 numHL.MakeLowerBound();
864                 uHH = numHH.UMod1();
865                 uHL = numHL.UMod1();
866                 numLH = numLL;
867                 numLH.MakeUpperBound();
868                 numLL.MakeLowerBound();
869                 uLH = numLH.UMod1();
870                 uLL = numLL.UMod1();
871                 Debug.Assert(uLL <= uLH && uLH <= uHL && uHL <= uHH);
872 
873                 // Find the starting scale
874                 uScale = 1;
875                 if (uHH >= 100000000)
876                 {
877                     uScale = 100000000;
878                     wExp10 += 8;
879                 }
880                 else
881                 {
882                     if (uHH >= 10000)
883                     {
884                         uScale = 10000;
885                         wExp10 += 4;
886                     }
887                     if (uHH >= 100 * uScale)
888                     {
889                         uScale *= 100;
890                         wExp10 += 2;
891                     }
892                 }
893                 if (uHH >= 10 * uScale)
894                 {
895                     uScale *= 10;
896                     wExp10++;
897                 }
898                 wExp10++;
899                 Debug.Assert(uHH >= uScale && uHH / uScale < 10);
900 
901                 for (ib = 0; ;)
902                 {
903                     Debug.Assert(uLL <= uHH);
904                     bHH = (byte)(uHH / uScale);
905                     uHH %= uScale;
906                     bLL = (byte)(uLL / uScale);
907                     uLL %= uScale;
908 
909                     if (bHH != bLL)
910                     {
911                         break;
912                     }
913 
914                     Debug.Assert(0 != uHH || !numHH.IsZero);
915                     mantissa[ib++] = bHH;
916 
917                     if (1 == uScale)
918                     {
919                         // Multiply by 10^8.
920                         uScale = 10000000;
921 
922                         numHH.Mul(ref s_tenPowersPos[7]);
923                         numHH.MakeUpperBound();
924                         uHH = numHH.UMod1();
925                         if (uHH >= 100000000)
926                         {
927                             goto LFail;
928                         }
929                         numHL.Mul(ref s_tenPowersPos[7]);
930                         numHL.MakeLowerBound();
931                         uHL = numHL.UMod1();
932 
933                         numLH.Mul(ref s_tenPowersPos[7]);
934                         numLH.MakeUpperBound();
935                         uLH = numLH.UMod1();
936                         numLL.Mul(ref s_tenPowersPos[7]);
937                         numLL.MakeLowerBound();
938                         uLL = numLL.UMod1();
939                     }
940                     else
941                     {
942                         uScale /= 10;
943                     }
944                 }
945 
946                 // LL and HH diverged. Get the digit values for LH and HL.
947                 Debug.Assert(0 <= bLL && bLL < bHH && bHH <= 9);
948                 bLH = (byte)((uLH / uScale) % 10);
949                 uLH %= uScale;
950                 bHL = (byte)((uHL / uScale) % 10);
951                 uHL %= uScale;
952 
953                 if (bLH >= bHL)
954                 {
955                     goto LFail;
956                 }
957 
958                 // LH and HL also diverged.
959 
960                 // We can get by with one fewer digit if: LL == LH and bLH is zero
961                 // and the current value of LH is zero and the least significant bit of
962                 // the double is zero. In this case, we have exactly the digit sequence
963                 // for the original numLL and IEEE and will rounds numLL up to the double.
964                 if (0 == bLH && 0 == uLH && numLH.IsZero && 0 == (dblLo & 1))
965                 {
966                 }
967                 else if (bHL - bLH > 1)
968                 {
969                     // HL and LH differ by at least two in this digit, so split
970                     // the difference.
971                     mantissa[ib++] = (byte)((bHL + bLH + 1) / 2);
972                 }
973                 else if (0 != uHL || !numHL.IsZero || 0 == (dblLo & 1))
974                 {
975                     // We can just use bHL because this guarantees that we're bigger than
976                     // LH and less than HL, so must convert to the double.
977                     mantissa[ib++] = bHL;
978                 }
979                 else
980                 {
981                     goto LFail;
982                 }
983 
984                 exponent = wExp10;
985                 mantissaSize = ib;
986                 goto LSucceed;
987 
988             LSmallInt:
989                 // dbl should be an integer from 1 to (2^53 - 1).
990                 dblInt = dbl;
991                 Debug.Assert(dblInt == Math.Floor(dblInt) && 1 <= dblInt && dblInt <= 9007199254740991.0d);
992 
993                 iT = 0;
994                 if (dblInt >= C10toN[iT + 8])
995                 {
996                     iT += 8;
997                 }
998                 if (dblInt >= C10toN[iT + 4])
999                 {
1000                     iT += 4;
1001                 }
1002                 if (dblInt >= C10toN[iT + 2])
1003                 {
1004                     iT += 2;
1005                 }
1006                 if (dblInt >= C10toN[iT + 1])
1007                 {
1008                     iT += 1;
1009                 }
1010                 Debug.Assert(iT >= 0 && iT <= 15);
1011                 Debug.Assert(dblInt >= C10toN[iT] && dblInt < C10toN[iT + 1]);
1012                 exponent = iT + 1;
1013 
1014                 for (ib = 0; 0 != dblInt; iT--)
1015                 {
1016                     Debug.Assert(iT >= 0);
1017                     bHH = (byte)(dblInt / C10toN[iT]);
1018                     dblInt -= bHH * C10toN[iT];
1019                     Debug.Assert(dblInt == Math.Floor(dblInt) && 0 <= dblInt && dblInt < C10toN[iT]);
1020                     mantissa[ib++] = bHH;
1021                 }
1022                 mantissaSize = ib;
1023 
1024             LSucceed:
1025 
1026 #if DEBUG
1027                 // Verify that precise is working and gives the same answer
1028                 if (mantissaSize > 0)
1029                 {
1030                     byte[] mantissaPrec = new byte[20];
1031                     int exponentPrec, mantissaSizePrec, idx;
1032 
1033                     DblToRgbPrecise(dbl, mantissaPrec, out exponentPrec, out mantissaSizePrec);
1034                     Debug.Assert(exponent == exponentPrec && mantissaSize == mantissaSizePrec);
1035                     // Assert(!memcmp(mantissa, mantissaPrec, mantissaSizePrec - 1));
1036                     bool equal = true;
1037                     for (idx = 0; idx < mantissaSize; idx++)
1038                     {
1039                         equal &= (
1040                             (mantissa[idx] == mantissaPrec[idx]) ||
1041                             (idx == mantissaSize - 1) && Math.Abs(mantissa[idx] - mantissaPrec[idx]) <= 1
1042                         );
1043                     }
1044                     Debug.Assert(equal, "DblToRgbFast and DblToRgbPrecise should give the same result");
1045                 }
1046 #endif
1047 
1048                 return true;
1049 
1050             LFail:
1051                 exponent = mantissaSize = 0;
1052                 return false;
1053             }
1054 
1055             /*  ----------------------------------------------------------------------------
1056                 DblToRgbPrecise()
1057 
1058                 Uses big integer arithmetic to get the sequence of digits.
1059             */
DblToRgbPreciseSystem.Xml.Xsl.XPathConvert.BigNumber1060             public static void DblToRgbPrecise(double dbl, byte[] mantissa, out int exponent, out int mantissaSize)
1061             {
1062                 BigInteger biNum = new BigInteger();
1063                 BigInteger biDen = new BigInteger();
1064                 BigInteger biHi = new BigInteger();
1065                 BigInteger biLo = new BigInteger();
1066                 BigInteger biT = new BigInteger();
1067                 BigInteger biHiLo;
1068                 byte bT;
1069                 bool fPow2;
1070                 int ib, cu;
1071                 int wExp10, wExp2, w1, w2;
1072                 int c2Num, c2Den, c5Num, c5Den;
1073                 double dblT;
1074                 //uint *rgu = stackalloc uint[2];
1075                 uint rgu0, rgu1;
1076                 uint dblHi, dblLo;
1077 
1078                 dblHi = DblHi(dbl);
1079                 dblLo = DblLo(dbl);
1080 
1081                 // Caller should take care of 0, negative and non-finite values.
1082                 Debug.Assert(!IsSpecial(dbl));
1083                 Debug.Assert(0 < dbl);
1084 
1085                 // Init the Denominator, Hi error and Lo error bigints.
1086                 biDen.InitFromDigits(1, 0, 1);
1087                 biHi.InitFromDigits(1, 0, 1);
1088 
1089                 wExp2 = (int)(((dblHi & 0x7FF00000) >> 20) - 1075);
1090                 rgu1 = dblHi & 0x000FFFFF;
1091                 rgu0 = dblLo;
1092                 cu = 2;
1093                 fPow2 = false;
1094                 if (wExp2 == -1075)
1095                 {
1096                     // dbl is denormalized.
1097                     Debug.Assert(0 == (dblHi & 0x7FF00000));
1098                     if (0 == rgu1)
1099                     {
1100                         cu = 1;
1101                     }
1102 
1103                     // Get dblT such that dbl / dblT is a power of 2 and 1 <= dblT < 2.
1104                     // First multiply by a power of 2 to get a normalized value.
1105                     dblT = BitConverter.Int64BitsToDouble(0x4FF00000L << 32);
1106                     dblT *= dbl;
1107                     Debug.Assert(0 != (DblHi(dblT) & 0x7FF00000));
1108 
1109                     // This is the power of 2.
1110                     w1 = (int)((DblHi(dblT) & 0x7FF00000) >> 20) - (256 + 1023);
1111 
1112                     dblHi = DblHi(dblT);
1113                     dblHi &= 0x000FFFFF;
1114                     dblHi |= 0x3FF00000;
1115                     dblT = BitConverter.Int64BitsToDouble((long)dblHi << 32 | DblLo(dblT));
1116 
1117                     // Adjust wExp2 because we don't have the implicit bit.
1118                     wExp2++;
1119                 }
1120                 else
1121                 {
1122                     // Get dblT such that dbl / dblT is a power of 2 and 1 <= dblT < 2.
1123                     // First multiply by a power of 2 to get a normalized value.
1124                     dblHi &= 0x000FFFFF;
1125                     dblHi |= 0x3FF00000;
1126                     dblT = BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
1127 
1128                     // This is the power of 2.
1129                     w1 = wExp2 + 52;
1130 
1131                     if (0 == rgu0 && 0 == rgu1 && wExp2 > -1074)
1132                     {
1133                         // Power of 2 bigger than smallest normal. The next smaller
1134                         // representable value is closer than the next larger value.
1135                         rgu1 = 0x00200000;
1136                         wExp2--;
1137                         fPow2 = true;
1138                     }
1139                     else
1140                     {
1141                         // Normalized and not a power of 2 or the smallest normal. The
1142                         // representable values on either side are the same distance away.
1143                         rgu1 |= 0x00100000;
1144                     }
1145                 }
1146 
1147                 // Compute an approximation to the base 10 log. This is borrowed from
1148                 // David Gay's paper.
1149                 Debug.Assert(1 <= dblT && dblT < 2);
1150                 dblT = (dblT - 1.5) * 0.289529654602168 + 0.1760912590558 +
1151                     w1 * 0.301029995663981;
1152                 wExp10 = (int)dblT;
1153                 if (dblT < 0 && dblT != wExp10)
1154                 {
1155                     wExp10--;
1156                 }
1157 
1158                 if (wExp2 >= 0)
1159                 {
1160                     c2Num = wExp2;
1161                     c2Den = 0;
1162                 }
1163                 else
1164                 {
1165                     c2Num = 0;
1166                     c2Den = -wExp2;
1167                 }
1168 
1169                 if (wExp10 >= 0)
1170                 {
1171                     c5Num = 0;
1172                     c5Den = wExp10;
1173                     c2Den += wExp10;
1174                 }
1175                 else
1176                 {
1177                     c2Num -= wExp10;
1178                     c5Num = -wExp10;
1179                     c5Den = 0;
1180                 }
1181 
1182                 if (c2Num > 0 && c2Den > 0)
1183                 {
1184                     w1 = c2Num < c2Den ? c2Num : c2Den;
1185                     c2Num -= w1;
1186                     c2Den -= w1;
1187                 }
1188                 // We need a bit for the Hi and Lo values.
1189                 c2Num++;
1190                 c2Den++;
1191 
1192                 // Initialize biNum and multiply by powers of 5.
1193                 if (c5Num > 0)
1194                 {
1195                     Debug.Assert(0 == c5Den);
1196                     biHi.MulPow5(c5Num);
1197                     biNum.InitFromBigint(biHi);
1198                     if (1 == cu)
1199                     {
1200                         biNum.MulAdd(rgu0, 0);
1201                     }
1202                     else
1203                     {
1204                         biNum.MulAdd(rgu1, 0);
1205                         biNum.ShiftLeft(32);
1206                         if (0 != rgu0)
1207                         {
1208                             biT.InitFromBigint(biHi);
1209                             biT.MulAdd(rgu0, 0);
1210                             biNum.Add(biT);
1211                         }
1212                     }
1213                 }
1214                 else
1215                 {
1216                     Debug.Assert(cu <= 2);
1217                     biNum.InitFromDigits(rgu0, rgu1, cu);
1218                     if (c5Den > 0)
1219                     {
1220                         biDen.MulPow5(c5Den);
1221                     }
1222                 }
1223 
1224                 // BigInteger.DivRem only works if the 4 high bits of the divisor are 0.
1225                 // It works most efficiently if there are exactly 4 zero high bits.
1226                 // Adjust c2Den and c2Num to guarantee this.
1227                 w1 = CbitZeroLeft(biDen[biDen.Length - 1]);
1228                 w1 = (w1 + 28 - c2Den) & 0x1F;
1229                 c2Num += w1;
1230                 c2Den += w1;
1231 
1232                 // Multiply by powers of 2.
1233                 Debug.Assert(c2Num > 0 && c2Den > 0);
1234                 biNum.ShiftLeft(c2Num);
1235                 if (c2Num > 1)
1236                 {
1237                     biHi.ShiftLeft(c2Num - 1);
1238                 }
1239                 biDen.ShiftLeft(c2Den);
1240                 Debug.Assert(0 == (biDen[biDen.Length - 1] & 0xF0000000));
1241                 Debug.Assert(0 != (biDen[biDen.Length - 1] & 0x08000000));
1242 
1243                 // Get biHiLo and handle the power of 2 case where biHi needs to be doubled.
1244                 if (fPow2)
1245                 {
1246                     biHiLo = biLo;
1247                     biHiLo.InitFromBigint(biHi);
1248                     biHi.ShiftLeft(1);
1249                 }
1250                 else
1251                 {
1252                     biHiLo = biHi;
1253                 }
1254 
1255                 for (ib = 0; ;)
1256                 {
1257                     bT = (byte)biNum.DivRem(biDen);
1258                     if (0 == ib && 0 == bT)
1259                     {
1260                         // Our estimate of wExp10 was too big. Oh well.
1261                         wExp10--;
1262                         goto LSkip;
1263                     }
1264 
1265                     // w1 = sign(biNum - biHiLo).
1266                     w1 = biNum.CompareTo(biHiLo);
1267 
1268                     // w2 = sign(biNum + biHi - biDen).
1269                     if (biDen.CompareTo(biHi) < 0)
1270                     {
1271                         w2 = 1;
1272                     }
1273                     else
1274                     {
1275                         // REVIEW: is there a faster way to do this?
1276                         biT.InitFromBigint(biDen);
1277                         biT.Subtract(biHi);
1278                         w2 = biNum.CompareTo(biT);
1279                     }
1280 
1281                     // if (biNum + biHi == biDen && even)
1282                     if (0 == w2 && 0 == (dblLo & 1))
1283                     {
1284                         // Rounding up this digit produces exactly (biNum + biHi) which
1285                         // StrToDbl will round down to dbl.
1286                         if (bT == 9)
1287                         {
1288                             goto LRoundUp9;
1289                         }
1290                         if (w1 > 0)
1291                         {
1292                             bT++;
1293                         }
1294                         mantissa[ib++] = bT;
1295                         break;
1296                     }
1297 
1298                     // if (biNum < biHiLo || biNum == biHiLo && even)
1299                     if (w1 < 0 || 0 == w1 && 0 == (dblLo & 1))
1300                     {
1301                         // if (biNum + biHi > biDen)
1302                         if (w2 > 0)
1303                         {
1304                             // Decide whether to round up.
1305                             biNum.ShiftLeft(1);
1306                             w2 = biNum.CompareTo(biDen);
1307                             if ((w2 > 0 || 0 == w2 && (0 != (bT & 1))) && bT++ == 9)
1308                             {
1309                                 goto LRoundUp9;
1310                             }
1311                         }
1312                         mantissa[ib++] = bT;
1313                         break;
1314                     }
1315 
1316                     // if (biNum + biHi > biDen)
1317                     if (w2 > 0)
1318                     {
1319                         // Round up and be done with it.
1320                         if (bT != 9)
1321                         {
1322                             mantissa[ib++] = (byte)(bT + 1);
1323                             break;
1324                         }
1325                         goto LRoundUp9;
1326                     }
1327 
1328                     // Save the digit.
1329                     mantissa[ib++] = bT;
1330 
1331                 LSkip:
1332                     biNum.MulAdd(10, 0);
1333                     biHi.MulAdd(10, 0);
1334                     if ((object)biHiLo != (object)biHi)
1335                     {
1336                         biHiLo.MulAdd(10, 0);
1337                     }
1338                     continue;
1339 
1340                 LRoundUp9:
1341                     while (ib > 0)
1342                     {
1343                         if (mantissa[--ib] != 9)
1344                         {
1345                             mantissa[ib++]++;
1346                             goto LReturn;
1347                         }
1348                     }
1349                     wExp10++;
1350                     mantissa[ib++] = 1;
1351                     break;
1352                 }
1353 
1354             LReturn:
1355                 exponent = wExp10 + 1;
1356                 mantissaSize = ib;
1357             }
1358 
1359             #region Powers of ten
1360             private static readonly BigNumber[] s_tenPowersPos = new BigNumber[46] {
1361                 // Positive powers of 10 to 96 bits precision.
1362                 new BigNumber( 0x00000000, 0x00000000, 0xA0000000,     4, 0 ), // 10^1
1363                 new BigNumber( 0x00000000, 0x00000000, 0xC8000000,     7, 0 ), // 10^2
1364                 new BigNumber( 0x00000000, 0x00000000, 0xFA000000,    10, 0 ), // 10^3
1365                 new BigNumber( 0x00000000, 0x00000000, 0x9C400000,    14, 0 ), // 10^4
1366                 new BigNumber( 0x00000000, 0x00000000, 0xC3500000,    17, 0 ), // 10^5
1367                 new BigNumber( 0x00000000, 0x00000000, 0xF4240000,    20, 0 ), // 10^6
1368                 new BigNumber( 0x00000000, 0x00000000, 0x98968000,    24, 0 ), // 10^7
1369                 new BigNumber( 0x00000000, 0x00000000, 0xBEBC2000,    27, 0 ), // 10^8
1370                 new BigNumber( 0x00000000, 0x00000000, 0xEE6B2800,    30, 0 ), // 10^9
1371                 new BigNumber( 0x00000000, 0x00000000, 0x9502F900,    34, 0 ), // 10^10
1372                 new BigNumber( 0x00000000, 0x00000000, 0xBA43B740,    37, 0 ), // 10^11
1373                 new BigNumber( 0x00000000, 0x00000000, 0xE8D4A510,    40, 0 ), // 10^12
1374                 new BigNumber( 0x00000000, 0x00000000, 0x9184E72A,    44, 0 ), // 10^13
1375                 new BigNumber( 0x00000000, 0x80000000, 0xB5E620F4,    47, 0 ), // 10^14
1376                 new BigNumber( 0x00000000, 0xA0000000, 0xE35FA931,    50, 0 ), // 10^15
1377                 new BigNumber( 0x00000000, 0x04000000, 0x8E1BC9BF,    54, 0 ), // 10^16
1378                 new BigNumber( 0x00000000, 0xC5000000, 0xB1A2BC2E,    57, 0 ), // 10^17
1379                 new BigNumber( 0x00000000, 0x76400000, 0xDE0B6B3A,    60, 0 ), // 10^18
1380                 new BigNumber( 0x00000000, 0x89E80000, 0x8AC72304,    64, 0 ), // 10^19
1381                 new BigNumber( 0x00000000, 0xAC620000, 0xAD78EBC5,    67, 0 ), // 10^20
1382                 new BigNumber( 0x00000000, 0x177A8000, 0xD8D726B7,    70, 0 ), // 10^21
1383                 new BigNumber( 0x00000000, 0x6EAC9000, 0x87867832,    74, 0 ), // 10^22
1384                 new BigNumber( 0x00000000, 0x0A57B400, 0xA968163F,    77, 0 ), // 10^23
1385                 new BigNumber( 0x00000000, 0xCCEDA100, 0xD3C21BCE,    80, 0 ), // 10^24
1386                 new BigNumber( 0x00000000, 0x401484A0, 0x84595161,    84, 0 ), // 10^25
1387                 new BigNumber( 0x00000000, 0x9019A5C8, 0xA56FA5B9,    87, 0 ), // 10^26
1388                 new BigNumber( 0x00000000, 0xF4200F3A, 0xCECB8F27,    90, 0 ), // 10^27
1389                 new BigNumber( 0x40000000, 0xF8940984, 0x813F3978,    94, 0 ), // 10^28
1390                 new BigNumber( 0x50000000, 0x36B90BE5, 0xA18F07D7,    97, 0 ), // 10^29
1391                 new BigNumber( 0xA4000000, 0x04674EDE, 0xC9F2C9CD,   100, 0 ), // 10^30
1392                 new BigNumber( 0x4D000000, 0x45812296, 0xFC6F7C40,   103, 0 ), // 10^31
1393                 new BigNumber( 0xF0200000, 0x2B70B59D, 0x9DC5ADA8,   107, 0 ), // 10^32
1394                 new BigNumber( 0x3CBF6B72, 0xFFCFA6D5, 0xC2781F49,   213, 1 ), // 10^64   (rounded up)
1395                 new BigNumber( 0xC5CFE94F, 0xC59B14A2, 0xEFB3AB16,   319, 1 ), // 10^96   (rounded up)
1396                 new BigNumber( 0xC66F336C, 0x80E98CDF, 0x93BA47C9,   426, 1 ), // 10^128
1397                 new BigNumber( 0x577B986B, 0x7FE617AA, 0xB616A12B,   532, 1 ), // 10^160
1398                 new BigNumber( 0x85BBE254, 0x3927556A, 0xE070F78D,   638, 1 ), // 10^192  (rounded up)
1399                 new BigNumber( 0x82BD6B71, 0xE33CC92F, 0x8A5296FF,   745, 1 ), // 10^224  (rounded up)
1400                 new BigNumber( 0xDDBB901C, 0x9DF9DE8D, 0xAA7EEBFB,   851, 1 ), // 10^256  (rounded up)
1401                 new BigNumber( 0x73832EEC, 0x5C6A2F8C, 0xD226FC19,   957, 1 ), // 10^288
1402                 new BigNumber( 0xE6A11583, 0xF2CCE375, 0x81842F29,  1064, 1 ), // 10^320
1403                 new BigNumber( 0x5EBF18B7, 0xDB900AD2, 0x9FA42700,  1170, 1 ), // 10^352  (rounded up)
1404                 new BigNumber( 0x1027FFF5, 0xAEF8AA17, 0xC4C5E310,  1276, 1 ), // 10^384
1405                 new BigNumber( 0xB5E54F71, 0xE9B09C58, 0xF28A9C07,  1382, 1 ), // 10^416
1406                 new BigNumber( 0xA7EA9C88, 0xEBF7F3D3, 0x957A4AE1,  1489, 1 ), // 10^448
1407                 new BigNumber( 0x7DF40A74, 0x0795A262, 0xB83ED8DC,  1595, 1 ), // 10^480
1408             };
1409 
1410             private static readonly BigNumber[] s_tenPowersNeg = new BigNumber[46] {
1411                 // Negative powers of 10 to 96 bits precision.
1412                 new BigNumber( 0xCCCCCCCD, 0xCCCCCCCC, 0xCCCCCCCC,    -3, 1 ), // 10^-1   (rounded up)
1413                 new BigNumber( 0x3D70A3D7, 0x70A3D70A, 0xA3D70A3D,    -6, 1 ), // 10^-2
1414                 new BigNumber( 0x645A1CAC, 0x8D4FDF3B, 0x83126E97,    -9, 1 ), // 10^-3
1415                 new BigNumber( 0xD3C36113, 0xE219652B, 0xD1B71758,   -13, 1 ), // 10^-4
1416                 new BigNumber( 0x0FCF80DC, 0x1B478423, 0xA7C5AC47,   -16, 1 ), // 10^-5
1417                 new BigNumber( 0xA63F9A4A, 0xAF6C69B5, 0x8637BD05,   -19, 1 ), // 10^-6   (rounded up)
1418                 new BigNumber( 0x3D329076, 0xE57A42BC, 0xD6BF94D5,   -23, 1 ), // 10^-7
1419                 new BigNumber( 0xFDC20D2B, 0x8461CEFC, 0xABCC7711,   -26, 1 ), // 10^-8
1420                 new BigNumber( 0x31680A89, 0x36B4A597, 0x89705F41,   -29, 1 ), // 10^-9   (rounded up)
1421                 new BigNumber( 0xB573440E, 0xBDEDD5BE, 0xDBE6FECE,   -33, 1 ), // 10^-10
1422                 new BigNumber( 0xF78F69A5, 0xCB24AAFE, 0xAFEBFF0B,   -36, 1 ), // 10^-11
1423                 new BigNumber( 0xF93F87B7, 0x6F5088CB, 0x8CBCCC09,   -39, 1 ), // 10^-12
1424                 new BigNumber( 0x2865A5F2, 0x4BB40E13, 0xE12E1342,   -43, 1 ), // 10^-13
1425                 new BigNumber( 0x538484C2, 0x095CD80F, 0xB424DC35,   -46, 1 ), // 10^-14  (rounded up)
1426                 new BigNumber( 0x0F9D3701, 0x3AB0ACD9, 0x901D7CF7,   -49, 1 ), // 10^-15
1427                 new BigNumber( 0x4C2EBE68, 0xC44DE15B, 0xE69594BE,   -53, 1 ), // 10^-16
1428                 new BigNumber( 0x09BEFEBA, 0x36A4B449, 0xB877AA32,   -56, 1 ), // 10^-17  (rounded up)
1429                 new BigNumber( 0x3AFF322E, 0x921D5D07, 0x9392EE8E,   -59, 1 ), // 10^-18
1430                 new BigNumber( 0x2B31E9E4, 0xB69561A5, 0xEC1E4A7D,   -63, 1 ), // 10^-19  (rounded up)
1431                 new BigNumber( 0x88F4BB1D, 0x92111AEA, 0xBCE50864,   -66, 1 ), // 10^-20  (rounded up)
1432                 new BigNumber( 0xD3F6FC17, 0x74DA7BEE, 0x971DA050,   -69, 1 ), // 10^-21  (rounded up)
1433                 new BigNumber( 0x5324C68B, 0xBAF72CB1, 0xF1C90080,   -73, 1 ), // 10^-22
1434                 new BigNumber( 0x75B7053C, 0x95928A27, 0xC16D9A00,   -76, 1 ), // 10^-23
1435                 new BigNumber( 0xC4926A96, 0x44753B52, 0x9ABE14CD,   -79, 1 ), // 10^-24
1436                 new BigNumber( 0x3A83DDBE, 0xD3EEC551, 0xF79687AE,   -83, 1 ), // 10^-25  (rounded up)
1437                 new BigNumber( 0x95364AFE, 0x76589DDA, 0xC6120625,   -86, 1 ), // 10^-26
1438                 new BigNumber( 0x775EA265, 0x91E07E48, 0x9E74D1B7,   -89, 1 ), // 10^-27  (rounded up)
1439                 new BigNumber( 0x8BCA9D6E, 0x8300CA0D, 0xFD87B5F2,   -93, 1 ), // 10^-28
1440                 new BigNumber( 0x096EE458, 0x359A3B3E, 0xCAD2F7F5,   -96, 1 ), // 10^-29
1441                 new BigNumber( 0xA125837A, 0x5E14FC31, 0xA2425FF7,   -99, 1 ), // 10^-30  (rounded up)
1442                 new BigNumber( 0x80EACF95, 0x4B43FCF4, 0x81CEB32C,  -102, 1 ), // 10^-31  (rounded up)
1443                 new BigNumber( 0x67DE18EE, 0x453994BA, 0xCFB11EAD,  -106, 1 ), // 10^-32  (rounded up)
1444                 new BigNumber( 0x3F2398D7, 0xA539E9A5, 0xA87FEA27,  -212, 1 ), // 10^-64
1445                 new BigNumber( 0x11DBCB02, 0xFD75539B, 0x88B402F7,  -318, 1 ), // 10^-96
1446                 new BigNumber( 0xAC7CB3F7, 0x64BCE4A0, 0xDDD0467C,  -425, 1 ), // 10^-128 (rounded up)
1447                 new BigNumber( 0x59ED2167, 0xDB73A093, 0xB3F4E093,  -531, 1 ), // 10^-160
1448                 new BigNumber( 0x7B6306A3, 0x5423CC06, 0x91FF8377,  -637, 1 ), // 10^-192
1449                 new BigNumber( 0xA4F8BF56, 0x4A314EBD, 0xECE53CEC,  -744, 1 ), // 10^-224
1450                 new BigNumber( 0xFA911156, 0x637A1939, 0xC0314325,  -850, 1 ), // 10^-256 (rounded up)
1451                 new BigNumber( 0x4EE367F9, 0x836AC577, 0x9BECCE62,  -956, 1 ), // 10^-288
1452                 new BigNumber( 0x8920B099, 0x478238D0, 0xFD00B897, -1063, 1 ), // 10^-320 (rounded up)
1453                 new BigNumber( 0x0092757C, 0x46F34F7D, 0xCD42A113, -1169, 1 ), // 10^-352 (rounded up)
1454                 new BigNumber( 0x88DBA000, 0xB11B0857, 0xA686E3E8, -1275, 1 ), // 10^-384 (rounded up)
1455                 new BigNumber( 0x1A4EB007, 0x3FFC68A6, 0x871A4981, -1381, 1 ), // 10^-416 (rounded up)
1456                 new BigNumber( 0x84C663CF, 0xB6074244, 0xDB377599, -1488, 1 ), // 10^-448 (rounded up)
1457                 new BigNumber( 0x61EB52E2, 0x79007736, 0xB1D983B4, -1594, 1 ), // 10^-480
1458             };
1459             #endregion
1460 
1461 #if false
1462             /***************************************************************************
1463                 This is JScript code to compute the BigNumber values in the tables above.
1464             ***************************************************************************/
1465             var cbits = 100;
1466             var cbitsExact = 96;
1467             var arrPos = new Array;
1468             var arrNeg = new Array;
1469 
mainSystem.Xml.Xsl.XPathConvert.BigNumber1470             function main()
1471             {
1472                 Compute(0, 31);
1473                 Compute(5, 15);
1474 
1475                 print();
1476                 Dump()
1477             }
1478 
DumpSystem.Xml.Xsl.XPathConvert.BigNumber1479             function Dump()
1480             {
1481                 var i;
1482                 for (i = 0; i < arrPos.length; i++)
1483                     print(arrPos[i]);
1484                 print();
1485                 for (i = 0; i < arrNeg.length; i++)
1486                     print(arrNeg[i]);
1487             }
1488 
ComputeSystem.Xml.Xsl.XPathConvert.BigNumber1489             function Compute(p, n)
1490             {
1491                 var t;
1492                 var i;
1493                 var exp = 1;
1494                 var str = '101';
1495 
1496                 for (i = 0; i < p; i++)
1497                     {
1498                     exp *= 2;
1499                     str = Mul(str, str);
1500                     }
1501 
1502                 PrintNum(str, exp);
1503                 PrintInv(str, exp);
1504 
1505                 t = str;
1506                 for (i = 2; i <= n; i++)
1507                     {
1508                     t = Mul(str, t);
1509                     PrintNum(t, i * exp);
1510                     PrintInv(t, i * exp);
1511                     }
1512             }
1513 
MulSystem.Xml.Xsl.XPathConvert.BigNumber1514             function Mul(a, b)
1515             {
1516                 var c;
1517                 var len;
1518                 var i;
1519                 var res;
1520                 var add;
1521 
1522                 if (a.length > b.length)
1523                     {
1524                     c = a;
1525                     a = b;
1526                     b = c;
1527                     }
1528 
1529                 res = '';
1530                 add = b;
1531                 len = a.length;
1532                 for (i = 1; i <= len; i++)
1533                     {
1534                     if (a.charAt(len - i) == '1')
1535                         res = Add(res, add);
1536                     add += '0';
1537                     }
1538 
1539                 return res;
1540             }
1541 
AddSystem.Xml.Xsl.XPathConvert.BigNumber1542             function Add(a, b)
1543             {
1544                 var bit;
1545                 var i;
1546                 var c = 0;
1547                 var res = '';
1548                 var lena = a.length;
1549                 var lenb = b.length;
1550                 var lenm = Math.max(lena, lenb);
1551 
1552                 for (i = 1; i <= lenm; i++)
1553                     {
1554                     bit = (a.charAt(lena - i) == '1') + (b.charAt(lenb - i) == '1') + c;
1555                     if (bit & 1)
1556                         res = '1' + res;
1557                     else
1558                         res = '0' + res;
1559                     c = bit >> 1;
1560                     }
1561                 if (c)
1562                     res = '1' + res;
1563 
1564                 return res;
1565             }
1566 
PrintNumSystem.Xml.Xsl.XPathConvert.BigNumber1567             function PrintNum(a, n)
1568             {
1569                 arrPos[arrPos.length] = PrintHex(a, a.length, n);
1570             }
1571 
PrintHexSystem.Xml.Xsl.XPathConvert.BigNumber1572             function PrintHex(a, e, n)
1573             {
1574                 var arr;
1575                 var i;
1576                 var dig;
1577                 var fRoundUp = false;
1578                 var res = '';
1579 
1580                 dig = 0;
1581                 for (i = 0; i < cbitsExact; )
1582                     {
1583                     dig *= 2;
1584                     if (a.charAt(i) == '1')
1585                         dig++;
1586                     if (0 == (++i & 0x1F) && i < cbitsExact)
1587                         {
1588                         strT = dig.toString(16).toUpperCase();
1589                         res += ' 0x' + '00000000'.substring(strT.length) + strT;
1590                         dig = 0;
1591                         }
1592                     }
1593 
1594                 if (a.charAt(cbitsExact) == '1')
1595                     {
1596                     // Round up. Don't have to worry about overflowing.
1597                     fRoundUp = true;
1598                     dig++;
1599                     }
1600                 strT = dig.toString(16).toUpperCase();
1601                 res += ' 0x' + '00000000'.substring(strT.length) + strT;
1602 
1603                 arr = SR.split(' ');
1604                 res  = '\t{ ' + arr[3];
1605                 res += ', ' + arr[2];
1606                 res += ', ' + arr[1];
1607                 strT = '' + (e + n);
1608                 res += ', ' + '     '.substring(strT.length) + strT;
1609                 res += ', ' + (a.length <= cbitsExact ? 0 : 1);
1610                 strT = '' + n;
1611                 res += ' ), // 10^' + strT;
1612                 if (fRoundUp)
1613                     res +=  '     '.substring(strT.length) + '(rounded up)';
1614                 print(res);
1615 
1616                 return res;
1617             }
1618 
PrintInvSystem.Xml.Xsl.XPathConvert.BigNumber1619             function PrintInv(a, n)
1620             {
1621                 var exp;
1622                 var cdig;
1623                 var len = a.length;
1624                 var div = '1';
1625                 var res = '';
1626 
1627                 for (exp = 0; div.length <= len; exp++)
1628                     div += '0';
1629 
1630                 for (cdig = 0; cdig < cbits; cdig++)
1631                     {
1632                     if (div.length > len || div.length == len && div >= a)
1633                         {
1634                         res += '1';
1635                         div = Sub(div, a);
1636                         }
1637                     else
1638                         res += '0';
1639                     div += '0';
1640                     }
1641 
1642                 arrNeg[arrNeg.length] = PrintHex(res, -exp + 1, -n);
1643             }
1644 
SubSystem.Xml.Xsl.XPathConvert.BigNumber1645             function Sub(a, b)
1646             {
1647                 var ad, bd;
1648                 var i;
1649                 var dig;
1650                 var cch;
1651                 var lena = a.length;
1652                 var lenb = b.length;
1653                 var c = false;
1654                 var res = '';
1655 
1656                 for (i = 1; i <= lena; i++)
1657                     {
1658                     ad = (a.charAt(lena - i) == '1');
1659                     bd = (b.charAt(lenb - i) == '1');
1660                     if (ad == bd)
1661                         dig = c;
1662                     else
1663                         {
1664                         dig = !c;
1665                         c = bd;
1666                         }
1667                     if (dig)
1668                         {
1669                         cch = i;
1670                         res = '1' + res;
1671                         }
1672                     else
1673                         res = '0' + res;
1674                     }
1675                 return SR.substring(SR.length - cch, SR.length);
1676             }
1677 #endif
1678         }
1679 
1680         /**
1681         * Implementation of very large variable-precision non-negative integers.
1682         *
1683         * Hungarian: bi
1684         *
1685         */
1686         private class BigInteger : IComparable
1687         {
1688             // Make this big enough that we rarely have to reallocate.
1689             private const int InitCapacity = 30;
1690 
1691             private int _capacity;
1692             private int _length;
1693             private uint[] _digits;
1694 
BigInteger()1695             public BigInteger()
1696             {
1697                 _capacity = InitCapacity;
1698                 _length = 0;
1699                 _digits = new uint[InitCapacity];
1700                 AssertValid();
1701             }
1702 
1703             public int Length
1704             {
1705                 get { return _length; }
1706             }
1707 
1708             public uint this[int idx]
1709             {
1710                 get
1711                 {
1712                     AssertValid();
1713                     Debug.Assert(0 <= idx && idx < _length);
1714                     return _digits[idx];
1715                 }
1716             }
1717 
1718             [Conditional("DEBUG")]
AssertValidNoVal()1719             private void AssertValidNoVal()
1720             {
1721                 Debug.Assert(_capacity >= InitCapacity);
1722                 Debug.Assert(_length >= 0 && _length <= _capacity);
1723             }
1724 
1725             [Conditional("DEBUG")]
AssertValid()1726             private void AssertValid()
1727             {
1728                 AssertValidNoVal();
1729                 Debug.Assert(0 == _length || 0 != _digits[_length - 1]);
1730             }
1731 
Ensure(int cu)1732             private void Ensure(int cu)
1733             {
1734                 AssertValidNoVal();
1735 
1736                 if (cu <= _capacity)
1737                 {
1738                     return;
1739                 }
1740 
1741                 cu += cu;
1742                 uint[] newDigits = new uint[cu];
1743                 _digits.CopyTo(newDigits, 0);
1744                 _digits = newDigits;
1745                 _capacity = cu;
1746 
1747                 AssertValidNoVal();
1748             }
1749 
1750             /*  ----------------------------------------------------------------------------
1751                 InitFromRgu()
1752 
1753                 Initialize this big integer from an array of uint values.
1754             */
InitFromRgu(uint[] rgu, int cu)1755             public void InitFromRgu(uint[] rgu, int cu)
1756             {
1757                 AssertValid();
1758                 Debug.Assert(cu >= 0);
1759 
1760                 Ensure(cu);
1761                 _length = cu;
1762                 // REVIEW: if (cu > 0) memcpy(digits, prgu, cu * sizeof(uint));
1763                 for (int i = 0; i < cu; i++)
1764                 {
1765                     _digits[i] = rgu[i];
1766                 }
1767                 AssertValid();
1768             }
1769 
1770             /*  ----------------------------------------------------------------------------
1771                 InitFromRgu()
1772 
1773                 Initialize this big integer from 0, 1, or 2 uint values.
1774             */
InitFromDigits(uint u0, uint u1, int cu)1775             public void InitFromDigits(uint u0, uint u1, int cu)
1776             {
1777                 AssertValid();
1778                 Debug.Assert(2 <= _capacity);
1779 
1780                 _length = cu;
1781                 _digits[0] = u0;
1782                 _digits[1] = u1;
1783                 AssertValid();
1784             }
1785 
1786             /*  ----------------------------------------------------------------------------
1787                 InitFromBigint()
1788 
1789                 Initialize this big integer from another BigInteger object.
1790             */
InitFromBigint(BigInteger biSrc)1791             public void InitFromBigint(BigInteger biSrc)
1792             {
1793                 AssertValid();
1794                 biSrc.AssertValid();
1795                 Debug.Assert((object)this != (object)biSrc);
1796 
1797                 InitFromRgu(biSrc._digits, biSrc._length);
1798             }
1799 
1800 #if !NOPARSE || DEBUG
1801             /*  ----------------------------------------------------------------------------
1802                 InitFromFloatingDecimal()
1803 
1804                 Initialize this big integer from a FloatingDecimal object.
1805             */
InitFromFloatingDecimal(FloatingDecimal dec)1806             public void InitFromFloatingDecimal(FloatingDecimal dec)
1807             {
1808                 AssertValid();
1809                 Debug.Assert(dec.MantissaSize >= 0);
1810 
1811                 uint uAdd, uMul;
1812                 int cu = (dec.MantissaSize + 8) / 9;
1813                 int mantissaSize = dec.MantissaSize;
1814 
1815                 Ensure(cu);
1816                 _length = 0;
1817 
1818                 uAdd = 0;
1819                 uMul = 1;
1820                 for (int ib = 0; ib < mantissaSize; ib++)
1821                 {
1822                     Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
1823                     if (1000000000 == uMul)
1824                     {
1825                         MulAdd(uMul, uAdd);
1826                         uMul = 1;
1827                         uAdd = 0;
1828                     }
1829                     uMul *= 10;
1830                     uAdd = uAdd * 10 + dec[ib];
1831                 }
1832                 Debug.Assert(1 < uMul);
1833                 MulAdd(uMul, uAdd);
1834 
1835                 AssertValid();
1836             }
1837 #endif
1838 
MulAdd(uint uMul, uint uAdd)1839             public void MulAdd(uint uMul, uint uAdd)
1840             {
1841                 AssertValid();
1842                 Debug.Assert(0 != uMul);
1843 
1844                 for (int i = 0; i < _length; i++)
1845                 {
1846                     uint d, uT;
1847                     d = MulU(_digits[i], uMul, out uT);
1848                     if (0 != uAdd)
1849                     {
1850                         uT += AddU(ref d, uAdd);
1851                     }
1852                     _digits[i] = d;
1853                     uAdd = uT;
1854                 }
1855                 if (0 != uAdd)
1856                 {
1857                     Ensure(_length + 1);
1858                     _digits[_length++] = uAdd;
1859                 }
1860                 AssertValid();
1861             }
1862 
MulPow5(int c5)1863             public void MulPow5(int c5)
1864             {
1865                 AssertValid();
1866                 Debug.Assert(c5 >= 0);
1867 
1868                 const uint C5to13 = 1220703125;
1869                 int cu = (c5 + 12) / 13;
1870 
1871                 if (0 == _length || 0 == c5)
1872                 {
1873                     return;
1874                 }
1875 
1876                 Ensure(_length + cu);
1877 
1878                 for (; c5 >= 13; c5 -= 13)
1879                 {
1880                     MulAdd(C5to13, 0);
1881                 }
1882 
1883                 if (c5 > 0)
1884                 {
1885                     uint uT;
1886                     for (uT = 5; --c5 > 0;)
1887                     {
1888                         uT *= 5;
1889                     }
1890                     MulAdd(uT, 0);
1891                 }
1892                 AssertValid();
1893             }
1894 
ShiftLeft(int cbit)1895             public void ShiftLeft(int cbit)
1896             {
1897                 AssertValid();
1898                 Debug.Assert(cbit >= 0);
1899 
1900                 int idx, cu;
1901                 uint uExtra;
1902 
1903                 if (0 == cbit || 0 == _length)
1904                 {
1905                     return;
1906                 }
1907 
1908                 cu = cbit >> 5;
1909                 cbit &= 0x001F;
1910 
1911                 if (cbit > 0)
1912                 {
1913                     idx = _length - 1;
1914                     uExtra = _digits[idx] >> (32 - cbit);
1915 
1916                     for (; ; idx--)
1917                     {
1918                         _digits[idx] <<= cbit;
1919                         if (0 == idx)
1920                         {
1921                             break;
1922                         }
1923                         _digits[idx] |= _digits[idx - 1] >> (32 - cbit);
1924                     }
1925                 }
1926                 else
1927                 {
1928                     uExtra = 0;
1929                 }
1930 
1931                 if (cu > 0 || 0 != uExtra)
1932                 {
1933                     // Make sure there's enough room.
1934                     idx = _length + (0 != uExtra ? 1 : 0) + cu;
1935                     Ensure(idx);
1936 
1937                     if (cu > 0)
1938                     {
1939                         // Shift the digits.
1940                         // REVIEW: memmove(digits + cu, digits, length * sizeof(uint));
1941                         for (int i = _length; 0 != i--;)
1942                         {
1943                             _digits[cu + i] = _digits[i];
1944                         }
1945                         // REVIEW: memset(digits, 0, cu * sizeof(uint));
1946                         for (int i = 0; i < cu; i++)
1947                         {
1948                             _digits[i] = 0;
1949                         }
1950                         _length += cu;
1951                     }
1952 
1953                     // Throw on the extra one.
1954                     if (0 != uExtra)
1955                     {
1956                         _digits[_length++] = uExtra;
1957                     }
1958                 }
1959                 AssertValid();
1960             }
1961 
ShiftUsRight(int cu)1962             public void ShiftUsRight(int cu)
1963             {
1964                 AssertValid();
1965                 Debug.Assert(cu >= 0);
1966 
1967                 if (cu >= _length)
1968                 {
1969                     _length = 0;
1970                 }
1971                 else if (cu > 0)
1972                 {
1973                     // REVIEW: memmove(digits, digits + cu, (length - cu) * sizeof(uint));
1974                     for (int i = 0; i < _length - cu; i++)
1975                     {
1976                         _digits[i] = _digits[cu + i];
1977                     }
1978                     _length -= cu;
1979                 }
1980                 AssertValid();
1981             }
1982 
ShiftRight(int cbit)1983             public void ShiftRight(int cbit)
1984             {
1985                 AssertValid();
1986                 Debug.Assert(cbit >= 0);
1987 
1988                 int idx;
1989                 int cu = cbit >> 5;
1990                 cbit &= 0x001F;
1991 
1992                 if (cu > 0)
1993                 {
1994                     ShiftUsRight(cu);
1995                 }
1996 
1997                 if (0 == cbit || 0 == _length)
1998                 {
1999                     AssertValid();
2000                     return;
2001                 }
2002 
2003                 for (idx = 0; ;)
2004                 {
2005                     _digits[idx] >>= cbit;
2006                     if (++idx >= _length)
2007                     {
2008                         // Last one.
2009                         if (0 == _digits[idx - 1])
2010                         {
2011                             _length--;
2012                         }
2013                         break;
2014                     }
2015                     _digits[idx - 1] |= _digits[idx] << (32 - cbit);
2016                 }
2017                 AssertValid();
2018             }
2019 
CompareTo(object obj)2020             public int CompareTo(object obj)
2021             {
2022                 BigInteger bi = (BigInteger)obj;
2023                 AssertValid();
2024                 bi.AssertValid();
2025 
2026                 if (_length > bi._length)
2027                 {
2028                     return 1;
2029                 }
2030                 else if (_length < bi._length)
2031                 {
2032                     return -1;
2033                 }
2034                 else if (0 == _length)
2035                 {
2036                     return 0;
2037                 }
2038 
2039                 int idx;
2040 
2041                 for (idx = _length - 1; _digits[idx] == bi._digits[idx]; idx--)
2042                 {
2043                     if (0 == idx)
2044                     {
2045                         return 0;
2046                     }
2047                 }
2048                 Debug.Assert(idx >= 0 && idx < _length);
2049                 Debug.Assert(_digits[idx] != bi._digits[idx]);
2050 
2051                 return (_digits[idx] > bi._digits[idx]) ? 1 : -1;
2052             }
2053 
Add(BigInteger bi)2054             public void Add(BigInteger bi)
2055             {
2056                 AssertValid();
2057                 bi.AssertValid();
2058                 Debug.Assert((object)this != (object)bi);
2059 
2060                 int idx, cuMax, cuMin;
2061                 uint wCarry;
2062 
2063                 if ((cuMax = _length) < (cuMin = bi._length))
2064                 {
2065                     cuMax = bi._length;
2066                     cuMin = _length;
2067                     Ensure(cuMax + 1);
2068                 }
2069 
2070                 wCarry = 0;
2071                 for (idx = 0; idx < cuMin; idx++)
2072                 {
2073                     if (0 != wCarry)
2074                     {
2075                         wCarry = AddU(ref _digits[idx], wCarry);
2076                     }
2077                     wCarry += AddU(ref _digits[idx], bi._digits[idx]);
2078                 }
2079 
2080                 if (_length < bi._length)
2081                 {
2082                     for (; idx < cuMax; idx++)
2083                     {
2084                         _digits[idx] = bi._digits[idx];
2085                         if (0 != wCarry)
2086                         {
2087                             wCarry = AddU(ref _digits[idx], wCarry);
2088                         }
2089                     }
2090                     _length = cuMax;
2091                 }
2092                 else
2093                 {
2094                     for (; 0 != wCarry && idx < cuMax; idx++)
2095                     {
2096                         wCarry = AddU(ref _digits[idx], wCarry);
2097                     }
2098                 }
2099 
2100                 if (0 != wCarry)
2101                 {
2102                     Ensure(_length + 1);
2103                     _digits[_length++] = wCarry;
2104                 }
2105                 AssertValid();
2106             }
2107 
Subtract(BigInteger bi)2108             public void Subtract(BigInteger bi)
2109             {
2110                 AssertValid();
2111                 bi.AssertValid();
2112                 Debug.Assert((object)this != (object)bi);
2113 
2114                 int idx;
2115                 uint wCarry, uT;
2116 
2117                 if (_length < bi._length)
2118                 {
2119                     goto LNegative;
2120                 }
2121 
2122                 wCarry = 1;
2123                 for (idx = 0; idx < bi._length; idx++)
2124                 {
2125                     Debug.Assert(0 == wCarry || 1 == wCarry);
2126                     uT = bi._digits[idx];
2127 
2128                     // NOTE: We should really do:
2129                     //    wCarry = AddU(ref digits[idx], wCarry);
2130                     //    wCarry += AddU(ref digits[idx], ~uT);
2131                     // The only case where this is different than
2132                     //    wCarry = AddU(ref digits[idx], ~uT + wCarry);
2133                     // is when 0 == uT and 1 == wCarry, in which case we don't
2134                     // need to add anything and wCarry should still be 1, so we can
2135                     // just skip the operations.
2136 
2137                     if (0 != uT || 0 == wCarry)
2138                     {
2139                         wCarry = AddU(ref _digits[idx], ~uT + wCarry);
2140                     }
2141                 }
2142                 while (0 == wCarry && idx < _length)
2143                 {
2144                     wCarry = AddU(ref _digits[idx], 0xFFFFFFFF);
2145                 }
2146 
2147                 if (0 != wCarry)
2148                 {
2149                     if (idx == _length)
2150                     {
2151                         // Trim off zeros.
2152                         while (--idx >= 0 && 0 == _digits[idx])
2153                         {
2154                         }
2155                         _length = idx + 1;
2156                     }
2157                     AssertValid();
2158                     return;
2159                 }
2160 
2161             LNegative:
2162                 // bi was bigger than this.
2163                 Debug.Assert(false, "Who's subtracting to negative?");
2164                 _length = 0;
2165                 AssertValid();
2166             }
2167 
DivRem(BigInteger bi)2168             public uint DivRem(BigInteger bi)
2169             {
2170                 AssertValid();
2171                 bi.AssertValid();
2172                 Debug.Assert((object)this != (object)bi);
2173 
2174                 int idx, cu;
2175                 uint uQuo, wCarry;
2176                 int wT;
2177                 uint uT, uHi, uLo;
2178 
2179                 cu = bi._length;
2180                 Debug.Assert(_length <= cu);
2181                 if (_length < cu)
2182                 {
2183                     return 0;
2184                 }
2185 
2186                 // Get a lower bound on the quotient.
2187                 uQuo = (uint)(_digits[cu - 1] / (bi._digits[cu - 1] + 1));
2188                 Debug.Assert(uQuo >= 0 && uQuo <= 9);
2189 
2190                 // Handle 0 and 1 as special cases.
2191                 switch (uQuo)
2192                 {
2193                     case 0:
2194                         break;
2195                     case 1:
2196                         Subtract(bi);
2197                         break;
2198                     default:
2199                         uHi = 0;
2200                         wCarry = 1;
2201                         for (idx = 0; idx < cu; idx++)
2202                         {
2203                             Debug.Assert(0 == wCarry || 1 == wCarry);
2204 
2205                             // Compute the product.
2206                             uLo = MulU(uQuo, bi._digits[idx], out uT);
2207                             uHi = uT + AddU(ref uLo, uHi);
2208 
2209                             // Subtract the product. See note in BigInteger.Subtract.
2210                             if (0 != uLo || 0 == wCarry)
2211                             {
2212                                 wCarry = AddU(ref _digits[idx], ~uLo + wCarry);
2213                             }
2214                         }
2215                         Debug.Assert(1 == wCarry);
2216                         Debug.Assert(idx == cu);
2217 
2218                         // Trim off zeros.
2219                         while (--idx >= 0 && 0 == _digits[idx])
2220                         {
2221                         }
2222                         _length = idx + 1;
2223                         break;
2224                 }
2225 
2226                 if (uQuo < 9 && (wT = CompareTo(bi)) >= 0)
2227                 {
2228                     // Quotient was off too small (by one).
2229                     uQuo++;
2230                     if (0 == wT)
2231                     {
2232                         _length = 0;
2233                     }
2234                     else
2235                     {
2236                         Subtract(bi);
2237                     }
2238                 }
2239                 Debug.Assert(CompareTo(bi) < 0);
2240 
2241                 return uQuo;
2242             }
2243 
2244 #if NEVER
operator double(BigInteger bi)2245             public static explicit operator double(BigInteger bi) {
2246                 uint uHi, uLo;
2247                 uint u1, u2, u3;
2248                 int idx;
2249                 int cbit;
2250                 uint dblHi, dblLo;
2251 
2252                 switch (bi.length) {
2253                 case 0:
2254                     return 0;
2255                 case 1:
2256                     return bi.digits[0];
2257                 case 2:
2258                     return (ulong)bi.digits[1] << 32 | bi.digits[0];
2259                 }
2260 
2261                 Debug.Assert(3 <= bi.length);
2262                 if (bi.length > 32) {
2263                     // Result is infinite.
2264                     return BitConverter.Int64BitsToDouble(0x7FF00000L << 32);
2265                 }
2266 
2267                 u1 = bi.digits[bi.length - 1];
2268                 u2 = bi.digits[bi.length - 2];
2269                 u3 = bi.digits[bi.length - 3];
2270                 Debug.Assert(0 != u1);
2271                 cbit = 31 - CbitZeroLeft(u1);
2272 
2273                 if (0 == cbit) {
2274                     uHi = u2;
2275                     uLo = u3;
2276                 } else {
2277                     uHi = (u1 << (32 - cbit)) | (u2 >> cbit);
2278                     // Or 1 if there are any remaining nonzero bits in u3, so we take
2279                     // them into account when rounding.
2280                     uLo = (u2 << (32 - cbit)) | (u3 >> cbit) | NotZero(u3 << (32 - cbit));
2281                 }
2282 
2283                 // Set the mantissa bits.
2284                 dblHi = uHi >> 12;
2285                 dblLo = (uHi << 20) | (uLo >> 12);
2286 
2287                 // Set the exponent field.
2288                 dblHi |= (uint)(0x03FF + cbit + (bi.length - 1) * 0x0020) << 20;
2289 
2290                 // Do IEEE rounding.
2291                 if (0 != (uLo & 0x0800)) {
2292                     if (0 != (uLo & 0x07FF) || 0 != (dblLo & 1)) {
2293                         if (0 == ++dblLo) {
2294                             ++dblHi;
2295                         }
2296                     } else {
2297                         // If there are any non-zero bits in digits from 0 to length - 4,
2298                         // round up.
2299                         for (idx = bi.length - 4; idx >= 0; idx--) {
2300                             if (0 != bi.digits[idx]) {
2301                                 if (0 == ++dblLo) {
2302                                     ++dblHi;
2303                                 }
2304                                 break;
2305                             }
2306                         }
2307                     }
2308                 }
2309                 return BitConverter.Int64BitsToDouble((long)dblHi << 32 | dblLo);
2310             }
2311 #endif
2312         };
2313 
2314         /**
2315         * Floating point number represented in base-10.
2316         */
2317         private class FloatingDecimal
2318         {
2319             public const int MaxDigits = 50;
2320             private const int MaxExp10 = 310;  // Upper bound on base 10 exponent
2321             private const int MinExp10 = -325;  // Lower bound on base 10 exponent
2322 
2323             private int _exponent;             // Base-10 scaling factor (0 means decimal point immediately precedes first digit)
2324             private int _sign;                 // Sign is -1 or 1, depending on sign of number
2325             private int _mantissaSize;         // Size of mantissa
2326             private byte[] _mantissa = new byte[MaxDigits];    // Array of base-10 digits
2327 
2328             public int Exponent { get { return _exponent; } set { _exponent = value; } }
2329             public int Sign { get { return _sign; } set { _sign = value; } }
2330             public byte[] Mantissa { get { return _mantissa; } }
2331 
2332             public int MantissaSize
2333             {
2334                 get
2335                 {
2336                     return _mantissaSize;
2337                 }
2338                 set
2339                 {
2340                     Debug.Assert(value <= MaxDigits);
2341                     _mantissaSize = value;
2342                 }
2343             }
2344 
2345             public byte this[int ib]
2346             {
2347                 get
2348                 {
2349                     Debug.Assert(0 <= ib && ib < _mantissaSize);
2350                     return _mantissa[ib];
2351                 }
2352             }
2353 
FloatingDecimal()2354             public FloatingDecimal()
2355             {
2356                 _exponent = 0;
2357                 _sign = 1;
2358                 _mantissaSize = 0;
2359             }
2360 
FloatingDecimal(double dbl)2361             public FloatingDecimal(double dbl)
2362             {
2363                 InitFromDouble(dbl);
2364 
2365 #if DEBUG
2366                 if (0 != _mantissaSize)
2367                 {
2368                     Debug.Assert(dbl == (double)this);
2369 
2370                     FloatingDecimal decAfter = new FloatingDecimal();
2371                     decAfter.InitFromDouble(Succ(dbl));
2372                     // Assert(memcmp(this, &decAfter, sizeof(*this) - MaxDigits + mantissaSize));
2373                     Debug.Assert(!this.Equals(decAfter));
2374 
2375                     FloatingDecimal decBefore = new FloatingDecimal();
2376                     decBefore.InitFromDouble(Pred(dbl));
2377                     // Assert(memcmp(this, &decBefore, sizeof(*this) - MaxDigits + mantissaSize));
2378                     Debug.Assert(!this.Equals(decBefore));
2379                 }
2380 #endif
2381             }
2382 
2383 #if DEBUG
Equals(FloatingDecimal other)2384             private bool Equals(FloatingDecimal other)
2385             {
2386                 if (_exponent != other._exponent || _sign != other._sign || _mantissaSize != other._mantissaSize)
2387                 {
2388                     return false;
2389                 }
2390                 for (int idx = 0; idx < _mantissaSize; idx++)
2391                 {
2392                     if (_mantissa[idx] != other._mantissa[idx])
2393                     {
2394                         return false;
2395                     }
2396                 }
2397                 return true;
2398             }
2399 #endif
2400 
2401 #if NEVER
2402             /*  ----------------------------------------------------------------------------
2403                 RoundTo()
2404 
2405                 Rounds off the BCD representation of a number to a specified number of digits.
2406                 This may result in the exponent being incremented (e.g. if digits were 999).
2407             */
RoundTo(int sizeMantissa)2408             public void RoundTo(int sizeMantissa) {
2409                 if (sizeMantissa >= mantissaSize) {
2410                     // No change required
2411                     return;
2412                 }
2413 
2414                 if (sizeMantissa >= 0) {
2415                     bool fRoundUp = mantissa[sizeMantissa] >= 5;
2416                     mantissaSize = sizeMantissa;
2417 
2418                     // Round up if necessary and trim trailing zeros
2419                     for (int idx = mantissaSize - 1; idx >= 0; idx--) {
2420                         if (fRoundUp) {
2421                             if (++(mantissa[idx]) <= 9) {
2422                                 // Trailing digit is non-zero, so break
2423                                 fRoundUp = false;
2424                                 break;
2425                             }
2426                         } else if (mantissa[idx] > 0) {
2427                             // Trailing digit is non-zero, so break
2428                             break;
2429                         }
2430 
2431                         // Trim trailing zeros
2432                         mantissaSize--;
2433                     }
2434 
2435                     if (fRoundUp) {
2436                         // Number consisted only of 9's
2437                         Debug.Assert(0 == mantissaSize);
2438                         mantissa[0] = 1;
2439                         mantissaSize = 1;
2440                         exponent++;
2441                     }
2442                 } else {
2443                     // Number was rounded past any significant digits (e.g. 0.001 rounded to 1 fractional place), so round to 0.0
2444                     mantissaSize = 0;
2445                 }
2446 
2447                 if (0 == mantissaSize) {
2448                     // 0.0
2449                     sign = 1;
2450                     exponent = 0;
2451                 }
2452             }
2453 #endif
2454 
2455 #if !NOPARSE || DEBUG
2456             /*  ----------------------------------------------------------------------------
2457                 explicit operator double()
2458 
2459                 Returns the double value of this floating decimal.
2460             */
operator double(FloatingDecimal dec)2461             public static explicit operator double (FloatingDecimal dec)
2462             {
2463                 BigNumber num, numHi, numLo;
2464                 uint ul;
2465                 int scale;
2466                 double dbl, dblLowPrec, dblLo;
2467                 int mantissaSize = dec._mantissaSize;
2468 
2469                 // Verify that there are no leading or trailing zeros in the mantissa
2470                 Debug.Assert(0 != mantissaSize && 0 != dec[0] && 0 != dec[mantissaSize - 1]);
2471 
2472                 // See if we can just use IEEE double arithmetic.
2473                 scale = dec._exponent - mantissaSize;
2474                 if (mantissaSize <= 15 && scale >= -22 && dec._exponent <= 37)
2475                 {
2476                     // These calculations are all exact since mantissaSize <= 15.
2477                     if (mantissaSize <= 9)
2478                     {
2479                         // Can use the ALU to perform fast integer arithmetic
2480                         ul = 0;
2481                         for (int ib = 0; ib < mantissaSize; ib++)
2482                         {
2483                             Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
2484                             ul = ul * 10 + dec[ib];
2485                         }
2486                         dbl = ul;
2487                     }
2488                     else
2489                     {
2490                         // Use floating point arithmetic
2491                         dbl = 0.0;
2492                         for (int ib = 0; ib < mantissaSize; ib++)
2493                         {
2494                             Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
2495                             dbl = dbl * 10.0 + dec[ib];
2496                         }
2497                     }
2498 
2499                     // This is the only (potential) rounding operation and we assume
2500                     // the compiler does the correct IEEE rounding.
2501                     if (scale > 0)
2502                     {
2503                         // Need to scale upwards by powers of 10
2504                         if (scale > 22)
2505                         {
2506                             // This one is exact. We're using the fact that mantissaSize < 15
2507                             // to handle exponents bigger than 22.
2508                             dbl *= C10toN[scale - 22];
2509                             dbl *= C10toN[22];
2510                         }
2511                         else
2512                         {
2513                             dbl *= C10toN[scale];
2514                         }
2515                     }
2516                     else if (scale < 0)
2517                     {
2518                         // Scale number by negative power of 10
2519                         dbl /= C10toN[-scale];
2520                     }
2521 
2522 #if DEBUG
2523                     // In the debug version, execute the high precision code also and
2524                     // verify that the results are the same.
2525                     dblLowPrec = dbl;
2526                 }
2527                 else
2528                 {
2529                     dblLowPrec = Double.NaN;
2530                 }
2531 #else
2532                     goto LDone;
2533                 }
2534 #endif
2535 
2536                 if (dec._exponent >= MaxExp10)
2537                 {
2538                     // Overflow to infinity.
2539                     dbl = Double.PositiveInfinity;
2540                     goto LDone;
2541                 }
2542 
2543                 if (dec._exponent <= MinExp10)
2544                 {
2545                     // Underflow to 0.
2546                     dbl = 0.0;
2547                     goto LDone;
2548                 }
2549 
2550                 // Convert to a big number.
2551                 num = new BigNumber(dec);
2552 
2553                 // If there is no error in the big number, just convert it to a double.
2554                 if (0 == num.Error)
2555                 {
2556                     dbl = (double)num;
2557 #if DEBUG
2558                     dblLo = dec.AdjustDbl(dbl);
2559                     Debug.Assert(dbl == dblLo);
2560 #endif
2561                     goto LDone;
2562                 }
2563 
2564                 // The big number has error in it, so see if the error matters.
2565                 // Get the upper bound and lower bound. If they convert to the same
2566                 // double we're done.
2567                 numHi = num;
2568                 numHi.MakeUpperBound();
2569                 numLo = num;
2570                 numLo.MakeLowerBound();
2571 
2572                 dbl = (double)numHi;
2573                 dblLo = (double)numLo;
2574                 if (dbl == dblLo)
2575                 {
2576 #if DEBUG
2577                     Debug.Assert(dbl == (double)num);
2578                     dblLo = dec.AdjustDbl(dbl);
2579                     Debug.Assert(dbl == dblLo || Double.IsNaN(dblLo));
2580 #endif
2581                     goto LDone;
2582                 }
2583 
2584                 // Need to use big integer arithmetic. There's too much error in
2585                 // our result and it's close to a boundary value. This is rare,
2586                 // but does happen. Eg,
2587                 // x = 1.2345678901234568347913049445e+200;
2588                 //
2589                 dbl = dec.AdjustDbl((double)num);
2590 
2591             LDone:
2592                 // This assert was removed because it would fire on VERY rare occasions. Not
2593                 // repro on all machines and very hard to repro even on machines that could repro it.
2594                 // The numbers (dblLowPrec and dbl) were different in their two least sig bits only
2595                 // which is _probably_ within expected errror. I did not take the time to fully
2596                 // investigate whether this really does meet the ECMA spec...
2597                 //
2598                 Debug.Assert(Double.IsNaN(dblLowPrec) || dblLowPrec == dbl);
2599                 return dec._sign < 0 ? -dbl : dbl;
2600             }
2601 
2602             /*  ----------------------------------------------------------------------------
2603                 AdjustDbl()
2604 
2605                 The double contains a binary value, M * 2^n, which is off by at most 1
2606                 in the least significant bit; this class' members represent a decimal
2607                 value, D * 10^e.
2608 
2609                 The general scheme is to find an integer N (the smaller the better) such
2610                 that N * M * 2^n and N * D * 10^e are both integers. We then compare
2611                 N * M * 2^n to N * D * 10^e (at full precision). If the binary value is
2612                 greater, we adjust it to be exactly half way to the next value that can
2613                 come from a double. We then compare again to decided whether to bump the
2614                 double up to the next value. Similary if the binary value is smaller,
2615                 we adjust it to be exactly half way to the previous representable value
2616                 and recompare.
2617             */
AdjustDbl(double dbl)2618             private double AdjustDbl(double dbl)
2619             {
2620                 BigInteger biDec = new BigInteger();
2621                 BigInteger biDbl = new BigInteger();
2622                 int c2Dec, c2Dbl;
2623                 int c5Dec, c5Dbl;
2624                 uint wAddHi, uT;
2625                 int wT, iT;
2626                 int lwExp, wExp2;
2627                 //uint *rgu = stackalloc uint[2];
2628                 uint rgu0, rgu1;
2629                 int cu;
2630 
2631                 biDec.InitFromFloatingDecimal(this);
2632                 lwExp = _exponent - _mantissaSize;
2633 
2634                 // lwExp is a base 10 exponent.
2635                 if (lwExp >= 0)
2636                 {
2637                     c5Dec = c2Dec = lwExp;
2638                     c5Dbl = c2Dbl = 0;
2639                 }
2640                 else
2641                 {
2642                     c5Dec = c2Dec = 0;
2643                     c5Dbl = c2Dbl = -lwExp;
2644                 }
2645 
2646                 rgu1 = DblHi(dbl);
2647                 rgu0 = DblLo(dbl);
2648                 wExp2 = (int)(rgu1 >> 20) & 0x07FF;
2649                 rgu1 &= 0x000FFFFF;
2650                 wAddHi = 1;
2651                 if (0 != wExp2)
2652                 {
2653                     // Normal, so add implicit bit.
2654                     if (0 == rgu1 && 0 == rgu0 && 1 != wExp2)
2655                     {
2656                         // Power of 2 (and not adjacent to the first denormal), so the
2657                         // adjacent low value is closer than the high value.
2658                         wAddHi = 2;
2659                         rgu1 = 0x00200000;
2660                         wExp2--;
2661                     }
2662                     else
2663                     {
2664                         rgu1 |= 0x00100000;
2665                     }
2666                     wExp2 -= 1076;
2667                 }
2668                 else
2669                 {
2670                     wExp2 = -1075;
2671                 }
2672 
2673                 // Shift left by 1 bit : the adjustment values need the next lower bit.
2674                 rgu1 = (rgu1 << 1) | (rgu0 >> 31);
2675                 rgu0 <<= 1;
2676 
2677                 // We must determine how many words of significant digits this requiSR.
2678                 if (0 == rgu0 && 0 == rgu1)
2679                 {
2680                     cu = 0;
2681                 }
2682                 else if (0 == rgu1)
2683                 {
2684                     cu = 1;
2685                 }
2686                 else
2687                 {
2688                     cu = 2;
2689                 }
2690 
2691                 biDbl.InitFromDigits(rgu0, rgu1, cu);
2692 
2693                 if (wExp2 >= 0)
2694                 {
2695                     c2Dbl += wExp2;
2696                 }
2697                 else
2698                 {
2699                     c2Dec += -wExp2;
2700                 }
2701 
2702                 // Eliminate common powers of 2.
2703                 if (c2Dbl > c2Dec)
2704                 {
2705                     c2Dbl -= c2Dec;
2706                     c2Dec = 0;
2707 
2708                     // See if biDec has some powers of 2 that we can get rid of.
2709                     for (iT = 0; c2Dbl >= 32 && 0 == biDec[iT]; iT++)
2710                     {
2711                         c2Dbl -= 32;
2712                     }
2713                     if (iT > 0)
2714                     {
2715                         biDec.ShiftUsRight(iT);
2716                     }
2717                     Debug.Assert(c2Dbl < 32 || 0 != biDec[0]);
2718                     uT = biDec[0];
2719                     for (iT = 0; iT < c2Dbl && 0 == (uT & (1L << iT)); iT++)
2720                     {
2721                     }
2722                     if (iT > 0)
2723                     {
2724                         c2Dbl -= iT;
2725                         biDec.ShiftRight(iT);
2726                     }
2727                 }
2728                 else
2729                 {
2730                     c2Dec -= c2Dbl;
2731                     c2Dbl = 0;
2732                 }
2733 
2734                 // There are no common powers of 2 or common powers of 5.
2735                 Debug.Assert(0 == c2Dbl || 0 == c2Dec);
2736                 Debug.Assert(0 == c5Dbl || 0 == c5Dec);
2737 
2738                 // Fold in the powers of 5.
2739                 if (c5Dbl > 0)
2740                 {
2741                     biDbl.MulPow5(c5Dbl);
2742                 }
2743                 else if (c5Dec > 0)
2744                 {
2745                     biDec.MulPow5(c5Dec);
2746                 }
2747 
2748                 // Fold in the powers of 2.
2749                 if (c2Dbl > 0)
2750                 {
2751                     biDbl.ShiftLeft(c2Dbl);
2752                 }
2753                 else if (c2Dec > 0)
2754                 {
2755                     biDec.ShiftLeft(c2Dec);
2756                 }
2757 
2758                 // Now determine whether biDbl is above or below biDec.
2759                 wT = biDbl.CompareTo(biDec);
2760 
2761                 if (0 == wT)
2762                 {
2763                     return dbl;
2764                 }
2765                 else if (wT > 0)
2766                 {
2767                     // biDbl is greater. Recompute with the dbl minus half the distance
2768                     // to the next smaller double.
2769                     if (0 == AddU(ref rgu0, 0xFFFFFFFF))
2770                     {
2771                         AddU(ref rgu1, 0xFFFFFFFF);
2772                     }
2773                     biDbl.InitFromDigits(rgu0, rgu1, 1 + (0 != rgu1 ? 1 : 0));
2774                     if (c5Dbl > 0)
2775                     {
2776                         biDbl.MulPow5(c5Dbl);
2777                     }
2778                     if (c2Dbl > 0)
2779                     {
2780                         biDbl.ShiftLeft(c2Dbl);
2781                     }
2782 
2783                     wT = biDbl.CompareTo(biDec);
2784                     if (wT > 0 || 0 == wT && 0 != (DblLo(dbl) & 1))
2785                     {
2786                         // Return the next lower value.
2787                         dbl = BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(dbl) - 1);
2788                     }
2789                 }
2790                 else
2791                 {
2792                     // biDbl is smaller. Recompute with the dbl plus half the distance
2793                     // to the next larger double.
2794                     if (0 != AddU(ref rgu0, wAddHi))
2795                     {
2796                         AddU(ref rgu1, 1);
2797                     }
2798                     biDbl.InitFromDigits(rgu0, rgu1, 1 + (0 != rgu1 ? 1 : 0));
2799                     if (c5Dbl > 0)
2800                     {
2801                         biDbl.MulPow5(c5Dbl);
2802                     }
2803                     if (c2Dbl > 0)
2804                     {
2805                         biDbl.ShiftLeft(c2Dbl);
2806                     }
2807 
2808                     wT = biDbl.CompareTo(biDec);
2809                     if (wT < 0 || 0 == wT && 0 != (DblLo(dbl) & 1))
2810                     {
2811                         // Return the next higher value.
2812                         dbl = BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(dbl) + 1);
2813                     }
2814                 }
2815                 return dbl;
2816             }
2817 #endif
2818 
InitFromDouble(double dbl)2819             private void InitFromDouble(double dbl)
2820             {
2821                 if (0.0 == dbl || IsSpecial(dbl))
2822                 {
2823                     _exponent = 0;
2824                     _sign = 1;
2825                     _mantissaSize = 0;
2826                 }
2827                 else
2828                 {
2829                     // Handle the sign.
2830                     if (dbl < 0)
2831                     {
2832                         _sign = -1;
2833                         dbl = -dbl;
2834                     }
2835                     else
2836                     {
2837                         _sign = 1;
2838                     }
2839 
2840                     if (!BigNumber.DblToRgbFast(dbl, _mantissa, out _exponent, out _mantissaSize))
2841                     {
2842                         BigNumber.DblToRgbPrecise(dbl, _mantissa, out _exponent, out _mantissaSize);
2843                     }
2844                 }
2845             }
2846         };
2847 
2848         /*  ----------------------------------------------------------------------------
2849             IntToString()
2850 
2851             Converts an integer to a string according to XPath rules.
2852         */
IntToString(int val)2853         private static unsafe string IntToString(int val)
2854         {
2855             // The maximum number of characters needed to represent any int value is 11
2856             const int BufSize = 12;
2857             char* pBuf = stackalloc char[BufSize];
2858             char* pch = pBuf += BufSize;
2859             uint u = (uint)(val < 0 ? -val : val);
2860 
2861             while (u >= 10)
2862             {
2863                 // Fast division by 10
2864                 uint quot = (uint)((0x66666667L * u) >> 32) >> 2;
2865                 *(--pch) = (char)((u - quot * 10) + '0');
2866                 u = quot;
2867             }
2868 
2869             *(--pch) = (char)(u + '0');
2870 
2871             if (val < 0)
2872             {
2873                 *(--pch) = '-';
2874             }
2875 
2876             return new string(pch, 0, (int)(pBuf - pch));
2877         }
2878 
2879         /*  ----------------------------------------------------------------------------
2880             DoubleToString()
2881 
2882             Converts a floating point number to a string according to XPath rules.
2883         */
DoubleToString(double dbl)2884         public static string DoubleToString(double dbl)
2885         {
2886             Debug.Assert(('0' & 0xF) == 0, "We use (char)(d |'0') to convert digit to char");
2887             int maxSize, sizeInt, sizeFract, cntDigits, ib;
2888             int iVal;
2889 
2890             if (IsInteger(dbl, out iVal))
2891             {
2892                 return IntToString(iVal);
2893             }
2894 
2895             // Handle NaN and infinity
2896             if (IsSpecial(dbl))
2897             {
2898                 if (Double.IsNaN(dbl))
2899                 {
2900                     return "NaN";
2901                 }
2902 
2903                 Debug.Assert(Double.IsInfinity(dbl));
2904                 return dbl < 0 ? "-Infinity" : "Infinity";
2905             }
2906 
2907             // Get decimal digits
2908             FloatingDecimal dec = new FloatingDecimal(dbl);
2909             Debug.Assert(0 != dec.MantissaSize);
2910 
2911             // If exponent is negative, size of fraction increases
2912             sizeFract = dec.MantissaSize - dec.Exponent;
2913 
2914             if (sizeFract > 0)
2915             {
2916                 // Decimal consists of a fraction part + possible integer part
2917                 sizeInt = (dec.Exponent > 0) ? dec.Exponent : 0;
2918             }
2919             else
2920             {
2921                 // Decimal consists of just an integer part
2922                 sizeInt = dec.Exponent;
2923                 sizeFract = 0;
2924             }
2925 
2926             // Sign + integer + fraction + decimal point + leading zero + terminating null
2927             maxSize = sizeInt + sizeFract + 4;
2928 
2929             unsafe
2930             {
2931                 // Allocate output memory
2932                 char* pBuf = stackalloc char[maxSize];
2933                 char* pch = pBuf;
2934 
2935                 if (dec.Sign < 0)
2936                 {
2937                     *pch++ = '-';
2938                 }
2939 
2940                 cntDigits = dec.MantissaSize;
2941                 ib = 0;
2942 
2943                 if (0 != sizeInt)
2944                 {
2945                     do
2946                     {
2947                         if (0 != cntDigits)
2948                         {
2949                             // Still mantissa digits left to consume
2950                             Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
2951                             *pch++ = (char)(dec[ib++] | '0');
2952                             cntDigits--;
2953                         }
2954                         else
2955                         {
2956                             // Add trailing zeros
2957                             *pch++ = '0';
2958                         }
2959                     } while (0 != --sizeInt);
2960                 }
2961                 else
2962                 {
2963                     *pch++ = '0';
2964                 }
2965 
2966                 if (0 != sizeFract)
2967                 {
2968                     Debug.Assert(0 != cntDigits);
2969                     Debug.Assert(sizeFract == cntDigits || sizeFract > cntDigits && pch[-1] == '0');
2970                     *pch++ = '.';
2971 
2972                     while (sizeFract > cntDigits)
2973                     {
2974                         // Add leading zeros
2975                         *pch++ = '0';
2976                         sizeFract--;
2977                     }
2978 
2979                     Debug.Assert(sizeFract == cntDigits);
2980                     while (0 != cntDigits)
2981                     {
2982                         // Output remaining mantissa digits
2983                         Debug.Assert(dec[ib] >= 0 && dec[ib] <= 9);
2984                         *pch++ = (char)(dec[ib++] | '0');
2985                         cntDigits--;
2986                     }
2987                 }
2988 
2989                 Debug.Assert(0 == sizeInt && 0 == cntDigits);
2990                 return new string(pBuf, 0, (int)(pch - pBuf));
2991             }
2992         }
2993 
IsAsciiDigit(char ch)2994         private static bool IsAsciiDigit(char ch)
2995         {
2996             return unchecked((uint)(ch - '0')) <= 9;
2997         }
2998 
IsWhitespace(char ch)2999         private static bool IsWhitespace(char ch)
3000         {
3001             return ch == '\x20' || ch == '\x9' || ch == '\xA' || ch == '\xD';
3002         }
3003 
SkipWhitespace(char* pch)3004         private static unsafe char* SkipWhitespace(char* pch)
3005         {
3006             while (IsWhitespace(*pch))
3007             {
3008                 pch++;
3009             }
3010             return pch;
3011         }
3012 
3013         /*  ----------------------------------------------------------------------------
3014             StringToDouble()
3015 
3016             Converts a string to a floating point number according to XPath rules.
3017             NaN is returned if the entire string is not a valid number.
3018 
3019             This code was stolen from MSXML6 DecimalFormat::parse(). The implementation
3020             depends on the fact that the String objects are always zero-terminated.
3021         */
StringToDouble(string s)3022         public static unsafe double StringToDouble(string s)
3023         {
3024             Debug.Assert(('0' & 0xF) == 0, "We use (ch & 0xF) to convert char to digit");
3025             // For the mantissa digits. After leaving the state machine, pchFirstDig
3026             // points to the first digit and pch points just past the last digit.
3027             // numDig is the number of digits. pch - pchFirstDig may be numDig + 1
3028             // (if there is a decimal point).
3029 
3030             fixed (char* pchStart = s)
3031             {
3032                 int numDig = 0;
3033                 char* pch = pchStart;
3034                 char* pchFirstDig = null;
3035                 char ch;
3036 
3037                 int sign = 1;       // sign of the mantissa
3038                 int expAdj = 0;     // exponent adjustment
3039 
3040             // Enter the state machine
3041 
3042             // Initialization
3043             LRestart:
3044                 ch = *pch++;
3045                 if (IsAsciiDigit(ch))
3046                 {
3047                     goto LGetLeft;
3048                 }
3049 
3050                 switch (ch)
3051                 {
3052                     case '-':
3053                         if (sign < 0)
3054                         {
3055                             break;
3056                         }
3057                         sign = -1;
3058                         goto LRestart;
3059                     case '.':
3060                         if (IsAsciiDigit(*pch))
3061                         {
3062                             goto LGetRight;
3063                         }
3064                         break;
3065                     default:
3066                         // MSXML has a bug, we should not allow whitespace after a minus sign
3067                         if (IsWhitespace(ch) && sign > 0)
3068                         {
3069                             pch = SkipWhitespace(pch);
3070                             goto LRestart;
3071                         }
3072                         break;
3073                 }
3074 
3075                 // Nothing digested - set the result to NaN and exit.
3076                 return Double.NaN;
3077 
3078             LGetLeft:
3079                 // Get digits to the left of the decimal point
3080                 if (ch == '0')
3081                 {
3082                     do
3083                     {
3084                         // Trim leading zeros
3085                         ch = *pch++;
3086                     } while (ch == '0');
3087 
3088                     if (!IsAsciiDigit(ch))
3089                     {
3090                         goto LSkipNonZeroDigits;
3091                     }
3092                 }
3093 
3094                 Debug.Assert(IsAsciiDigit(ch));
3095                 pchFirstDig = pch - 1;
3096                 do
3097                 {
3098                     ch = *pch++;
3099                 } while (IsAsciiDigit(ch));
3100                 numDig = (int)(pch - pchFirstDig) - 1;
3101 
3102             LSkipNonZeroDigits:
3103                 if (ch != '.')
3104                 {
3105                     goto LEnd;
3106                 }
3107 
3108             LGetRight:
3109                 Debug.Assert(ch == '.');
3110                 ch = *pch++;
3111                 if (pchFirstDig == null)
3112                 {
3113                     // Count fractional leading zeros (e.g. six zeros in '0.0000005')
3114                     while (ch == '0')
3115                     {
3116                         expAdj--;
3117                         ch = *pch++;
3118                     }
3119                     pchFirstDig = pch - 1;
3120                 }
3121 
3122                 while (IsAsciiDigit(ch))
3123                 {
3124                     expAdj--;
3125                     numDig++;
3126                     ch = *pch++;
3127                 }
3128 
3129             LEnd:
3130                 pch--;
3131                 char* pchEnd = pchStart + s.Length;
3132                 Debug.Assert(*pchEnd == '\0', "String objects must be zero-terminated");
3133 
3134                 if (pch < pchEnd && SkipWhitespace(pch) < pchEnd)
3135                 {
3136                     // If we're not at the end of the string, this is not a valid number
3137                     return Double.NaN;
3138                 }
3139 
3140                 if (numDig == 0)
3141                 {
3142                     return 0.0;
3143                 }
3144 
3145                 Debug.Assert(pchFirstDig != null);
3146 
3147                 if (expAdj == 0)
3148                 {
3149                     // Assert(StrRChrW(pchFirstDig, &pchFirstDig[numDig], '.') == null);
3150 
3151                     // Detect special case where number is an integer
3152                     if (numDig <= 9)
3153                     {
3154                         Debug.Assert(pchFirstDig != pch);
3155                         int iNum = *pchFirstDig & 0xF; // - '0'
3156                         while (--numDig != 0)
3157                         {
3158                             pchFirstDig++;
3159                             Debug.Assert(IsAsciiDigit(*pchFirstDig));
3160                             iNum = iNum * 10 + (*pchFirstDig & 0xF); // - '0'
3161                         }
3162                         return (double)(sign < 0 ? -iNum : iNum);
3163                     }
3164                 }
3165                 else
3166                 {
3167                     // The number has a fractional part
3168                     Debug.Assert(expAdj < 0);
3169                     // Assert(StrRChrW(pchStart, pch, '.') != null);
3170                 }
3171 
3172                 // Limit to 50 digits (double is only precise up to 17 or so digits)
3173                 if (numDig > FloatingDecimal.MaxDigits)
3174                 {
3175                     pch -= (numDig - FloatingDecimal.MaxDigits);
3176                     expAdj += (numDig - FloatingDecimal.MaxDigits);
3177                     numDig = FloatingDecimal.MaxDigits;
3178                 }
3179 
3180                 // Remove trailing zero's from mantissa
3181                 Debug.Assert(IsAsciiDigit(*pchFirstDig) && *pchFirstDig != '0');
3182                 while (true)
3183                 {
3184                     if (*--pch == '0')
3185                     {
3186                         numDig--;
3187                         expAdj++;
3188                     }
3189                     else if (*pch != '.')
3190                     {
3191                         Debug.Assert(IsAsciiDigit(*pch) && *pch != '0');
3192                         pch++;
3193                         break;
3194                     }
3195                 }
3196                 Debug.Assert(pch - pchFirstDig == numDig || pch - pchFirstDig == numDig + 1);
3197 
3198                 {
3199                     // Construct a floating decimal from the array of digits
3200                     Debug.Assert(numDig > 0 && numDig <= FloatingDecimal.MaxDigits);
3201 
3202                     FloatingDecimal dec = new FloatingDecimal();
3203                     dec.Exponent = expAdj + numDig;
3204                     dec.Sign = sign;
3205                     dec.MantissaSize = numDig;
3206 
3207                     fixed (byte* pin = &dec.Mantissa[0])
3208                     {
3209                         byte* mantissa = pin;
3210                         while (pchFirstDig < pch)
3211                         {
3212                             if (*pchFirstDig != '.')
3213                             {
3214                                 *mantissa = (byte)(*pchFirstDig & 0xF); // - '0'
3215                                 mantissa++;
3216                             }
3217                             pchFirstDig++;
3218                         }
3219                     }
3220 
3221                     return (double)dec;
3222                 }
3223             }
3224         }
3225     }
3226 }
3227