PageRenderTime 111ms CodeModel.GetById 15ms app.highlight 83ms RepoModel.GetById 1ms app.codeStats 1ms

/IronPython_Main/Runtime/Microsoft.Dynamic/Math/BigIntegerV2.cs

#
C# | 1757 lines | 1395 code | 267 blank | 95 comment | 430 complexity | c973411751ed54f63b08ec1e6bc3e730 MD5 | raw file
   1/* ****************************************************************************
   2 *
   3 * Copyright (c) Microsoft Corporation. 
   4 *
   5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
   6 * copy of the license can be found in the License.html file at the root of this distribution. If 
   7 * you cannot locate the  Apache License, Version 2.0, please send an email to 
   8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
   9 * by the terms of the Apache License, Version 2.0.
  10 *
  11 * You must not remove this notice, or any other, from this software.
  12 *
  13 *
  14 * ***************************************************************************/
  15#if CLR2
  16
  17using System;
  18using System.Collections.Generic;
  19using System.Diagnostics;
  20using System.Diagnostics.CodeAnalysis;
  21using System.Globalization;
  22using System.Text;
  23using Microsoft.Contracts;
  24using Microsoft.Scripting.Utils;
  25
  26namespace Microsoft.Scripting.Math {
  27    /// <summary>
  28    /// arbitrary precision integers
  29    /// </summary>
  30    [Serializable]
  31    public sealed class BigInteger : IFormattable, IComparable, IConvertible, IEquatable<BigInteger> {
  32        private const int BitsPerDigit = 32;
  33        private const ulong Base = 0x100000000;
  34
  35        // -1 if negative, +1 if positive, 0 if zero.
  36        private readonly short sign;
  37
  38        // Non-null. data[0] is the least significant 32 bits.
  39        private readonly uint[] data;
  40
  41        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  42        public static readonly BigInteger Zero = new BigInteger(0, new uint[0]);
  43        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  44        public static readonly BigInteger One = new BigInteger(+1, new uint[] { 1 });
  45        private const int bias = 1075;
  46
  47        [CLSCompliant(false)]
  48        public static BigInteger Create(ulong v) {
  49            return new BigInteger(+1, (uint)v, (uint)(v >> BitsPerDigit));
  50        }
  51
  52        [CLSCompliant(false)]
  53        public static BigInteger Create(uint v) {
  54            if (v == 0) return Zero;
  55            else if (v == 1) return One;
  56            else return new BigInteger(+1, v);
  57        }
  58
  59        public static BigInteger Create(long v) {
  60            ulong x;
  61            int s = +1;
  62            if (v < 0) {
  63                x = (ulong)-v; s = -1;
  64            } else {
  65                x = (ulong)v;
  66            }
  67
  68            return new BigInteger(s, (uint)x, (uint)(x >> BitsPerDigit));
  69        }
  70
  71        public static BigInteger Create(int v) {
  72            if (v == 0) return Zero;
  73            else if (v == 1) return One;
  74            else if (v < 0) return new BigInteger(-1, (uint)-v);
  75            else return new BigInteger(+1, (uint)v);
  76        }
  77
  78        private const Int32 DecimalScaleFactorMask = 0x00FF0000;
  79        private const Int32 DecimalSignMask = unchecked((Int32)0x80000000);
  80
  81        public static BigInteger Create(decimal v) {
  82            // First truncate to get scale to 0 and extract bits
  83            int[] bits = Decimal.GetBits(Decimal.Truncate(v));
  84
  85            Debug.Assert(bits.Length == 4 && (bits[3] & DecimalScaleFactorMask) == 0);
  86
  87            int size = 3;
  88            while (size > 0 && bits[size - 1] == 0) size--;
  89
  90            if (size == 0) {
  91                return BigInteger.Zero;
  92            }
  93
  94            UInt32[] array = new UInt32[size];
  95            array[0] = (UInt32)bits[0];
  96            if (size > 1) array[1] = (UInt32)bits[1];
  97            if (size > 2) array[2] = (UInt32)bits[2];
  98
  99            return new BigInteger(((bits[3] & DecimalSignMask) != 0) ? -1 : +1, array);
 100        }
 101
 102        /// <summary>
 103        /// Create a BigInteger from a little-endian twos-complement byte array
 104        /// (inverse of ToByteArray())
 105        /// </summary>
 106        public static BigInteger Create(byte[] v) {
 107            ContractUtils.RequiresNotNull(v, "v");
 108            if (v.Length == 0) return Create(0);
 109
 110            int byteCount = v.Length;
 111            int unalignedBytes = byteCount % 4;
 112            int dwordCount = byteCount / 4 + (unalignedBytes == 0 ? 0 : 1);
 113            uint[] data = new uint[dwordCount];
 114
 115            bool isNegative = (v[byteCount - 1] & 0x80) == 0x80;
 116
 117            bool isZero = true;
 118
 119            // Copy all dwords, except but don't do the last one if it's not a full four bytes
 120            int curDword, curByte, byteInDword;
 121            curByte = 3;
 122            for (curDword = 0; curDword < dwordCount - (unalignedBytes == 0 ? 0 : 1); curDword++) {
 123                byteInDword = 0;
 124                while (byteInDword < 4) {
 125                    if (v[curByte] != 0x00) isZero = false;
 126                    data[curDword] <<= 8;
 127                    data[curDword] |= v[curByte];
 128                    curByte--;
 129                    byteInDword++;
 130                }
 131                curByte += 8;
 132            }
 133
 134            // Copy the last dword specially if it's not aligned
 135            if (unalignedBytes != 0) {
 136                if (isNegative) data[dwordCount - 1] = 0xffffffff;
 137                for (curByte = byteCount - 1; curByte >= byteCount - unalignedBytes; curByte--) {
 138                    if (v[curByte] != 0x00) isZero = false;
 139                    data[curDword] <<= 8;
 140                    data[curDword] |= v[curByte];
 141                }
 142            }
 143
 144            if (isZero) return Zero;
 145
 146            if (isNegative) {
 147                makeTwosComplement(data);
 148                return new BigInteger(-1, data);
 149            }
 150            return new BigInteger(1, data);
 151        }
 152
 153
 154        private static bool Negative(byte[] v) {
 155            return ((v[7] & 0x80) != 0);
 156        }
 157
 158        private static ushort Exponent(byte[] v) {
 159            return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4));
 160        }
 161
 162        private static ulong Mantissa(byte[] v) {
 163            uint i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24));
 164            uint i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16));
 165
 166            return (ulong)((ulong)i1 | ((ulong)i2 << 32));
 167        }
 168
 169        public static BigInteger Create(double v) {
 170            if (Double.IsNaN(v) || Double.IsInfinity(v)) {
 171                throw new OverflowException();
 172            }
 173
 174            byte[] bytes = System.BitConverter.GetBytes(v);
 175            ulong mantissa = Mantissa(bytes);
 176            if (mantissa == 0) {
 177                // 1.0 * 2**exp, we have a power of 2
 178                int exponent = Exponent(bytes);
 179                if (exponent == 0) return Zero;
 180
 181                BigInteger res = Negative(bytes) ? Negate(One) : One;
 182                res = res << (exponent - 0x3ff);
 183                return res;
 184            } else {
 185                // 1.mantissa * 2**exp
 186                int exponent = Exponent(bytes);
 187                mantissa |= 0x10000000000000ul;
 188                BigInteger res = BigInteger.Create(mantissa);
 189                res = exponent > bias ? res << (exponent - bias) : res >> (bias - exponent);
 190                return Negative(bytes) ? res * (-1) : res;
 191            }
 192        }
 193
 194        public static implicit operator BigInteger(byte i) {
 195            return Create((uint)i);
 196        }
 197
 198        [CLSCompliant(false)]
 199        public static implicit operator BigInteger(sbyte i) {
 200            return Create((int)i);
 201        }
 202
 203        public static implicit operator BigInteger(short i) {
 204            return Create((int)i);
 205        }
 206
 207        [CLSCompliant(false)]
 208        public static implicit operator BigInteger(ushort i) {
 209            return Create((uint)i);
 210        }
 211
 212        [CLSCompliant(false)]
 213        public static implicit operator BigInteger(uint i) {
 214            return Create(i);
 215        }
 216
 217        public static implicit operator BigInteger(int i) {
 218            return Create(i);
 219        }
 220
 221        [CLSCompliant(false)]
 222        public static implicit operator BigInteger(ulong i) {
 223            return Create(i);
 224        }
 225
 226        public static implicit operator BigInteger(long i) {
 227            return Create(i);
 228        }
 229
 230        public static implicit operator BigInteger(decimal i) {
 231            return Create(i);
 232        }
 233
 234        public static explicit operator BigInteger(double self) {
 235            return Create(self);
 236        }
 237
 238        public static explicit operator BigInteger(float self) {
 239            return Create((double)self);
 240        }
 241
 242        public static explicit operator double(BigInteger self) {
 243            if (object.ReferenceEquals(self, null)) {
 244                throw new ArgumentNullException("self");
 245            }
 246            return self.ToFloat64();
 247        }
 248
 249        public static explicit operator float(BigInteger self) {
 250            if (object.ReferenceEquals(self, null)) {
 251                throw new ArgumentNullException("self");
 252            }
 253            return checked((float)self.ToFloat64());
 254        }
 255
 256        public static explicit operator decimal(BigInteger self) {
 257            decimal res;
 258            if (self.AsDecimal(out res)) {
 259                return res;
 260            }
 261            throw new OverflowException();
 262        }
 263
 264        public static explicit operator byte(BigInteger self) {
 265            int tmp;
 266            if (self.AsInt32(out tmp)) {
 267                return checked((byte)tmp);
 268            }
 269            throw new OverflowException();
 270        }
 271
 272        [CLSCompliant(false)]
 273        public static explicit operator sbyte(BigInteger self) {
 274            int tmp;
 275            if (self.AsInt32(out tmp)) {
 276                return checked((sbyte)tmp);
 277            }
 278            throw new OverflowException();
 279        }
 280
 281        [CLSCompliant(false)]
 282        public static explicit operator UInt16(BigInteger self) {
 283            int tmp;
 284            if (self.AsInt32(out tmp)) {
 285                return checked((UInt16)tmp);
 286            }
 287            throw new OverflowException();
 288        }
 289
 290        public static explicit operator Int16(BigInteger self) {
 291            int tmp;
 292            if (self.AsInt32(out tmp)) {
 293                return checked((Int16)tmp);
 294            }
 295            throw new OverflowException();
 296        }
 297
 298        [CLSCompliant(false)]
 299        public static explicit operator UInt32(BigInteger self) {
 300            uint tmp;
 301            if (self.AsUInt32(out tmp)) {
 302                return tmp;
 303            }
 304            throw new OverflowException();
 305        }
 306
 307        public static explicit operator Int32(BigInteger self) {
 308            int tmp;
 309            if (self.AsInt32(out tmp)) {
 310                return tmp;
 311            }
 312            throw new OverflowException();
 313        }
 314
 315        public static explicit operator Int64(BigInteger self) {
 316            long tmp;
 317            if (self.AsInt64(out tmp)) {
 318                return tmp;
 319            }
 320            throw new OverflowException();
 321        }
 322
 323        [CLSCompliant(false)]
 324        public static explicit operator UInt64(BigInteger self) {
 325            ulong tmp;
 326            if (self.AsUInt64(out tmp)) {
 327                return tmp;
 328            }
 329            throw new OverflowException();
 330        }
 331
 332        public BigInteger(BigInteger copy) {
 333            if (object.ReferenceEquals(copy, null)) {
 334                throw new ArgumentNullException("copy");
 335            }
 336            this.sign = copy.sign;
 337            this.data = copy.data;
 338        }
 339
 340        public BigInteger(byte[] bytes) : this(Create(bytes)) { }
 341
 342        [CLSCompliant(false)]
 343        public BigInteger(int sign, params uint[] data) {
 344            ContractUtils.RequiresNotNull(data, "data");
 345            ContractUtils.Requires(sign >= -1 && sign <= +1, "sign");
 346            int length = GetLength(data);
 347            ContractUtils.Requires(length == 0 || sign != 0, "sign");
 348            
 349            this.data = data;
 350            this.sign = (short)(length == 0 ? 0 : sign);
 351        }
 352
 353        /// <summary>
 354        /// Return the magnitude of this BigInteger as an array of zero or more uints.
 355        /// Element zero is the value of the least significant four bytes, element one is
 356        /// the value of the four next most significant bytes, etc.
 357        /// 
 358        /// The returned data is the unsigned magnitude of the number. To determine the sign,
 359        /// use GetSign().
 360        /// 
 361        /// It is guaranteed that the highest element of the returned array is never zero.
 362        /// This means that if the value of this BigInteger is zero, a zero-length array
 363        /// is returned.
 364        /// </summary>
 365        [CLSCompliant(false)]
 366        public uint[] GetWords() {
 367            if (sign == 0) return new uint[] { 0 };
 368            int w = GetLength();
 369            uint[] bits = new uint[w];
 370            Array.Copy(data, bits, w);
 371            return bits;
 372        }
 373
 374        [CLSCompliant(false)]
 375        public uint GetWord(int index) {
 376            return data[index];
 377        }
 378
 379        public int GetBitCount() {
 380            if (IsZero()) {
 381                return 1;
 382            }
 383            int w = GetLength() - 1;
 384            uint b = data[w];
 385            Debug.Assert(b > 0);
 386            int result = w * 32;
 387
 388            if (b >= 1u << 16) {
 389                b >>= 16;
 390                result += 16;
 391            }
 392            if (b >= 1u << 8) {
 393                b >>= 8;
 394                result += 8;
 395            }
 396            if (b >= 1u << 4) {
 397                b >>= 4;
 398                result += 4;
 399            }
 400            if (b >= 1u << 2) {
 401                b >>= 2;
 402                result += 2;
 403            }
 404            if (b >= 1u << 1) {
 405                b >>= 1;
 406                result++;
 407            }
 408            if (b > 0) {
 409                result++;
 410            }
 411
 412            return result;
 413        }
 414
 415        public int GetByteCount() {
 416            return (GetBitCount() + 7) / 8;
 417        }
 418
 419        /// <summary>
 420        /// Return the sign of this BigInteger: -1, 0, or 1.
 421        /// </summary>
 422        public short Sign {
 423            get {
 424                return sign;
 425            }
 426        }
 427
 428        public bool AsInt64(out long ret) {
 429            ret = 0;
 430            if (sign == 0) return true;
 431            if (GetLength() > 2) return false;
 432            if (data.Length == 1) {
 433                ret = sign * (long)data[0];
 434                return true;
 435            }
 436            ulong tmp = (((ulong)data[1]) << 32 | (ulong)data[0]);
 437            if (tmp > 0x8000000000000000) return false;
 438            if (tmp == 0x8000000000000000 && sign == 1) return false;
 439            ret = ((long)tmp) * sign;
 440            return true;
 441        }
 442
 443        [CLSCompliant(false)]
 444        public bool AsUInt32(out uint ret) {
 445            ret = 0;
 446            if (sign == 0) return true;
 447            if (sign < 0) return false;
 448            if (GetLength() > 1) return false;
 449            ret = data[0];
 450            return true;
 451        }
 452
 453        [CLSCompliant(false)]
 454        public bool AsUInt64(out ulong ret) {
 455            ret = 0;
 456            if (sign == 0) return true;
 457            if (sign < 0) return false;
 458            if (GetLength() > 2) return false;
 459            ret = (ulong)data[0];
 460            if (data.Length > 1) {
 461                ret |= ((ulong)data[1]) << 32;
 462            }
 463            return true;
 464        }
 465
 466        public bool AsInt32(out int ret) {
 467            ret = 0;
 468            if (sign == 0) return true;
 469            if (GetLength() > 1) return false;
 470            if (data[0] > 0x80000000) return false;
 471            if (data[0] == 0x80000000 && sign == 1) return false;
 472            ret = (int)data[0];
 473            ret *= sign;
 474            return true;
 475        }
 476
 477        public bool AsDecimal(out Decimal ret) {
 478            if (sign == 0) {
 479                ret = Decimal.Zero;
 480                return true;
 481            }
 482
 483            int length = GetLength();
 484            if (length > 3) {
 485                ret = default(Decimal);
 486                return false;
 487            }
 488
 489            int lo = 0, mi = 0, hi = 0;
 490            if (length > 2) hi = (Int32)data[2];
 491            if (length > 1) mi = (Int32)data[1];
 492            if (length > 0) lo = (Int32)data[0];
 493
 494            ret = new Decimal(lo, mi, hi, sign < 0, 0);
 495            return true;
 496        }
 497
 498
 499        [CLSCompliant(false)]
 500        public uint ToUInt32() {
 501            uint ret;
 502            if (AsUInt32(out ret)) return ret;
 503            throw new OverflowException("big integer won't fit into uint");
 504        }
 505
 506        public int ToInt32() {
 507            int ret;
 508            if (AsInt32(out ret)) return ret;
 509            throw new OverflowException("big integer won't fit into int");
 510        }
 511
 512        public decimal ToDecimal() {
 513            decimal ret;
 514            if (AsDecimal(out ret)) return ret;
 515            throw new OverflowException("big integer won't fit into decimal");
 516        }
 517
 518        [CLSCompliant(false)]
 519        public ulong ToUInt64() {
 520            ulong ret;
 521            if (AsUInt64(out ret)) return ret;
 522            throw new OverflowException("big integer won't fit into ulong");
 523        }
 524
 525        public long ToInt64() {
 526            long ret;
 527            if (AsInt64(out ret)) return ret;
 528            throw new OverflowException("big integer won't fit into long");
 529        }
 530
 531        public int GetWordCount() {
 532            if (IsZero()) {
 533                return 1;
 534            }
 535            return GetLength();
 536        }
 537
 538        private int GetLength() {
 539            return GetLength(data);
 540        }
 541
 542        private static int GetLength(uint[] data) {
 543            int ret = data.Length - 1;
 544            while (ret >= 0 && data[ret] == 0) ret--;
 545            return ret + 1;
 546        }
 547
 548
 549        private static uint[] copy(uint[] v) {
 550            uint[] ret = new uint[v.Length];
 551            Array.Copy(v, ret, v.Length);
 552            return ret;
 553        }
 554
 555        private static uint[] resize(uint[] v, int len) {
 556            if (v.Length == len) return v;
 557            uint[] ret = new uint[len];
 558            int n = System.Math.Min(v.Length, len);
 559            for (int i = 0; i < n; i++) {
 560                ret[i] = v[i];
 561            }
 562            return ret;
 563        }
 564
 565        private static uint[] InternalAdd(uint[] x, int xl, uint[] y, int yl) {
 566            Debug.Assert(xl >= yl);
 567            uint[] z = new uint[xl];
 568
 569            int i;
 570            ulong sum = 0;
 571            for (i = 0; i < yl; i++) {
 572                sum = sum + x[i] + y[i];
 573                z[i] = (uint)sum;
 574                sum >>= BitsPerDigit;
 575            }
 576
 577            for (; i < xl && sum != 0; i++) {
 578                sum = sum + x[i];
 579                z[i] = (uint)sum;
 580                sum >>= BitsPerDigit;
 581            }
 582            if (sum != 0) {
 583                z = resize(z, xl + 1);
 584                z[i] = (uint)sum;
 585            } else {
 586                for (; i < xl; i++) {
 587                    z[i] = x[i];
 588                }
 589            }
 590            return z;
 591        }
 592
 593        private static uint[] sub(uint[] x, int xl, uint[] y, int yl) {
 594            Debug.Assert(xl >= yl);
 595            uint[] z = new uint[xl];
 596
 597            int i;
 598            bool borrow = false;
 599            for (i = 0; i < yl; i++) {
 600                uint xi = x[i];
 601                uint yi = y[i];
 602                if (borrow) {
 603                    if (xi == 0) {
 604                        xi = 0xffffffff;
 605                        borrow = true;
 606                    } else {
 607                        xi -= 1;
 608                        borrow = false;
 609                    }
 610                }
 611                if (yi > xi) borrow = true;
 612                z[i] = xi - yi;
 613            }
 614
 615            if (borrow) {
 616                for (; i < xl; i++) {
 617                    uint xi = x[i];
 618                    z[i] = xi - 1;
 619                    if (xi != 0) { i++; break; }
 620                }
 621            }
 622            for (; i < xl; i++) {
 623                z[i] = x[i];
 624            }
 625            return z;  // may have leading zeros
 626        }
 627
 628        private static uint[] add0(uint[] x, int xl, uint[] y, int yl) {
 629            if (xl >= yl) return InternalAdd(x, xl, y, yl);
 630            else return InternalAdd(y, yl, x, xl);
 631        }
 632
 633        public static int Compare(BigInteger x, BigInteger y) {
 634            if (object.ReferenceEquals(x, null)) {
 635                throw new ArgumentNullException("x");
 636            }
 637            if (object.ReferenceEquals(y, null)) {
 638                throw new ArgumentNullException("y");
 639            }
 640            if (x.sign == y.sign) {
 641                int xl = x.GetLength();
 642                int yl = y.GetLength();
 643                if (xl == yl) {
 644                    for (int i = xl - 1; i >= 0; i--) {
 645                        if (x.data[i] == y.data[i]) continue;
 646                        return x.data[i] > y.data[i] ? x.sign : -x.sign;
 647                    }
 648                    return 0;
 649                } else {
 650                    return xl > yl ? +x.sign : -x.sign;
 651                }
 652            } else {
 653                return x.sign > y.sign ? +1 : -1;
 654            }
 655        }
 656
 657        public static bool operator ==(BigInteger x, int y) {
 658            return x == (BigInteger)y;
 659        }
 660
 661        public static bool operator !=(BigInteger x, int y) {
 662            return !(x == y);
 663        }
 664
 665        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
 666        public static bool operator ==(BigInteger x, double y) {
 667            if (object.ReferenceEquals(x, null)) {
 668                throw new ArgumentNullException("x");
 669            }
 670
 671            // we can hold all double values, but not all double values
 672            // can hold BigInteger values, and we may lose precision.  Convert
 673            // the double to a big int, then compare.
 674
 675            if ((y % 1) != 0) return false;  // not a whole number, can't be equal
 676
 677            return x == BigInteger.Create(y);
 678        }
 679
 680        public static bool operator ==(double x, BigInteger y) {
 681            return y == x;
 682        }
 683
 684        public static bool operator !=(BigInteger x, double y) {
 685            return !(x == y);
 686        }
 687
 688        public static bool operator !=(double x, BigInteger y) {
 689            return !(x == y);
 690        }
 691
 692
 693        public static bool operator ==(BigInteger x, BigInteger y) {
 694            return Compare(x, y) == 0;
 695        }
 696
 697        public static bool operator !=(BigInteger x, BigInteger y) {
 698            return Compare(x, y) != 0;
 699        }
 700        public static bool operator <(BigInteger x, BigInteger y) {
 701            return Compare(x, y) < 0;
 702        }
 703        public static bool operator <=(BigInteger x, BigInteger y) {
 704            return Compare(x, y) <= 0;
 705        }
 706        public static bool operator >(BigInteger x, BigInteger y) {
 707            return Compare(x, y) > 0;
 708        }
 709        public static bool operator >=(BigInteger x, BigInteger y) {
 710            return Compare(x, y) >= 0;
 711        }
 712
 713        public static BigInteger Add(BigInteger x, BigInteger y) {
 714            return x + y;
 715        }
 716
 717        public static BigInteger operator +(BigInteger x, BigInteger y) {
 718            if (object.ReferenceEquals(x, null)) {
 719                throw new ArgumentNullException("x");
 720            }
 721            if (object.ReferenceEquals(y, null)) {
 722                throw new ArgumentNullException("y");
 723            }
 724
 725            if (x.sign == y.sign) {
 726                return new BigInteger(x.sign, add0(x.data, x.GetLength(), y.data, y.GetLength()));
 727            } else {
 728                return x - new BigInteger(-y.sign, y.data);  //??? performance issue
 729            }
 730        }
 731
 732        public static BigInteger Subtract(BigInteger x, BigInteger y) {
 733            return x - y;
 734        }
 735
 736        public static BigInteger operator -(BigInteger x, BigInteger y) {
 737            int c = Compare(x, y);
 738            if (c == 0) return Zero;
 739
 740            if (x.sign == y.sign) {
 741                uint[] z;
 742                switch (c * x.sign) {
 743                    case +1:
 744                        z = sub(x.data, x.GetLength(), y.data, y.GetLength());
 745                        break;
 746                    case -1:
 747                        z = sub(y.data, y.GetLength(), x.data, x.GetLength());
 748                        break;
 749                    default:
 750                        return Zero;
 751                }
 752                return new BigInteger(c, z);
 753            } else {
 754                uint[] z = add0(x.data, x.GetLength(), y.data, y.GetLength());
 755                return new BigInteger(c, z);
 756            }
 757        }
 758
 759        public static BigInteger Multiply(BigInteger x, BigInteger y) {
 760            return x * y;
 761        }
 762
 763        public static BigInteger operator *(BigInteger x, BigInteger y) {
 764            if (object.ReferenceEquals(x, null)) {
 765                throw new ArgumentNullException("x");
 766            }
 767            if (object.ReferenceEquals(y, null)) {
 768                throw new ArgumentNullException("y");
 769            }
 770            int xl = x.GetLength();
 771            int yl = y.GetLength();
 772            int zl = xl + yl;
 773            uint[] xd = x.data, yd = y.data, zd = new uint[zl];
 774
 775            for (int xi = 0; xi < xl; xi++) {
 776                uint xv = xd[xi];
 777                int zi = xi;
 778                ulong carry = 0;
 779                for (int yi = 0; yi < yl; yi++) {
 780                    carry = carry + ((ulong)xv) * yd[yi] + zd[zi];
 781                    zd[zi++] = (uint)carry;
 782                    carry >>= BitsPerDigit;
 783                }
 784                while (carry != 0) {
 785                    carry += zd[zi];
 786                    zd[zi++] = (uint)carry;
 787                    carry >>= BitsPerDigit;
 788                }
 789            }
 790
 791            return new BigInteger(x.sign * y.sign, zd);
 792        }
 793
 794        public static BigInteger Divide(BigInteger x, BigInteger y) {
 795            return x / y;
 796        }
 797
 798        public static BigInteger operator /(BigInteger x, BigInteger y) {
 799            BigInteger dummy;
 800            return DivRem(x, y, out dummy);
 801        }
 802
 803        public static BigInteger Mod(BigInteger x, BigInteger y) {
 804            return x % y;
 805        }
 806
 807        public static BigInteger operator %(BigInteger x, BigInteger y) {
 808            BigInteger ret;
 809            DivRem(x, y, out ret);
 810            return ret;
 811        }
 812
 813        private static int GetNormalizeShift(uint value) {
 814            int shift = 0;
 815
 816            if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
 817            if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
 818            if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
 819            if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
 820            if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
 821
 822            return shift;
 823        }
 824
 825        [Conditional("DEBUG")]
 826        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Scripting.Math.BigInteger")]
 827        private static void TestNormalize(uint[] u, uint[] un, int shift) {
 828            BigInteger i = new BigInteger(1, u);
 829            BigInteger j = new BigInteger(1, un);
 830            BigInteger k = j >> shift;
 831
 832            Debug.Assert(i == k);
 833        }
 834
 835        [Conditional("DEBUG")]
 836        private static void TestDivisionStep(uint[] un, uint[] vn, uint[] q, uint[] u, uint[] v) {
 837            int n = GetLength(v);
 838            int shift = GetNormalizeShift(v[n - 1]);
 839
 840            BigInteger uni = new BigInteger(1, un);
 841            BigInteger vni = new BigInteger(1, vn);
 842            BigInteger qi = new BigInteger(1, q);
 843            BigInteger ui = new BigInteger(1, u);
 844
 845            BigInteger expected = vni * qi + uni;
 846            BigInteger usi = ui << shift;
 847
 848            Debug.Assert(expected == usi);
 849        }
 850
 851        [Conditional("DEBUG")]
 852        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Scripting.Math.BigInteger")]
 853        private static void TestResult(uint[] u, uint[] v, uint[] q, uint[] r) {
 854            BigInteger ui = new BigInteger(1, u);
 855            BigInteger vi = new BigInteger(1, v);
 856            BigInteger qi = new BigInteger(1, q);
 857            BigInteger ri = new BigInteger(1, r);
 858
 859            BigInteger viqi = vi * qi;
 860            BigInteger expected = viqi + ri;
 861            Debug.Assert(ui == expected);
 862            Debug.Assert(ri < vi);
 863        }
 864
 865        private static void Normalize(uint[] u, int l, uint[] un, int shift) {
 866            Debug.Assert(un.Length == l || un.Length == l + 1);
 867            Debug.Assert(un.Length == l + 1 || ((u[l - 1] << shift) >> shift) == u[l - 1]);
 868            Debug.Assert(0 <= shift && shift < 32);
 869
 870            uint carry = 0;
 871            int i;
 872            if (shift > 0) {
 873                int rshift = BitsPerDigit - shift;
 874                for (i = 0; i < l; i++) {
 875                    uint ui = u[i];
 876                    un[i] = (ui << shift) | carry;
 877                    carry = ui >> rshift;
 878                }
 879            } else {
 880                for (i = 0; i < l; i++) {
 881                    un[i] = u[i];
 882                }
 883            }
 884
 885            while (i < un.Length) {
 886                un[i++] = 0;
 887            }
 888
 889            if (carry != 0) {
 890                Debug.Assert(l == un.Length - 1);
 891                un[l] = carry;
 892            }
 893
 894            TestNormalize(u, un, shift);
 895        }
 896
 897        private static void Unnormalize(uint[] un, out uint[] r, int shift) {
 898            Debug.Assert(0 <= shift && shift < 32);
 899
 900            int length = GetLength(un);
 901            r = new uint[length];
 902
 903            if (shift > 0) {
 904                int lshift = 32 - shift;
 905                uint carry = 0;
 906                for (int i = length - 1; i >= 0; i--) {
 907                    uint uni = un[i];
 908                    r[i] = (uni >> shift) | carry;
 909                    carry = (uni << lshift);
 910                }
 911            } else {
 912                for (int i = 0; i < length; i++) {
 913                    r[i] = un[i];
 914                }
 915            }
 916
 917            TestNormalize(r, un, shift);
 918        }
 919
 920        private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r) {
 921            int m = GetLength(u);
 922            int n = GetLength(v);
 923
 924            if (n <= 1) {
 925                if (n == 0) {
 926                    throw new DivideByZeroException();
 927                }
 928
 929                //  Divide by single digit
 930                //
 931                ulong rem = 0;
 932                uint v0 = v[0];
 933                q = new uint[m];
 934                r = new uint[1];
 935
 936                for (int j = m - 1; j >= 0; j--) {
 937                    rem *= Base;
 938                    rem += u[j];
 939
 940                    ulong div = rem / v0;
 941                    rem -= div * v0;
 942                    q[j] = (uint)div;
 943                }
 944                r[0] = (uint)rem;
 945            } else if (m >= n) {
 946                int shift = GetNormalizeShift(v[n - 1]);
 947
 948                uint[] un = new uint[m + 1];
 949                uint[] vn = new uint[n];
 950
 951                Normalize(u, m, un, shift);
 952                Normalize(v, n, vn, shift);
 953
 954                q = new uint[m - n + 1];
 955                r = null;
 956
 957                TestDivisionStep(un, vn, q, u, v);
 958
 959                //  Main division loop
 960                //
 961                for (int j = m - n; j >= 0; j--) {
 962                    ulong rr, qq;
 963                    int i;
 964
 965                    rr = Base * un[j + n] + un[j + n - 1];
 966                    qq = rr / vn[n - 1];
 967                    rr -= qq * vn[n - 1];
 968
 969                    Debug.Assert((Base * un[j + n] + un[j + n - 1]) == qq * vn[n - 1] + rr);
 970
 971                    for (; ; ) {
 972                        // Estimate too big ?
 973                        //
 974                        if ((qq >= Base) || (qq * vn[n - 2] > (rr * Base + un[j + n - 2]))) {
 975                            qq--;
 976                            rr += (ulong)vn[n - 1];
 977                            if (rr < Base) continue;
 978                        }
 979                        break;
 980                    }
 981
 982                    Debug.Assert((Base * un[j + n] + un[j + n - 1]) == qq * vn[n - 1] + rr);
 983
 984                    //  Multiply and subtract
 985                    //
 986                    long b = 0;
 987                    long t = 0;
 988                    for (i = 0; i < n; i++) {
 989                        ulong p = vn[i] * qq;
 990                        t = (long)un[i + j] - (long)(uint)p - b;
 991                        un[i + j] = (uint)t;
 992                        p >>= 32;
 993                        t >>= 32;
 994                        Debug.Assert(t == 0 || t == -1 || t == -2);
 995                        b = (long)p - t;
 996                    }
 997                    t = (long)un[j + n] - b;
 998                    un[j + n] = (uint)t;
 999
1000                    //  Store the calculated value
1001                    //
1002                    q[j] = (uint)qq;
1003
1004                    //  Add back vn[0..n] to un[j..j+n]
1005                    //
1006                    if (t < 0) {
1007                        q[j]--;
1008                        ulong c = 0;
1009                        for (i = 0; i < n; i++) {
1010                            c = (ulong)vn[i] + un[j + i] + c;
1011                            un[j + i] = (uint)c;
1012                            c >>= 32;
1013                        }
1014                        c += (ulong)un[j + n];
1015                        un[j + n] = (uint)c;
1016                    }
1017
1018                    TestDivisionStep(un, vn, q, u, v);
1019                }
1020
1021                Unnormalize(un, out r, shift);
1022
1023                //  Test normalized value ... Call TestNormalize
1024                //  only pass the values in different order.
1025                //
1026                TestNormalize(r, un, shift);
1027            } else {
1028                q = new uint[] { 0 };
1029                r = u;
1030            }
1031
1032            TestResult(u, v, q, r);
1033        }
1034
1035        public static BigInteger DivRem(BigInteger x, BigInteger y, out BigInteger remainder) {
1036            if (object.ReferenceEquals(x, null)) {
1037                throw new ArgumentNullException("x");
1038            }
1039            if (object.ReferenceEquals(y, null)) {
1040                throw new ArgumentNullException("y");
1041            }
1042
1043            uint[] q;
1044            uint[] r;
1045
1046            DivModUnsigned(x.data, y.data, out q, out r);
1047
1048            remainder = new BigInteger(x.sign, r);
1049            return new BigInteger(x.sign * y.sign, q);
1050        }
1051
1052        private static uint extend(uint v, ref bool seenNonZero) {
1053            if (seenNonZero) {
1054                return ~v;
1055            } else {
1056                if (v == 0) {
1057                    return 0;
1058                } else {
1059                    seenNonZero = true;
1060                    return ~v + 1;
1061                }
1062            }
1063        }
1064
1065        private static uint getOne(bool isNeg, uint[] data, int i, ref bool seenNonZero) {
1066            if (i < data.Length) {
1067                uint ret = data[i];
1068                return isNeg ? extend(ret, ref seenNonZero) : ret;
1069            } else {
1070                return isNeg ? uint.MaxValue : 0;
1071            }
1072        }
1073
1074        /// <summary>
1075        /// Do an in-place twos complement of d and also return the result.
1076        /// </summary>
1077        private static uint[] makeTwosComplement(uint[] d) {
1078            // first do complement and +1 as long as carry is needed
1079            int i = 0;
1080            uint v = 0;
1081            for (; i < d.Length; i++) {
1082                v = ~d[i] + 1;
1083                d[i] = v;
1084                if (v != 0) { i++; break; }
1085            }
1086
1087            if (v != 0) {
1088                // now ones complement is sufficient
1089                for (; i < d.Length; i++) {
1090                    d[i] = ~d[i];
1091                }
1092            } else {
1093                //??? this is weird
1094                d = resize(d, d.Length + 1);
1095                d[d.Length - 1] = 1;
1096            }
1097            return d;
1098        }
1099
1100        public static BigInteger BitwiseAnd(BigInteger x, BigInteger y) {
1101            return x & y;
1102        }
1103
1104        public static BigInteger operator &(BigInteger x, BigInteger y) {
1105            if (object.ReferenceEquals(x, null)) {
1106                throw new ArgumentNullException("x");
1107            }
1108            if (object.ReferenceEquals(y, null)) {
1109                throw new ArgumentNullException("y");
1110            }
1111            int xl = x.GetLength(), yl = y.GetLength();
1112            uint[] xd = x.data, yd = y.data;
1113
1114            int zl = System.Math.Max(xl, yl);
1115            uint[] zd = new uint[zl];
1116
1117            bool negx = x.sign == -1, negy = y.sign == -1;
1118            bool seenNonZeroX = false, seenNonZeroY = false;
1119            for (int i = 0; i < zl; i++) {
1120                uint xu = getOne(negx, xd, i, ref seenNonZeroX);
1121                uint yu = getOne(negy, yd, i, ref seenNonZeroY);
1122                zd[i] = xu & yu;
1123            }
1124
1125            if (negx && negy) {
1126
1127                return new BigInteger(-1, makeTwosComplement(zd));
1128            } else if (negx || negy) {
1129                return new BigInteger(+1, zd);
1130            } else {
1131                return new BigInteger(+1, zd);
1132            }
1133        }
1134
1135        public static BigInteger BitwiseOr(BigInteger x, BigInteger y) {
1136            return x | y;
1137        }
1138
1139        public static BigInteger operator |(BigInteger x, BigInteger y) {
1140            if (object.ReferenceEquals(x, null)) {
1141                throw new ArgumentNullException("x");
1142            }
1143            if (object.ReferenceEquals(y, null)) {
1144                throw new ArgumentNullException("y");
1145            }
1146            int xl = x.GetLength(), yl = y.GetLength();
1147            uint[] xd = x.data, yd = y.data;
1148
1149            int zl = System.Math.Max(xl, yl);
1150            uint[] zd = new uint[zl];
1151
1152            bool negx = x.sign == -1, negy = y.sign == -1;
1153            bool seenNonZeroX = false, seenNonZeroY = false;
1154            for (int i = 0; i < zl; i++) {
1155                uint xu = getOne(negx, xd, i, ref seenNonZeroX);
1156                uint yu = getOne(negy, yd, i, ref seenNonZeroY);
1157                zd[i] = xu | yu;
1158            }
1159
1160            if (negx && negy) {
1161                return new BigInteger(-1, makeTwosComplement(zd));
1162            } else if (negx || negy) {
1163                return new BigInteger(-1, makeTwosComplement(zd));
1164            } else {
1165                return new BigInteger(+1, zd);
1166            }
1167        }
1168
1169        public static BigInteger Xor(BigInteger x, BigInteger y) {
1170            return x ^ y;
1171        }
1172
1173        public static BigInteger operator ^(BigInteger x, BigInteger y) {
1174            if (object.ReferenceEquals(x, null)) {
1175                throw new ArgumentNullException("x");
1176            }
1177            if (object.ReferenceEquals(y, null)) {
1178                throw new ArgumentNullException("y");
1179            }
1180            int xl = x.GetLength(), yl = y.GetLength();
1181            uint[] xd = x.data, yd = y.data;
1182
1183            int zl = System.Math.Max(xl, yl);
1184            uint[] zd = new uint[zl];
1185
1186            bool negx = x.sign == -1, negy = y.sign == -1;
1187            bool seenNonZeroX = false, seenNonZeroY = false;
1188            for (int i = 0; i < zl; i++) {
1189                uint xu = getOne(negx, xd, i, ref seenNonZeroX);
1190                uint yu = getOne(negy, yd, i, ref seenNonZeroY);
1191                zd[i] = xu ^ yu;
1192            }
1193
1194            if (negx && negy) {
1195                return new BigInteger(+1, zd);
1196            } else if (negx || negy) {
1197                return new BigInteger(-1, makeTwosComplement(zd));
1198            } else {
1199                return new BigInteger(+1, zd);
1200            }
1201        }
1202
1203        public static BigInteger LeftShift(BigInteger x, int shift) {
1204            return x << shift;
1205        }
1206
1207        public static BigInteger operator <<(BigInteger x, int shift) {
1208            if (object.ReferenceEquals(x, null)) {
1209                throw new ArgumentNullException("x");
1210            }
1211            if (shift == 0) return x;
1212            else if (shift < 0) return x >> -shift;
1213
1214            int digitShift = shift / BitsPerDigit;
1215            int smallShift = shift - (digitShift * BitsPerDigit);
1216
1217            int xl = x.GetLength();
1218            uint[] xd = x.data;
1219            int zl = xl + digitShift + 1;
1220            uint[] zd = new uint[zl];
1221
1222            if (smallShift == 0) {
1223                for (int i = 0; i < xl; i++) {
1224                    zd[i + digitShift] = xd[i];
1225                }
1226            } else {
1227                int carryShift = BitsPerDigit - smallShift;
1228                uint carry = 0;
1229                int i;
1230                for (i = 0; i < xl; i++) {
1231                    uint rot = xd[i];
1232                    zd[i + digitShift] = rot << smallShift | carry;
1233                    carry = rot >> carryShift;
1234                }
1235                zd[i + digitShift] = carry;
1236            }
1237            return new BigInteger(x.sign, zd);
1238        }
1239
1240        public static BigInteger RightShift(BigInteger x, int shift) {
1241            return x >> shift;
1242        }
1243
1244        public static BigInteger operator >>(BigInteger x, int shift) {
1245            if (object.ReferenceEquals(x, null)) {
1246                throw new ArgumentNullException("x");
1247            }
1248            if (shift == 0) return x;
1249            else if (shift < 0) return x << -shift;
1250
1251            int digitShift = shift / BitsPerDigit;
1252            int smallShift = shift - (digitShift * BitsPerDigit);
1253
1254            int xl = x.GetLength();
1255            uint[] xd = x.data;
1256            int zl = xl - digitShift;
1257            if (zl < 0) zl = 0;
1258            uint[] zd = new uint[zl];
1259
1260            if (smallShift == 0) {
1261                for (int i = xl - 1; i >= digitShift; i--) {
1262                    zd[i - digitShift] = xd[i];
1263                }
1264            } else {
1265                int carryShift = BitsPerDigit - smallShift;
1266                uint carry = 0;
1267                for (int i = xl - 1; i >= digitShift; i--) {
1268                    uint rot = xd[i];
1269                    zd[i - digitShift] = rot >> smallShift | carry;
1270                    carry = rot << carryShift;
1271                }
1272            }
1273
1274            BigInteger res = new BigInteger(x.sign, zd);
1275
1276            // We wish to always round down, but shifting our data array (which is not
1277            // stored in 2's-complement form) has caused us to round towards zero instead.
1278            // Correct that here.
1279            if (x.IsNegative()) {
1280                for (int i = 0; i < digitShift; i++) {
1281                    if (xd[i] != 0u) {
1282                        return res - One;
1283                    }
1284                }
1285                if (smallShift > 0 && xd[digitShift] << (BitsPerDigit - smallShift) != 0u) {
1286                    return res - One;
1287                }
1288            }
1289
1290            return res;
1291        }
1292
1293        public static BigInteger Negate(BigInteger x) {
1294            return -x;
1295        }
1296
1297        public static BigInteger operator -(BigInteger x) {
1298            if (object.ReferenceEquals(x, null)) {
1299                throw new ArgumentNullException("x");
1300            }
1301            return new BigInteger(-x.sign, x.data);
1302        }
1303
1304        public BigInteger OnesComplement() {
1305            return ~this;
1306        }
1307
1308        public static BigInteger operator ~(BigInteger x) {
1309            if (object.ReferenceEquals(x, null)) {
1310                throw new ArgumentNullException("x");
1311            }
1312            return -(x + One);
1313        }
1314
1315        public BigInteger Abs() {
1316            if (this.sign == -1) return -this;
1317            else return this;
1318        }
1319
1320        public BigInteger Power(int exp) {
1321            if (exp == 0) return One;
1322            if (exp < 0) {
1323                throw new ArgumentOutOfRangeException("exp", "exp must be >= 0");
1324            }
1325            BigInteger factor = this;
1326            BigInteger result = One;
1327            while (exp != 0) {
1328                if ((exp & 1) != 0) result = result * factor;
1329                if (exp == 1) break;  // avoid costly factor.square()
1330                factor = factor.Square();
1331                exp >>= 1;
1332            }
1333            return result;
1334        }
1335
1336        public BigInteger ModPow(int power, BigInteger mod) {
1337            if (object.ReferenceEquals(mod, null)) {
1338                throw new ArgumentNullException("mod");
1339            }
1340
1341            if (power < 0) {
1342                throw new ArgumentOutOfRangeException("power", "power must be >= 0");
1343            }
1344            BigInteger factor = this;
1345            BigInteger result = One % mod; // Handle special case of power=0, mod=1
1346            while (power != 0) {
1347                if ((power & 1) != 0) {
1348                    result = result * factor;
1349                    result = result % mod;
1350                }
1351                if (power == 1) break;  // avoid costly factor.Square()
1352                factor = factor.Square();
1353                factor = factor % mod;
1354                power >>= 1;
1355            }
1356            return result;
1357        }
1358
1359        public BigInteger ModPow(BigInteger power, BigInteger mod) {
1360            if (object.ReferenceEquals(power, null)) {
1361                throw new ArgumentNullException("power");
1362            }
1363            if (object.ReferenceEquals(mod, null)) {
1364                throw new ArgumentNullException("mod");
1365            }
1366
1367            if (power < 0) {
1368                throw new ArgumentOutOfRangeException("power", "power must be >= 0");
1369            }
1370
1371            BigInteger factor = this;
1372            BigInteger result = One % mod;
1373            while (power != Zero) {
1374                if (!power.IsEven) {
1375                    result = result * factor;
1376                    result = result % mod;
1377                }
1378                if (power == One) break;  // avoid costly factor.Square()
1379                factor = factor.Square();
1380                factor = factor % mod;
1381                power >>= 1;
1382            }
1383            return result;
1384        }
1385
1386        public BigInteger Square() {
1387            return this * this;
1388        }
1389
1390        [Confined]
1391        public override string ToString() {
1392            return ToString(10);
1393        }
1394
1395        [Confined]
1396        public string ToString(int radix) {
1397            return MathUtils.BigIntegerToString(copy(data), sign, radix);
1398        }
1399
1400        [Confined]
1401        public override int GetHashCode() {
1402            // The Object.GetHashCode function needs to be consistent with the Object.Equals function.
1403            // Languages that build on top of this may have a more flexible equality function and 
1404            // so may not be able to use this hash function directly.
1405            // For example, Python allows BigInteger(10) == int32(10), so hashing a BigInt over the Int32
1406            // domain should return the same value as a hash of the Int32.
1407
1408            // If this is in the int32 range, this hash function returns the integer.
1409            if (data.Length == 0) {
1410                return 0;
1411            }
1412
1413            // Add up all uints. We want to incorporate all bits to get good hash distribution. 
1414            uint total = 0;
1415            foreach (uint x in data) {
1416                total = unchecked(total + x);
1417            }
1418
1419            int hash = unchecked((int)total);
1420
1421            // The sign is not part of the data array, so explicitly incorporate that.
1422            // This is also needed to ensure that hash(-x) == -x for int32.
1423            if (IsNegative()) {
1424                return unchecked(-hash);
1425            } else {
1426                return hash;
1427            }
1428        }
1429
1430        [Confined]
1431        public override bool Equals(object obj) {
1432            return Equals(obj as BigInteger);
1433        }
1434
1435        [StateIndependent]
1436        public bool Equals(BigInteger other) {
1437            if (object.ReferenceEquals(other, null)) return false;
1438            return this == other;
1439        }
1440
1441
1442        public bool IsNegative() {
1443            return sign < 0;
1444        }
1445
1446        public bool IsZero() {
1447            return sign == 0;
1448        }
1449
1450        public bool IsPositive() {
1451            return sign > 0;
1452        }
1453
1454        public bool IsEven {
1455            get { return data.Length == 0 || (data[0] & 1) == 0; }
1456        }
1457
1458        public double Log(Double newBase) {
1459            if (IsNegative() || newBase == 1.0D || this == Zero || (newBase == 0.0D && this != One)) {
1460                return Double.NaN;
1461            } else if (newBase == Double.PositiveInfinity) {
1462                return this == One ? 0.0D : Double.NaN;
1463            }
1464
1465            int length = GetLength() - 1;
1466            int bitCount = -1;
1467            for (int curBit = 31; curBit >= 0; curBit--) {
1468                if ((data[length] & (1 << curBit)) != 0) {
1469                    bitCount = curBit + length * 32;
1470                    break;
1471                }
1472            }
1473
1474            long bitlen = bitCount;
1475            Double c = 0, d = 1;
1476
1477            BigInteger testBit = BigInteger.One;
1478            long tempBitlen = bitlen;
1479            while (tempBitlen > Int32.MaxValue) {
1480                testBit = testBit << Int32.MaxValue;
1481                tempBitlen -= Int32.MaxValue;
1482            }
1483            testBit = testBit << (int)tempBitlen;
1484
1485            for (long curbit = bitlen; curbit >= 0; --curbit) {
1486                if ((this & testBit) != BigInteger.Zero)
1487                    c += d;
1488                d *= 0.5;
1489                testBit = testBit >> 1;
1490            }
1491            return (System.Math.Log(c) + System.Math.Log(2) * bitlen) / System.Math.Log(newBase);
1492        }
1493
1494        /// <summary>
1495        /// Calculates the natural logarithm of the BigInteger.
1496        /// </summary>
1497        public double Log() {
1498            return Log(System.Math.E);
1499        }
1500
1501        /// <summary>
1502        /// Calculates log base 10 of a BigInteger.
1503        /// </summary>
1504        public double Log10() {
1505            return Log(10);
1506        }
1507
1508#region IComparable Members
1509
1510        public int CompareTo(object obj) {
1511            if (obj == null) {
1512                return 1;
1513            }
1514            BigInteger o = obj as BigInteger;
1515            if (object.ReferenceEquals(o, null)) {
1516                throw new ArgumentException("expected integer");
1517            }
1518            return Compare(this, o);
1519        }
1520
1521        #endregion
1522
1523#region IConvertible Members
1524
1525        [Confined]
1526        public TypeCode GetTypeCode() {
1527            return TypeCode.Object;
1528        }
1529
1530        [Confined]
1531        public bool ToBoolean(IFormatProvider provider) {
1532            return this != Zero;
1533        }
1534
1535        [Confined]
1536        public byte ToByte(IFormatProvider provider) {
1537            uint ret;
1538            if (AsUInt32(out ret) && (ret & ~0xFF) == 0) {
1539                return (byte)ret;
1540            }
1541            throw new OverflowException("big integer won't fit into byte");
1542        }
1543
1544        /// <summary>
1545        /// Return the value of this BigInteger as a little-endian twos-complement
1546        /// byte array, using the fewest number of bytes possible. If the value is zero,
1547        /// return an array of one byte whose element is 0x00.
1548        /// </summary>
1549        public byte[] ToByteArray() {
1550            // We could probably make this more efficient by eliminating one of the passes.
1551            // The current code does one pass for uint array -> byte array conversion,
1552            // and then a another pass to remove unneeded bytes at the top of the array.
1553            if (0 == sign) return new byte[] { 0 };
1554
1555            uint[] dwords;
1556            byte highByte;
1557
1558            if (-1 == sign) {
1559                dwords = (uint[])this.data.Clone();
1560                makeTwosComplement(dwords);
1561                highByte = 0xff;
1562            } else {
1563                dwords = this.data;
1564                highByte = 0x00;
1565            }
1566
1567            byte[] bytes = new byte[4 * dwords.Length];
1568            int curByte = 0;
1569            uint dword;
1570            for (int i = 0; i < dwords.Length; i++) {
1571                dword = dwords[i];
1572                for (int j = 0; j < 4; j++) {
1573                    bytes[curByte++] = (byte)(dword & 0xff);
1574                    dword >>= 8;
1575                }
1576            }
1577
1578            // find highest significant byte
1579            int msb;
1580            for (msb = bytes.Length - 1; msb > 0; msb--) {
1581                if (bytes[msb] != highByte) break;
1582            }
1583            // ensure high bit is 0 if positive, 1 if negative
1584            bool needExtraByte = (bytes[msb] & 0x80) != (highByte & 0x80);
1585
1586            byte[] trimmedBytes = new byte[msb + 1 + (needExtraByte ? 1 : 0)];
1587            Array.Copy(bytes, trimmedBytes, msb + 1);
1588
1589            if (needExtraByte) trimmedBytes[trimmedBytes.Length - 1] = highByte;
1590
1591            return trimmedBytes;
1592        }
1593
1594        [Confined]
1595        public char ToChar(IFormatProvider provider) {
1596            int ret;
1597            if (AsInt32(out ret) && (ret <= Char.MaxValue) && (ret >= Char.MinValue)) {
1598                return (char)ret;
1599            }
1600            throw new OverflowException("big integer won't fit into char");
1601        }
1602
1603        [Confined]
1604        public DateTime ToDateTime(IFormatProvider provider) {
1605            throw new NotImplementedException();
1606        }
1607
1608        [Confined]
1609        public decimal ToDecimal(IFormatProvider provider) {
1610            decimal ret;
1611            if (AsDecimal(out ret)) return ret;
1612            throw new OverflowException("big integer won't fit into decimal");
1613        }
1614
1615        [Confined]
1616        public double ToDouble(IFormatProvider provider) {
1617            return this.ToFloat64();
1618        }
1619
1620        [Confined]
1621        public short ToInt16(IFormatProvider provider) {
1622            int ret;
1623            if (AsInt32(out ret) && (ret <= short.MaxValue) && (ret >= short.MinValue)) {
1624                return (short)ret;
1625            }
1626            throw new OverflowException("big integer won't fit into short");
1627        }
1628
1629        [Confined]
1630        public int ToInt32(IFormatProvider provider) {
1631            int ret;
1632            if (AsInt32(out ret)) {
1633                return ret;
1634            }
1635            throw new OverflowException("big integer won't fit into int");
1636        }
1637
1638        [Confined]
1639        public long ToInt64(IFormatProvider provider) {
1640            long ret;
1641            if (AsInt64(out ret)) {
1642                return ret;
1643            }
1644            throw new OverflowException("big integer won't fit into long");
1645        }
1646
1647        [CLSCompliant(false), Confined]
1648        public sbyte ToSByte(IFormatProvider provider) {
1649            int ret;
1650            if (AsInt32(out ret) && (ret <= sbyte.MaxValue) && (ret >= sbyte.MinValue)) {
1651                return (sbyte)ret;
1652            }
1653            throw new OverflowException("big integer won't fit into sbyte");
1654        }
1655
1656        [Confined]
1657        public float ToSingle(IFormatProvider provider) {
1658            return checked((float)ToDouble(provider));
1659        }
1660
1661        [Confined]
1662        public string ToString(IFormatProvider provider) {
1663            return ToString();
1664        }
1665
1666        [Confined]
1667        public object ToType(Type conversionType, IFormatProvider provider) {
1668            if (conversionType == typeof(BigInteger)) {
1669                return this;
1670            }
1671            throw new NotImplementedException();
1672        }
1673
1674        [CLSCompliant(false), Confined]
1675        public ushort ToUInt16(IFormatProvider provider) {
1676            uint ret;
1677            if (AsUInt32(out ret) && ret <= ushort.MaxValue) {
1678                return (ushort)ret;
1679            }
1680            throw new OverflowException("big integer won't fit into ushort");
1681        }
1682
1683        [CLSCompliant(false), Confined]
1684        public uint ToUInt32(IFormatProvider provider) {
1685            uint ret;
1686            if (AsUInt32(out ret)) {
1687                return ret;
1688            }
1689            throw new OverflowException("big integer won't fit into uint");
1690        }
1691
1692        [CLSCompliant(false), Confined]
1693        public ulong ToUInt64(IFormatProvider provider) {
1694            ulong ret;
1695            if (AsUInt64(out ret)) {
1696                return ret;
1697            }
1698            throw new OverflowException("big integer won't fit into ulong");
1699        }
1700
1701        #endregion
1702
1703#region IFormattable Members
1704
1705        string IFormattable.ToString(string format, IFormatProvider formatProvider) {
1706            if (format == null) return this.ToString();
1707
1708            switch (format[0]) {
1709                case 'd':
1710                case 'D':
1711                    if (format.Length > 1) {
1712                        int precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
1713                        string baseStr = ToString(10);
1714                        if (baseStr.Length < precision) {
1715                            string additional = new String('0', precision - baseStr.Length);
1716                            if (baseStr[0] != '-') {
1717                                return additional + baseStr;
1718                            } else {
1719                                return "-" + additional + baseStr.Substring(1);
1720                            }
1721                        }
1722                        return baseStr;
1723                    }
1724                    return ToString(10);
1725                case 'x':
1726                case 'X':
1727                    StringBuilder res = new StringBuilder(ToString(16));
1728                    if (format[0] == 'x') {
1729                        for (int i = 0; i < res.Length; i++) {
1730                            if (res[i] >= 'A' && res[i] <= 'F') {
1731                                res[i] = Char.ToLower(res[i], CultureInfo.InvariantCulture);
1732                            }
1733                        }
1734                    }
1735
1736                    if (format.Length > 1) {
1737                        int precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
1738                        if (res.Length < precision) {
1739                            string additional = new String('0', precision - res.Length);
1740                            if (res[0] != '-') {
1741                                res.Insert(0, additional);
1742                            } else {
1743                                res.Insert(1, additional);
1744                            }
1745                        }
1746                    }
1747
1748                    return res.ToString();
1749                default:
1750                    throw new NotImplementedException("format not implemented");
1751            }
1752        }
1753
1754        #endregion        
1755    }
1756}
1757#endif