PageRenderTime 131ms CodeModel.GetById 31ms RepoModel.GetById 5ms app.codeStats 0ms

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

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