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