1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation.
\r
5 * This source code is subject to terms and conditions of the Microsoft Public License. A
\r
6 * copy of the license can be found in the License.html file at the root of this distribution. If
\r
7 * you cannot locate the Microsoft Public License, please send an email to
\r
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
\r
9 * by the terms of the Microsoft Public License.
\r
11 * You must not remove this notice, or any other, from this software.
\r
14 * ***************************************************************************/
\r
17 using System.Collections.Generic;
\r
18 using System.Diagnostics;
\r
19 using System.Diagnostics.CodeAnalysis;
\r
20 using System.Globalization;
\r
23 namespace System.Numerics {
\r
25 /// arbitrary precision integers
\r
28 public sealed class BigInteger : IFormattable, IComparable, IConvertible, IEquatable<BigInteger> {
\r
29 private const int BitsPerDigit = 32;
\r
30 private const ulong Base = 0x100000000;
\r
32 // -1 if negative, +1 if positive, 0 if zero.
\r
33 private readonly short sign;
\r
35 // Non-null. data[0] is the least significant 32 bits.
\r
36 private readonly uint[] data;
\r
38 [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
\r
39 public static readonly BigInteger Zero = new BigInteger(0, new uint[0]);
\r
40 [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
\r
41 public static readonly BigInteger One = new BigInteger(+1, new uint[] { 1 });
\r
42 private const int bias = 1075;
\r
44 [CLSCompliant(false)]
\r
45 public static BigInteger Create(ulong v) {
\r
46 return new BigInteger(+1, (uint)v, (uint)(v >> BitsPerDigit));
\r
49 [CLSCompliant(false)]
\r
50 public static BigInteger Create(uint v) {
\r
51 if (v == 0) return Zero;
\r
52 else if (v == 1) return One;
\r
53 else return new BigInteger(+1, v);
\r
56 public static BigInteger Create(long v) {
\r
60 x = (ulong)-v; s = -1;
\r
65 return new BigInteger(s, (uint)x, (uint)(x >> BitsPerDigit));
\r
68 public static BigInteger Create(int v) {
\r
69 if (v == 0) return Zero;
\r
70 else if (v == 1) return One;
\r
71 else if (v < 0) return new BigInteger(-1, (uint)-v);
\r
72 else return new BigInteger(+1, (uint)v);
\r
75 private const Int32 DecimalScaleFactorMask = 0x00FF0000;
\r
76 private const Int32 DecimalSignMask = unchecked((Int32)0x80000000);
\r
78 public static BigInteger Create(decimal v) {
\r
79 // First truncate to get scale to 0 and extract bits
\r
80 int[] bits = Decimal.GetBits(Decimal.Truncate(v));
\r
82 Debug.Assert(bits.Length == 4 && (bits[3] & DecimalScaleFactorMask) == 0);
\r
85 while (size > 0 && bits[size - 1] == 0) size--;
\r
88 return BigInteger.Zero;
\r
91 UInt32[] array = new UInt32[size];
\r
92 array[0] = (UInt32)bits[0];
\r
93 if (size > 1) array[1] = (UInt32)bits[1];
\r
94 if (size > 2) array[2] = (UInt32)bits[2];
\r
96 return new BigInteger(((bits[3] & DecimalSignMask) != 0) ? -1 : +1, array);
\r
100 /// Create a BigInteger from a little-endian twos-complement byte array
\r
101 /// (inverse of ToByteArray())
\r
103 public static BigInteger Create(byte[] v) {
\r
105 throw new ArgumentNullException ("v");
\r
106 if (v.Length == 0) return Create(0);
\r
108 int byteCount = v.Length;
\r
109 int unalignedBytes = byteCount % 4;
\r
110 int dwordCount = byteCount / 4 + (unalignedBytes == 0 ? 0 : 1);
\r
111 uint[] data = new uint[dwordCount];
\r
113 bool isNegative = (v[byteCount - 1] & 0x80) == 0x80;
\r
115 bool isZero = true;
\r
117 // Copy all dwords, except but don't do the last one if it's not a full four bytes
\r
118 int curDword, curByte, byteInDword;
\r
120 for (curDword = 0; curDword < dwordCount - (unalignedBytes == 0 ? 0 : 1); curDword++) {
\r
122 while (byteInDword < 4) {
\r
123 if (v[curByte] != 0x00) isZero = false;
\r
124 data[curDword] <<= 8;
\r
125 data[curDword] |= v[curByte];
\r
132 // Copy the last dword specially if it's not aligned
\r
133 if (unalignedBytes != 0) {
\r
134 if (isNegative) data[dwordCount - 1] = 0xffffffff;
\r
135 for (curByte = byteCount - 1; curByte >= byteCount - unalignedBytes; curByte--) {
\r
136 if (v[curByte] != 0x00) isZero = false;
\r
137 data[curDword] <<= 8;
\r
138 data[curDword] |= v[curByte];
\r
142 if (isZero) return Zero;
\r
145 makeTwosComplement(data);
\r
146 return new BigInteger(-1, data);
\r
148 return new BigInteger(1, data);
\r
152 private static bool Negative(byte[] v) {
\r
153 return ((v[7] & 0x80) != 0);
\r
156 private static ushort Exponent(byte[] v) {
\r
157 return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4));
\r
160 private static ulong Mantissa(byte[] v) {
\r
161 uint i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24));
\r
162 uint i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16));
\r
164 return (ulong)((ulong)i1 | ((ulong)i2 << 32));
\r
167 public static BigInteger Create(double v) {
\r
168 if (Double.IsNaN(v) || Double.IsInfinity(v)) {
\r
169 throw new OverflowException();
\r
172 byte[] bytes = System.BitConverter.GetBytes(v);
\r
173 ulong mantissa = Mantissa(bytes);
\r
174 if (mantissa == 0) {
\r
175 // 1.0 * 2**exp, we have a power of 2
\r
176 int exponent = Exponent(bytes);
\r
177 if (exponent == 0) return Zero;
\r
179 BigInteger res = Negative(bytes) ? Negate(One) : One;
\r
180 res = res << (exponent - 0x3ff);
\r
183 // 1.mantissa * 2**exp
\r
184 int exponent = Exponent(bytes);
\r
185 mantissa |= 0x10000000000000ul;
\r
186 BigInteger res = BigInteger.Create(mantissa);
\r
187 res = exponent > bias ? res << (exponent - bias) : res >> (bias - exponent);
\r
188 return Negative(bytes) ? res * (-1) : res;
\r
192 public static implicit operator BigInteger(byte i) {
\r
193 return Create((uint)i);
\r
196 [CLSCompliant(false)]
\r
197 public static implicit operator BigInteger(sbyte i) {
\r
198 return Create((int)i);
\r
201 public static implicit operator BigInteger(short i) {
\r
202 return Create((int)i);
\r
205 [CLSCompliant(false)]
\r
206 public static implicit operator BigInteger(ushort i) {
\r
207 return Create((uint)i);
\r
210 [CLSCompliant(false)]
\r
211 public static implicit operator BigInteger(uint i) {
\r
215 public static implicit operator BigInteger(int i) {
\r
219 [CLSCompliant(false)]
\r
220 public static implicit operator BigInteger(ulong i) {
\r
224 public static implicit operator BigInteger(long i) {
\r
228 public static implicit operator BigInteger(decimal i) {
\r
232 public static explicit operator BigInteger(double self) {
\r
233 return Create(self);
\r
236 public static explicit operator BigInteger(float self) {
\r
237 return Create((double)self);
\r
240 public static explicit operator double(BigInteger self) {
\r
241 if (object.ReferenceEquals(self, null)) {
\r
242 throw new ArgumentNullException("self");
\r
244 return self.ToFloat64();
\r
247 public static explicit operator float(BigInteger self) {
\r
248 if (object.ReferenceEquals(self, null)) {
\r
249 throw new ArgumentNullException("self");
\r
251 return checked((float)self.ToFloat64());
\r
254 public static explicit operator decimal(BigInteger self) {
\r
256 if (self.AsDecimal(out res)) {
\r
259 throw new OverflowException();
\r
262 public static explicit operator byte(BigInteger self) {
\r
264 if (self.AsInt32(out tmp)) {
\r
265 return checked((byte)tmp);
\r
267 throw new OverflowException();
\r
270 [CLSCompliant(false)]
\r
271 public static explicit operator sbyte(BigInteger self) {
\r
273 if (self.AsInt32(out tmp)) {
\r
274 return checked((sbyte)tmp);
\r
276 throw new OverflowException();
\r
279 [CLSCompliant(false)]
\r
280 public static explicit operator UInt16(BigInteger self) {
\r
282 if (self.AsInt32(out tmp)) {
\r
283 return checked((UInt16)tmp);
\r
285 throw new OverflowException();
\r
288 public static explicit operator Int16(BigInteger self) {
\r
290 if (self.AsInt32(out tmp)) {
\r
291 return checked((Int16)tmp);
\r
293 throw new OverflowException();
\r
296 [CLSCompliant(false)]
\r
297 public static explicit operator UInt32(BigInteger self) {
\r
299 if (self.AsUInt32(out tmp)) {
\r
302 throw new OverflowException();
\r
305 public static explicit operator Int32(BigInteger self) {
\r
307 if (self.AsInt32(out tmp)) {
\r
310 throw new OverflowException();
\r
313 public static explicit operator Int64(BigInteger self) {
\r
315 if (self.AsInt64(out tmp)) {
\r
318 throw new OverflowException();
\r
321 [CLSCompliant(false)]
\r
322 public static explicit operator UInt64(BigInteger self) {
\r
324 if (self.AsUInt64(out tmp)) {
\r
327 throw new OverflowException();
\r
330 public BigInteger(BigInteger copy) {
\r
331 if (object.ReferenceEquals(copy, null)) {
\r
332 throw new ArgumentNullException("copy");
\r
334 this.sign = copy.sign;
\r
335 this.data = copy.data;
\r
338 [CLSCompliant(false)]
\r
339 public BigInteger(int sign, params uint[] data) {
\r
341 throw new ArgumentNullException ("data");
\r
342 if (!(sign >= -1 && sign <= +1))
\r
343 throw new ArgumentException ("sign");
\r
344 int length = GetLength(data);
\r
345 if (!(length == 0 || sign != 0))
\r
346 throw new ArgumentException ("sign");
\r
349 this.sign = (short)(length == 0 ? 0 : sign);
\r
353 /// Return the magnitude of this BigInteger as an array of zero or more uints.
\r
354 /// Element zero is the value of the least significant four bytes, element one is
\r
355 /// the value of the four next most significant bytes, etc.
\r
357 /// The returned data is the unsigned magnitude of the number. To determine the sign,
\r
360 /// It is guaranteed that the highest element of the returned array is never zero.
\r
361 /// This means that if the value of this BigInteger is zero, a zero-length array
\r
364 [CLSCompliant(false)]
\r
365 public uint[] GetWords() {
\r
366 if (sign == 0) return new uint[0];
\r
367 int w = GetWordCount();
\r
368 uint[] bits = new uint[w];
\r
369 Array.Copy(data, bits, w);
\r
373 [CLSCompliant(false)]
\r
374 public uint GetWord(int index) {
\r
375 return data[index];
\r
378 public int GetBitCount() {
\r
382 int w = GetWordCount() - 1;
\r
384 Debug.Assert(b > 0);
\r
385 int result = w * 32;
\r
394 public int GetByteCount() {
\r
395 return (GetBitCount() + 7) / 8;
\r
399 /// Return the sign of this BigInteger: -1, 0, or 1.
\r
401 public short Sign {
\r
407 public bool AsInt64(out long ret) {
\r
409 if (sign == 0) return true;
\r
410 if (GetWordCount() > 2) return false;
\r
411 if (data.Length == 1) {
\r
412 ret = sign * (long)data[0];
\r
415 ulong tmp = (((ulong)data[1]) << 32 | (ulong)data[0]);
\r
416 if (tmp > 0x8000000000000000) return false;
\r
417 if (tmp == 0x8000000000000000 && sign == 1) return false;
\r
418 ret = ((long)tmp) * sign;
\r
422 [CLSCompliant(false)]
\r
423 public bool AsUInt32(out uint ret) {
\r
425 if (sign == 0) return true;
\r
426 if (sign < 0) return false;
\r
427 if (GetWordCount() > 1) return false;
\r
432 [CLSCompliant(false)]
\r
433 public bool AsUInt64(out ulong ret) {
\r
435 if (sign == 0) return true;
\r
436 if (sign < 0) return false;
\r
437 if (GetWordCount() > 2) return false;
\r
438 ret = (ulong)data[0];
\r
439 if (data.Length > 1) {
\r
440 ret |= ((ulong)data[1]) << 32;
\r
445 public bool AsInt32(out int ret) {
\r
447 if (sign == 0) return true;
\r
448 if (GetWordCount() > 1) return false;
\r
449 if (data[0] > 0x80000000) return false;
\r
450 if (data[0] == 0x80000000 && sign == 1) return false;
\r
451 ret = (int)data[0];
\r
456 public bool AsDecimal(out Decimal ret) {
\r
458 ret = Decimal.Zero;
\r
462 int length = GetWordCount();
\r
464 ret = default(Decimal);
\r
468 int lo = 0, mi = 0, hi = 0;
\r
469 if (length > 2) hi = (Int32)data[2];
\r
470 if (length > 1) mi = (Int32)data[1];
\r
471 if (length > 0) lo = (Int32)data[0];
\r
473 ret = new Decimal(lo, mi, hi, sign < 0, 0);
\r
478 [CLSCompliant(false)]
\r
479 public uint ToUInt32() {
\r
481 if (AsUInt32(out ret)) return ret;
\r
482 throw new OverflowException("big integer won't fit into uint");
\r
485 public int ToInt32() {
\r
487 if (AsInt32(out ret)) return ret;
\r
488 throw new OverflowException("big integer won't fit into int");
\r
491 public decimal ToDecimal() {
\r
493 if (AsDecimal(out ret)) return ret;
\r
494 throw new OverflowException("big integer won't fit into decimal");
\r
497 [CLSCompliant(false)]
\r
498 public ulong ToUInt64() {
\r
500 if (AsUInt64(out ret)) return ret;
\r
501 throw new OverflowException("big integer won't fit into ulong");
\r
504 public long ToInt64() {
\r
506 if (AsInt64(out ret)) return ret;
\r
507 throw new OverflowException("big integer won't fit into long");
\r
510 public bool TryToFloat64(out double result) {
\r
511 return double.TryParse(ToString(10),
\r
512 System.Globalization.NumberStyles.Number,
\r
513 System.Globalization.CultureInfo.InvariantCulture.NumberFormat,
\r
517 public double ToFloat64() {
\r
518 return double.Parse(
\r
520 System.Globalization.CultureInfo.InvariantCulture.NumberFormat
\r
524 public int GetWordCount() {
\r
525 return GetLength(data);
\r
528 private static int GetLength(uint[] data) {
\r
529 int ret = data.Length - 1;
\r
530 while (ret >= 0 && data[ret] == 0) ret--;
\r
535 private static uint[] copy(uint[] v) {
\r
536 uint[] ret = new uint[v.Length];
\r
537 Array.Copy(v, ret, v.Length);
\r
541 private static uint[] resize(uint[] v, int len) {
\r
542 if (v.Length == len) return v;
\r
543 uint[] ret = new uint[len];
\r
544 int n = System.Math.Min(v.Length, len);
\r
545 for (int i = 0; i < n; i++) {
\r
551 private static uint[] InternalAdd(uint[] x, int xl, uint[] y, int yl) {
\r
552 Debug.Assert(xl >= yl);
\r
553 uint[] z = new uint[xl];
\r
557 for (i = 0; i < yl; i++) {
\r
558 sum = sum + x[i] + y[i];
\r
560 sum >>= BitsPerDigit;
\r
563 for (; i < xl && sum != 0; i++) {
\r
566 sum >>= BitsPerDigit;
\r
569 z = resize(z, xl + 1);
\r
572 for (; i < xl; i++) {
\r
579 private static uint[] sub(uint[] x, int xl, uint[] y, int yl) {
\r
580 Debug.Assert(xl >= yl);
\r
581 uint[] z = new uint[xl];
\r
584 bool borrow = false;
\r
585 for (i = 0; i < yl; i++) {
\r
597 if (yi > xi) borrow = true;
\r
602 for (; i < xl; i++) {
\r
605 if (xi != 0) { i++; break; }
\r
608 for (; i < xl; i++) {
\r
611 return z; // may have leading zeros
\r
614 private static uint[] add0(uint[] x, int xl, uint[] y, int yl) {
\r
615 if (xl >= yl) return InternalAdd(x, xl, y, yl);
\r
616 else return InternalAdd(y, yl, x, xl);
\r
619 public static int Compare(BigInteger x, BigInteger y) {
\r
620 if (object.ReferenceEquals(x, null)) {
\r
621 throw new ArgumentNullException("x");
\r
623 if (object.ReferenceEquals(y, null)) {
\r
624 throw new ArgumentNullException("y");
\r
626 if (x.sign == y.sign) {
\r
627 int xl = x.GetWordCount();
\r
628 int yl = y.GetWordCount();
\r
630 for (int i = xl - 1; i >= 0; i--) {
\r
631 if (x.data[i] == y.data[i]) continue;
\r
632 return x.data[i] > y.data[i] ? x.sign : -x.sign;
\r
636 return xl > yl ? +x.sign : -x.sign;
\r
639 return x.sign > y.sign ? +1 : -1;
\r
643 public static bool operator ==(BigInteger x, int y) {
\r
644 return x == (BigInteger)y;
\r
647 public static bool operator !=(BigInteger x, int y) {
\r
651 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
\r
652 public static bool operator ==(BigInteger x, double y) {
\r
653 if (object.ReferenceEquals(x, null)) {
\r
654 throw new ArgumentNullException("x");
\r
657 // we can hold all double values, but not all double values
\r
658 // can hold BigInteger values, and we may lose precision. Convert
\r
659 // the double to a big int, then compare.
\r
661 if ((y % 1) != 0) return false; // not a whole number, can't be equal
\r
663 return x == BigInteger.Create(y);
\r
666 public static bool operator ==(double x, BigInteger y) {
\r
670 public static bool operator !=(BigInteger x, double y) {
\r
674 public static bool operator !=(double x, BigInteger y) {
\r
679 public static bool operator ==(BigInteger x, BigInteger y) {
\r
680 return Compare(x, y) == 0;
\r
683 public static bool operator !=(BigInteger x, BigInteger y) {
\r
684 return Compare(x, y) != 0;
\r
686 public static bool operator <(BigInteger x, BigInteger y) {
\r
687 return Compare(x, y) < 0;
\r
689 public static bool operator <=(BigInteger x, BigInteger y) {
\r
690 return Compare(x, y) <= 0;
\r
692 public static bool operator >(BigInteger x, BigInteger y) {
\r
693 return Compare(x, y) > 0;
\r
695 public static bool operator >=(BigInteger x, BigInteger y) {
\r
696 return Compare(x, y) >= 0;
\r
699 public static BigInteger Add(BigInteger x, BigInteger y) {
\r
703 public static BigInteger operator +(BigInteger x, BigInteger y) {
\r
704 if (object.ReferenceEquals(x, null)) {
\r
705 throw new ArgumentNullException("x");
\r
707 if (object.ReferenceEquals(y, null)) {
\r
708 throw new ArgumentNullException("y");
\r
711 if (x.sign == y.sign) {
\r
712 return new BigInteger(x.sign, add0(x.data, x.GetWordCount(), y.data, y.GetWordCount()));
\r
714 return x - new BigInteger(-y.sign, y.data); //??? performance issue
\r
718 public static BigInteger Subtract(BigInteger x, BigInteger y) {
\r
722 public static BigInteger operator -(BigInteger x, BigInteger y) {
\r
723 int c = Compare(x, y);
\r
724 if (c == 0) return Zero;
\r
726 if (x.sign == y.sign) {
\r
728 switch (c * x.sign) {
\r
730 z = sub(x.data, x.GetWordCount(), y.data, y.GetWordCount());
\r
733 z = sub(y.data, y.GetWordCount(), x.data, x.GetWordCount());
\r
738 return new BigInteger(c, z);
\r
740 uint[] z = add0(x.data, x.GetWordCount(), y.data, y.GetWordCount());
\r
741 return new BigInteger(c, z);
\r
745 public static BigInteger Multiply(BigInteger x, BigInteger y) {
\r
749 public static BigInteger operator *(BigInteger x, BigInteger y) {
\r
750 if (object.ReferenceEquals(x, null)) {
\r
751 throw new ArgumentNullException("x");
\r
753 if (object.ReferenceEquals(y, null)) {
\r
754 throw new ArgumentNullException("y");
\r
756 int xl = x.GetWordCount();
\r
757 int yl = y.GetWordCount();
\r
759 uint[] xd = x.data, yd = y.data, zd = new uint[zl];
\r
761 for (int xi = 0; xi < xl; xi++) {
\r
765 for (int yi = 0; yi < yl; yi++) {
\r
766 carry = carry + ((ulong)xv) * yd[yi] + zd[zi];
\r
767 zd[zi++] = (uint)carry;
\r
768 carry >>= BitsPerDigit;
\r
770 while (carry != 0) {
\r
772 zd[zi++] = (uint)carry;
\r
773 carry >>= BitsPerDigit;
\r
777 return new BigInteger(x.sign * y.sign, zd);
\r
780 public static BigInteger Divide(BigInteger x, BigInteger y) {
\r
784 public static BigInteger operator /(BigInteger x, BigInteger y) {
\r
786 return DivRem(x, y, out dummy);
\r
789 public static BigInteger Mod(BigInteger x, BigInteger y) {
\r
793 public static BigInteger operator %(BigInteger x, BigInteger y) {
\r
795 DivRem(x, y, out ret);
\r
799 private static int GetNormalizeShift(uint value) {
\r
802 if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; }
\r
803 if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; }
\r
804 if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; }
\r
805 if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; }
\r
806 if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; }
\r
811 [Conditional("DEBUG")]
\r
812 [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Scripting.Math.BigInteger")]
\r
813 private static void TestNormalize(uint[] u, uint[] un, int shift) {
\r
814 BigInteger i = new BigInteger(1, u);
\r
815 BigInteger j = new BigInteger(1, un);
\r
816 BigInteger k = j >> shift;
\r
818 Debug.Assert(i == k);
\r
821 [Conditional("DEBUG")]
\r
822 private static void TestDivisionStep(uint[] un, uint[] vn, uint[] q, uint[] u, uint[] v) {
\r
823 int n = GetLength(v);
\r
824 int shift = GetNormalizeShift(v[n - 1]);
\r
826 BigInteger uni = new BigInteger(1, un);
\r
827 BigInteger vni = new BigInteger(1, vn);
\r
828 BigInteger qi = new BigInteger(1, q);
\r
829 BigInteger ui = new BigInteger(1, u);
\r
831 BigInteger expected = vni * qi + uni;
\r
832 BigInteger usi = ui << shift;
\r
834 Debug.Assert(expected == usi);
\r
837 [Conditional("DEBUG")]
\r
838 [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Scripting.Math.BigInteger")]
\r
839 private static void TestResult(uint[] u, uint[] v, uint[] q, uint[] r) {
\r
840 BigInteger ui = new BigInteger(1, u);
\r
841 BigInteger vi = new BigInteger(1, v);
\r
842 BigInteger qi = new BigInteger(1, q);
\r
843 BigInteger ri = new BigInteger(1, r);
\r
845 BigInteger viqi = vi * qi;
\r
846 BigInteger expected = viqi + ri;
\r
847 Debug.Assert(ui == expected);
\r
848 Debug.Assert(ri < vi);
\r
851 private static void Normalize(uint[] u, int l, uint[] un, int shift) {
\r
852 Debug.Assert(un.Length == l || un.Length == l + 1);
\r
853 Debug.Assert(un.Length == l + 1 || ((u[l - 1] << shift) >> shift) == u[l - 1]);
\r
854 Debug.Assert(0 <= shift && shift < 32);
\r
859 int rshift = BitsPerDigit - shift;
\r
860 for (i = 0; i < l; i++) {
\r
862 un[i] = (ui << shift) | carry;
\r
863 carry = ui >> rshift;
\r
866 for (i = 0; i < l; i++) {
\r
871 while (i < un.Length) {
\r
876 Debug.Assert(l == un.Length - 1);
\r
880 TestNormalize(u, un, shift);
\r
883 private static void Unnormalize(uint[] un, out uint[] r, int shift) {
\r
884 Debug.Assert(0 <= shift && shift < 32);
\r
886 int length = GetLength(un);
\r
887 r = new uint[length];
\r
890 int lshift = 32 - shift;
\r
892 for (int i = length - 1; i >= 0; i--) {
\r
894 r[i] = (uni >> shift) | carry;
\r
895 carry = (uni << lshift);
\r
898 for (int i = 0; i < length; i++) {
\r
903 TestNormalize(r, un, shift);
\r
906 private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r) {
\r
907 int m = GetLength(u);
\r
908 int n = GetLength(v);
\r
912 throw new DivideByZeroException();
\r
915 // Divide by single digit
\r
922 for (int j = m - 1; j >= 0; j--) {
\r
926 ulong div = rem / v0;
\r
931 } else if (m >= n) {
\r
932 int shift = GetNormalizeShift(v[n - 1]);
\r
934 uint[] un = new uint[m + 1];
\r
935 uint[] vn = new uint[n];
\r
937 Normalize(u, m, un, shift);
\r
938 Normalize(v, n, vn, shift);
\r
940 q = new uint[m - n + 1];
\r
943 TestDivisionStep(un, vn, q, u, v);
\r
945 // Main division loop
\r
947 for (int j = m - n; j >= 0; j--) {
\r
951 rr = Base * un[j + n] + un[j + n - 1];
\r
952 qq = rr / vn[n - 1];
\r
953 rr -= qq * vn[n - 1];
\r
955 Debug.Assert((Base * un[j + n] + un[j + n - 1]) == qq * vn[n - 1] + rr);
\r
958 // Estimate too big ?
\r
960 if ((qq >= Base) || (qq * vn[n - 2] > (rr * Base + un[j + n - 2]))) {
\r
962 rr += (ulong)vn[n - 1];
\r
963 if (rr < Base) continue;
\r
968 Debug.Assert((Base * un[j + n] + un[j + n - 1]) == qq * vn[n - 1] + rr);
\r
970 // Multiply and subtract
\r
974 for (i = 0; i < n; i++) {
\r
975 ulong p = vn[i] * qq;
\r
976 t = (long)un[i + j] - (long)(uint)p - b;
\r
977 un[i + j] = (uint)t;
\r
980 Debug.Assert(t == 0 || t == -1 || t == -2);
\r
983 t = (long)un[j + n] - b;
\r
984 un[j + n] = (uint)t;
\r
986 // Store the calculated value
\r
990 // Add back vn[0..n] to un[j..j+n]
\r
995 for (i = 0; i < n; i++) {
\r
996 c = (ulong)vn[i] + un[j + i] + c;
\r
997 un[j + i] = (uint)c;
\r
1000 c += (ulong)un[j + n];
\r
1001 un[j + n] = (uint)c;
\r
1004 TestDivisionStep(un, vn, q, u, v);
\r
1007 Unnormalize(un, out r, shift);
\r
1009 // Test normalized value ... Call TestNormalize
\r
1010 // only pass the values in different order.
\r
1012 TestNormalize(r, un, shift);
\r
1014 q = new uint[] { 0 };
\r
1018 TestResult(u, v, q, r);
\r
1021 public static BigInteger DivRem(BigInteger x, BigInteger y, out BigInteger remainder) {
\r
1022 if (object.ReferenceEquals(x, null)) {
\r
1023 throw new ArgumentNullException("x");
\r
1025 if (object.ReferenceEquals(y, null)) {
\r
1026 throw new ArgumentNullException("y");
\r
1032 DivModUnsigned(x.data, y.data, out q, out r);
\r
1034 remainder = new BigInteger(x.sign, r);
\r
1035 return new BigInteger(x.sign * y.sign, q);
\r
1038 private static uint extend(uint v, ref bool seenNonZero) {
\r
1039 if (seenNonZero) {
\r
1045 seenNonZero = true;
\r
1051 private static uint getOne(bool isNeg, uint[] data, int i, ref bool seenNonZero) {
\r
1052 if (i < data.Length) {
\r
1053 uint ret = data[i];
\r
1054 return isNeg ? extend(ret, ref seenNonZero) : ret;
\r
1056 return isNeg ? uint.MaxValue : 0;
\r
1061 /// Do an in-place twos complement of d and also return the result.
\r
1063 private static uint[] makeTwosComplement(uint[] d) {
\r
1064 // first do complement and +1 as long as carry is needed
\r
1067 for (; i < d.Length; i++) {
\r
1070 if (v != 0) { i++; break; }
\r
1074 // now ones complement is sufficient
\r
1075 for (; i < d.Length; i++) {
\r
1079 //??? this is weird
\r
1080 d = resize(d, d.Length + 1);
\r
1081 d[d.Length - 1] = 1;
\r
1086 public static BigInteger BitwiseAnd(BigInteger x, BigInteger y) {
\r
1090 public static BigInteger operator &(BigInteger x, BigInteger y) {
\r
1091 if (object.ReferenceEquals(x, null)) {
\r
1092 throw new ArgumentNullException("x");
\r
1094 if (object.ReferenceEquals(y, null)) {
\r
1095 throw new ArgumentNullException("y");
\r
1097 int xl = x.GetWordCount(), yl = y.GetWordCount();
\r
1098 uint[] xd = x.data, yd = y.data;
\r
1100 int zl = System.Math.Max(xl, yl);
\r
1101 uint[] zd = new uint[zl];
\r
1103 bool negx = x.sign == -1, negy = y.sign == -1;
\r
1104 bool seenNonZeroX = false, seenNonZeroY = false;
\r
1105 for (int i = 0; i < zl; i++) {
\r
1106 uint xu = getOne(negx, xd, i, ref seenNonZeroX);
\r
1107 uint yu = getOne(negy, yd, i, ref seenNonZeroY);
\r
1111 if (negx && negy) {
\r
1113 return new BigInteger(-1, makeTwosComplement(zd));
\r
1114 } else if (negx || negy) {
\r
1115 return new BigInteger(+1, zd);
\r
1117 return new BigInteger(+1, zd);
\r
1121 public static BigInteger BitwiseOr(BigInteger x, BigInteger y) {
\r
1125 public static BigInteger operator |(BigInteger x, BigInteger y) {
\r
1126 if (object.ReferenceEquals(x, null)) {
\r
1127 throw new ArgumentNullException("x");
\r
1129 if (object.ReferenceEquals(y, null)) {
\r
1130 throw new ArgumentNullException("y");
\r
1132 int xl = x.GetWordCount(), yl = y.GetWordCount();
\r
1133 uint[] xd = x.data, yd = y.data;
\r
1135 int zl = System.Math.Max(xl, yl);
\r
1136 uint[] zd = new uint[zl];
\r
1138 bool negx = x.sign == -1, negy = y.sign == -1;
\r
1139 bool seenNonZeroX = false, seenNonZeroY = false;
\r
1140 for (int i = 0; i < zl; i++) {
\r
1141 uint xu = getOne(negx, xd, i, ref seenNonZeroX);
\r
1142 uint yu = getOne(negy, yd, i, ref seenNonZeroY);
\r
1146 if (negx && negy) {
\r
1147 return new BigInteger(-1, makeTwosComplement(zd));
\r
1148 } else if (negx || negy) {
\r
1149 return new BigInteger(-1, makeTwosComplement(zd));
\r
1151 return new BigInteger(+1, zd);
\r
1155 public static BigInteger Xor(BigInteger x, BigInteger y) {
\r
1159 public static BigInteger operator ^(BigInteger x, BigInteger y) {
\r
1160 if (object.ReferenceEquals(x, null)) {
\r
1161 throw new ArgumentNullException("x");
\r
1163 if (object.ReferenceEquals(y, null)) {
\r
1164 throw new ArgumentNullException("y");
\r
1166 int xl = x.GetWordCount(), yl = y.GetWordCount();
\r
1167 uint[] xd = x.data, yd = y.data;
\r
1169 int zl = System.Math.Max(xl, yl);
\r
1170 uint[] zd = new uint[zl];
\r
1172 bool negx = x.sign == -1, negy = y.sign == -1;
\r
1173 bool seenNonZeroX = false, seenNonZeroY = false;
\r
1174 for (int i = 0; i < zl; i++) {
\r
1175 uint xu = getOne(negx, xd, i, ref seenNonZeroX);
\r
1176 uint yu = getOne(negy, yd, i, ref seenNonZeroY);
\r
1180 if (negx && negy) {
\r
1181 return new BigInteger(+1, zd);
\r
1182 } else if (negx || negy) {
\r
1183 return new BigInteger(-1, makeTwosComplement(zd));
\r
1185 return new BigInteger(+1, zd);
\r
1189 public static BigInteger LeftShift(BigInteger x, int shift) {
\r
1190 return x << shift;
\r
1193 public static BigInteger operator <<(BigInteger x, int shift) {
\r
1194 if (object.ReferenceEquals(x, null)) {
\r
1195 throw new ArgumentNullException("x");
\r
1197 if (shift == 0) return x;
\r
1198 else if (shift < 0) return x >> -shift;
\r
1200 int digitShift = shift / BitsPerDigit;
\r
1201 int smallShift = shift - (digitShift * BitsPerDigit);
\r
1203 int xl = x.GetWordCount();
\r
1204 uint[] xd = x.data;
\r
1205 int zl = xl + digitShift + 1;
\r
1206 uint[] zd = new uint[zl];
\r
1208 if (smallShift == 0) {
\r
1209 for (int i = 0; i < xl; i++) {
\r
1210 zd[i + digitShift] = xd[i];
\r
1213 int carryShift = BitsPerDigit - smallShift;
\r
1216 for (i = 0; i < xl; i++) {
\r
1218 zd[i + digitShift] = rot << smallShift | carry;
\r
1219 carry = rot >> carryShift;
\r
1221 zd[i + digitShift] = carry;
\r
1223 return new BigInteger(x.sign, zd);
\r
1226 public static BigInteger RightShift(BigInteger x, int shift) {
\r
1227 return x >> shift;
\r
1230 public static BigInteger operator >>(BigInteger x, int shift) {
\r
1231 if (object.ReferenceEquals(x, null)) {
\r
1232 throw new ArgumentNullException("x");
\r
1234 if (shift == 0) return x;
\r
1235 else if (shift < 0) return x << -shift;
\r
1237 int digitShift = shift / BitsPerDigit;
\r
1238 int smallShift = shift - (digitShift * BitsPerDigit);
\r
1240 int xl = x.GetWordCount();
\r
1241 uint[] xd = x.data;
\r
1242 int zl = xl - digitShift;
\r
1243 if (zl < 0) zl = 0;
\r
1244 uint[] zd = new uint[zl];
\r
1246 if (smallShift == 0) {
\r
1247 for (int i = xl - 1; i >= digitShift; i--) {
\r
1248 zd[i - digitShift] = xd[i];
\r
1251 int carryShift = BitsPerDigit - smallShift;
\r
1253 for (int i = xl - 1; i >= digitShift; i--) {
\r
1255 zd[i - digitShift] = rot >> smallShift | carry;
\r
1256 carry = rot << carryShift;
\r
1259 return new BigInteger(x.sign, zd);
\r
1262 public static BigInteger Negate(BigInteger x) {
\r
1266 public static BigInteger operator -(BigInteger x) {
\r
1267 if (object.ReferenceEquals(x, null)) {
\r
1268 throw new ArgumentNullException("x");
\r
1270 return new BigInteger(-x.sign, x.data);
\r
1273 public BigInteger OnesComplement() {
\r
1277 public static BigInteger operator ~(BigInteger x) {
\r
1278 if (object.ReferenceEquals(x, null)) {
\r
1279 throw new ArgumentNullException("x");
\r
1281 return -(x + One);
\r
1284 public BigInteger Abs() {
\r
1285 if (this.sign == -1) return -this;
\r
1289 public BigInteger Power(int exp) {
\r
1290 if (exp == 0) return One;
\r
1292 throw new ArgumentOutOfRangeException("exp", "exp must be >= 0");
\r
1294 BigInteger factor = this;
\r
1295 BigInteger result = One;
\r
1296 while (exp != 0) {
\r
1297 if ((exp & 1) != 0) result = result * factor;
\r
1298 if (exp == 1) break; // avoid costly factor.square()
\r
1299 factor = factor.Square();
\r
1305 public BigInteger ModPow(int power, BigInteger mod) {
\r
1306 if (object.ReferenceEquals(mod, null)) {
\r
1307 throw new ArgumentNullException("mod");
\r
1311 throw new ArgumentOutOfRangeException("power", "power must be >= 0");
\r
1313 BigInteger factor = this;
\r
1314 BigInteger result = One % mod; // Handle special case of power=0, mod=1
\r
1315 while (power != 0) {
\r
1316 if ((power & 1) != 0) {
\r
1317 result = result * factor;
\r
1318 result = result % mod;
\r
1320 if (power == 1) break; // avoid costly factor.Square()
\r
1321 factor = factor.Square();
\r
1322 factor = factor % mod;
\r
1328 public BigInteger ModPow(BigInteger power, BigInteger mod) {
\r
1329 if (object.ReferenceEquals(power, null)) {
\r
1330 throw new ArgumentNullException("power");
\r
1332 if (object.ReferenceEquals(mod, null)) {
\r
1333 throw new ArgumentNullException("mod");
\r
1337 throw new ArgumentOutOfRangeException("power", "power must be >= 0");
\r
1340 BigInteger factor = this;
\r
1341 BigInteger result = One % mod;
\r
1342 while (power != Zero) {
\r
1343 if (power.IsOdd()) {
\r
1344 result = result * factor;
\r
1345 result = result % mod;
\r
1347 if (power == One) break; // avoid costly factor.Square()
\r
1348 factor = factor.Square();
\r
1349 factor = factor % mod;
\r
1355 public BigInteger Square() {
\r
1356 return this * this;
\r
1359 public override string ToString() {
\r
1360 return ToString(10);
\r
1363 // generated by scripts/radix_generator.py
\r
1364 private static readonly uint[] maxCharsPerDigit = { 0, 0, 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 };
\r
1365 private static readonly uint[] groupRadixValues = { 0, 0, 2147483648, 3486784401, 1073741824, 1220703125, 2176782336, 1977326743, 1073741824, 3486784401, 1000000000, 2357947691, 429981696, 815730721, 1475789056, 2562890625, 268435456, 410338673, 612220032, 893871739, 1280000000, 1801088541, 2494357888, 3404825447, 191102976, 244140625, 308915776, 387420489, 481890304, 594823321, 729000000, 887503681, 1073741824, 1291467969, 1544804416, 1838265625, 2176782336 };
\r
1367 public static ArgumentOutOfRangeException MakeArgumentOutOfRangeException(string paramName, object actualValue, string message) {
\r
1368 return new ArgumentOutOfRangeException(paramName, string.Format("{0} (actual value is '{1}')", message, actualValue));
\r
1371 internal static string BigIntegerToString(uint[] d, int sign, int radix) {
\r
1373 throw MakeArgumentOutOfRangeException("radix", radix, "radix must be >= 2");
\r
1376 throw MakeArgumentOutOfRangeException("radix", radix, "radix must be <= 36");
\r
1379 int dl = d.Length;
\r
1384 List<uint> digitGroups = new List<uint>();
\r
1386 uint groupRadix = groupRadixValues[radix];
\r
1388 uint rem = div(d, ref dl, groupRadix);
\r
1389 digitGroups.Add(rem);
\r
1392 StringBuilder ret = new StringBuilder();
\r
1397 int digitIndex = digitGroups.Count - 1;
\r
1399 char[] tmpDigits = new char[maxCharsPerDigit[radix]];
\r
1401 AppendRadix((uint)digitGroups[digitIndex--], (uint)radix, tmpDigits, ret, false);
\r
1402 while (digitIndex >= 0) {
\r
1403 AppendRadix((uint)digitGroups[digitIndex--], (uint)radix, tmpDigits, ret, true);
\r
1405 return ret.Length == 0 ? "0" : ret.ToString();
\r
1408 private static uint div(uint[] n, ref int nl, uint d) {
\r
1411 bool seenNonZero = false;
\r
1412 while (--i >= 0) {
\r
1413 rem <<= BitsPerDigit;
\r
1415 uint v = (uint)(rem / d);
\r
1418 if (!seenNonZero) nl--;
\r
1420 seenNonZero = true;
\r
1427 private static void AppendRadix(uint rem, uint radix, char[] tmp, StringBuilder buf, bool leadingZeros) {
\r
1428 const string symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
\r
1430 int digits = tmp.Length;
\r
1432 while (i > 0 && (leadingZeros || rem != 0)) {
\r
1433 uint digit = rem % radix;
\r
1435 tmp[--i] = symbols[(int)digit];
\r
1437 if (leadingZeros) buf.Append(tmp);
\r
1438 else buf.Append(tmp, i, digits - i);
\r
1441 public string ToString(int radix) {
\r
1442 return BigIntegerToString(copy(data), sign, radix);
\r
1445 public override int GetHashCode() {
\r
1446 // The Object.GetHashCode function needs to be consistent with the Object.Equals function.
\r
1447 // Languages that build on top of this may have a more flexible equality function and
\r
1448 // so may not be able to use this hash function directly.
\r
1449 // For example, Python allows BigInteger(10) == int32(10), so hashing a BigInt over the Int32
\r
1450 // domain should return the same value as a hash of the Int32.
\r
1452 // If this is in the int32 range, this hash function returns the integer.
\r
1453 if (data.Length == 0) {
\r
1457 // Add up all uints. We want to incorporate all bits to get good hash distribution.
\r
1459 foreach (uint x in data) {
\r
1460 total = unchecked(total + x);
\r
1463 int hash = unchecked((int)total);
\r
1465 // The sign is not part of the data array, so explicitly incorporate that.
\r
1466 // This is also needed to ensure that hash(-x) == -x for int32.
\r
1467 if (IsNegative()) {
\r
1468 return unchecked(-hash);
\r
1474 public override bool Equals(object obj) {
\r
1475 return Equals(obj as BigInteger);
\r
1478 public bool Equals(BigInteger other) {
\r
1479 if (object.ReferenceEquals(other, null)) return false;
\r
1480 return this == other;
\r
1484 public bool IsNegative() {
\r
1488 public bool IsZero() {
\r
1492 public bool IsPositive() {
\r
1496 private bool IsOdd() {
\r
1497 // must have the lowest-order bit set to 1
\r
1498 return (data != null && data.Length > 0 && ((data[0] & 1) != 0));
\r
1502 public double Log(Double newBase) {
\r
1503 if (IsNegative() || newBase == 1.0D || this == Zero || (newBase == 0.0D && this != One)) {
\r
1504 return Double.NaN;
\r
1505 } else if (newBase == Double.PositiveInfinity) {
\r
1506 return this == One ? 0.0D : Double.NaN;
\r
1509 int length = GetLength(data) - 1;
\r
1510 int bitCount = -1;
\r
1511 for (int curBit = 31; curBit >= 0; curBit--) {
\r
1512 if ((data[length] & (1 << curBit)) != 0) {
\r
1513 bitCount = curBit + length * 32;
\r
1518 long bitlen = bitCount;
\r
1519 Double c = 0, d = 1;
\r
1521 BigInteger testBit = BigInteger.One;
\r
1522 long tempBitlen = bitlen;
\r
1523 while (tempBitlen > Int32.MaxValue) {
\r
1524 testBit = testBit << Int32.MaxValue;
\r
1525 tempBitlen -= Int32.MaxValue;
\r
1527 testBit = testBit << (int)tempBitlen;
\r
1529 for (long curbit = bitlen; curbit >= 0; --curbit) {
\r
1530 if ((this & testBit) != BigInteger.Zero)
\r
1533 testBit = testBit >> 1;
\r
1535 return (System.Math.Log(c) + System.Math.Log(2) * bitlen) / System.Math.Log(newBase);
\r
1539 /// Calculates the natural logarithm of the BigInteger.
\r
1541 public double Log() {
\r
1542 return Log(System.Math.E);
\r
1546 /// Calculates log base 10 of a BigInteger.
\r
1548 public double Log10() {
\r
1552 #region IComparable Members
\r
1554 public int CompareTo(object obj) {
\r
1555 if (obj == null) {
\r
1558 BigInteger o = obj as BigInteger;
\r
1559 if (object.ReferenceEquals(o, null)) {
\r
1560 throw new ArgumentException("expected integer");
\r
1562 return Compare(this, o);
\r
1567 #region IConvertible Members
\r
1569 public TypeCode GetTypeCode() {
\r
1570 return TypeCode.Object;
\r
1573 public bool ToBoolean(IFormatProvider provider) {
\r
1574 return this != Zero;
\r
1577 public byte ToByte(IFormatProvider provider) {
\r
1579 if (AsUInt32(out ret) && (ret & ~0xFF) == 0) {
\r
1582 throw new OverflowException("big integer won't fit into byte");
\r
1586 /// Return the value of this BigInteger as a little-endian twos-complement
\r
1587 /// byte array, using the fewest number of bytes possible. If the value is zero,
\r
1588 /// return an array of one byte whose element is 0x00.
\r
1590 public byte[] ToByteArray() {
\r
1591 // We could probably make this more efficient by eliminating one of the passes.
\r
1592 // The current code does one pass for uint array -> byte array conversion,
\r
1593 // and then a another pass to remove unneeded bytes at the top of the array.
\r
1594 if (0 == sign) return new byte[] { 0 };
\r
1600 dwords = (uint[])this.data.Clone();
\r
1601 makeTwosComplement(dwords);
\r
1604 dwords = this.data;
\r
1608 byte[] bytes = new byte[4 * dwords.Length];
\r
1611 for (int i = 0; i < dwords.Length; i++) {
\r
1612 dword = dwords[i];
\r
1613 for (int j = 0; j < 4; j++) {
\r
1614 bytes[curByte++] = (byte)(dword & 0xff);
\r
1619 // find highest significant byte
\r
1621 for (msb = bytes.Length - 1; msb > 0; msb--) {
\r
1622 if (bytes[msb] != highByte) break;
\r
1624 // ensure high bit is 0 if positive, 1 if negative
\r
1625 bool needExtraByte = (bytes[msb] & 0x80) != (highByte & 0x80);
\r
1627 byte[] trimmedBytes = new byte[msb + 1 + (needExtraByte ? 1 : 0)];
\r
1628 Array.Copy(bytes, trimmedBytes, msb + 1);
\r
1630 if (needExtraByte) trimmedBytes[trimmedBytes.Length - 1] = highByte;
\r
1632 return trimmedBytes;
\r
1635 public char ToChar(IFormatProvider provider) {
\r
1637 if (AsInt32(out ret) && (ret <= Char.MaxValue) && (ret >= Char.MinValue)) {
\r
1640 throw new OverflowException("big integer won't fit into char");
\r
1643 public DateTime ToDateTime(IFormatProvider provider) {
\r
1644 throw new NotImplementedException();
\r
1647 public decimal ToDecimal(IFormatProvider provider) {
\r
1649 if (AsDecimal(out ret)) return ret;
\r
1650 throw new OverflowException("big integer won't fit into decimal");
\r
1653 public double ToDouble(IFormatProvider provider) {
\r
1654 return ToFloat64();
\r
1657 public short ToInt16(IFormatProvider provider) {
\r
1659 if (AsInt32(out ret) && (ret <= short.MaxValue) && (ret >= short.MinValue)) {
\r
1660 return (short)ret;
\r
1662 throw new OverflowException("big integer won't fit into short");
\r
1665 public int ToInt32(IFormatProvider provider) {
\r
1667 if (AsInt32(out ret)) {
\r
1670 throw new OverflowException("big integer won't fit into int");
\r
1673 public long ToInt64(IFormatProvider provider) {
\r
1675 if (AsInt64(out ret)) {
\r
1678 throw new OverflowException("big integer won't fit into long");
\r
1681 [CLSCompliant(false)]
\r
1682 public sbyte ToSByte(IFormatProvider provider) {
\r
1684 if (AsInt32(out ret) && (ret <= sbyte.MaxValue) && (ret >= sbyte.MinValue)) {
\r
1685 return (sbyte)ret;
\r
1687 throw new OverflowException("big integer won't fit into sbyte");
\r
1690 public float ToSingle(IFormatProvider provider) {
\r
1691 return checked((float)ToDouble(provider));
\r
1694 public string ToString(IFormatProvider provider) {
\r
1695 return ToString();
\r
1698 public object ToType(Type conversionType, IFormatProvider provider) {
\r
1699 if (conversionType == typeof(BigInteger)) {
\r
1702 throw new NotImplementedException();
\r
1705 [CLSCompliant(false)]
\r
1706 public ushort ToUInt16(IFormatProvider provider) {
\r
1708 if (AsUInt32(out ret) && ret <= ushort.MaxValue) {
\r
1709 return (ushort)ret;
\r
1711 throw new OverflowException("big integer won't fit into ushort");
\r
1714 [CLSCompliant(false)]
\r
1715 public uint ToUInt32(IFormatProvider provider) {
\r
1717 if (AsUInt32(out ret)) {
\r
1720 throw new OverflowException("big integer won't fit into uint");
\r
1723 [CLSCompliant(false)]
\r
1724 public ulong ToUInt64(IFormatProvider provider) {
\r
1726 if (AsUInt64(out ret)) {
\r
1729 throw new OverflowException("big integer won't fit into ulong");
\r
1734 #region IFormattable Members
\r
1736 string IFormattable.ToString(string format, IFormatProvider formatProvider) {
\r
1737 if (format == null) return this.ToString();
\r
1739 switch (format[0]) {
\r
1742 if (format.Length > 1) {
\r
1743 int precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
\r
1744 string baseStr = ToString(10);
\r
1745 if (baseStr.Length < precision) {
\r
1746 string additional = new String('0', precision - baseStr.Length);
\r
1747 if (baseStr[0] != '-') {
\r
1748 return additional + baseStr;
\r
1750 return "-" + additional + baseStr.Substring(1);
\r
1755 return ToString(10);
\r
1758 StringBuilder res = new StringBuilder(ToString(16));
\r
1759 if (format[0] == 'x') {
\r
1760 for (int i = 0; i < res.Length; i++) {
\r
1761 if (res[i] >= 'A' && res[i] <= 'F') {
\r
1762 res[i] = Char.ToLower(res[i], CultureInfo.InvariantCulture);
\r
1767 if (format.Length > 1) {
\r
1768 int precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat);
\r
1769 if (res.Length < precision) {
\r
1770 string additional = new String('0', precision - res.Length);
\r
1771 if (res[0] != '-') {
\r
1772 res.Insert(0, additional);
\r
1774 res.Insert(1, additional);
\r
1779 return res.ToString();
\r
1781 throw new NotImplementedException("format not implemented");
\r