PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

#
C# | 612 lines | 455 code | 123 blank | 34 comment | 40 complexity | 5d23ff04580970a542ef6b57353999ce 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. using BigInt = System.Numerics.BigInteger;
  25. namespace Microsoft.Scripting.Math {
  26. /// <summary>
  27. /// arbitrary precision integers
  28. /// </summary>
  29. [Serializable]
  30. public sealed class BigInteger : IFormattable, IComparable, IEquatable<BigInteger> {
  31. internal readonly BigInt Value;
  32. [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  33. public static readonly BigInteger Zero = new BigInteger((BigInt)0);
  34. [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  35. public static readonly BigInteger One = new BigInteger((BigInt)1);
  36. public BigInteger(BigInt value) {
  37. Value = value;
  38. }
  39. [CLSCompliant(false)]
  40. public static BigInteger Create(ulong v) {
  41. return new BigInteger(new BigInt(v));
  42. }
  43. [CLSCompliant(false)]
  44. public static BigInteger Create(uint v) {
  45. return new BigInteger(new BigInt(v));
  46. }
  47. public static BigInteger Create(long v) {
  48. return new BigInteger(new BigInt(v));
  49. }
  50. public static BigInteger Create(int v) {
  51. return new BigInteger(new BigInt(v));
  52. }
  53. public static BigInteger Create(decimal v) {
  54. return new BigInteger(new BigInt(v));
  55. }
  56. public static BigInteger Create(byte[] v) {
  57. return new BigInteger(v);
  58. }
  59. public static BigInteger Create(double v) {
  60. return new BigInteger(new BigInt(v));
  61. }
  62. public static implicit operator BigInteger(byte i) {
  63. return new BigInteger((BigInt)i);
  64. }
  65. [CLSCompliant(false)]
  66. public static implicit operator BigInteger(sbyte i) {
  67. return new BigInteger((BigInt)i);
  68. }
  69. public static implicit operator BigInteger(short i) {
  70. return new BigInteger((BigInt)i);
  71. }
  72. [CLSCompliant(false)]
  73. public static implicit operator BigInteger(ushort i) {
  74. return new BigInteger((BigInt)i);
  75. }
  76. [CLSCompliant(false)]
  77. public static implicit operator BigInteger(uint i) {
  78. return new BigInteger((BigInt)i);
  79. }
  80. public static implicit operator BigInteger(int i) {
  81. return new BigInteger((BigInt)i);
  82. }
  83. [CLSCompliant(false)]
  84. public static implicit operator BigInteger(ulong i) {
  85. return new BigInteger((BigInt)i);
  86. }
  87. public static implicit operator BigInteger(long i) {
  88. return new BigInteger((BigInt)i);
  89. }
  90. public static implicit operator BigInteger(decimal self) {
  91. return new BigInteger((BigInt)self);
  92. }
  93. public static explicit operator BigInteger(double self) {
  94. return new BigInteger((BigInt)self);
  95. }
  96. public static explicit operator BigInteger(float self) {
  97. return new BigInteger((BigInt)self);
  98. }
  99. public static explicit operator double(BigInteger self) {
  100. return (double)self.Value;
  101. }
  102. public static explicit operator float(BigInteger self) {
  103. return (float)self.Value;
  104. }
  105. public static explicit operator decimal(BigInteger self) {
  106. return (decimal)self.Value;
  107. }
  108. public static explicit operator byte(BigInteger self) {
  109. return (byte)self.Value;
  110. }
  111. [CLSCompliant(false)]
  112. public static explicit operator sbyte(BigInteger self) {
  113. return (sbyte)self.Value;
  114. }
  115. [CLSCompliant(false)]
  116. public static explicit operator UInt16(BigInteger self) {
  117. return (UInt16)self.Value;
  118. }
  119. public static explicit operator Int16(BigInteger self) {
  120. return (Int16)self.Value;
  121. }
  122. [CLSCompliant(false)]
  123. public static explicit operator UInt32(BigInteger self) {
  124. return (UInt32)self.Value;
  125. }
  126. public static explicit operator Int32(BigInteger self) {
  127. return (Int32)self.Value;
  128. }
  129. public static explicit operator Int64(BigInteger self) {
  130. return (Int64)self.Value;
  131. }
  132. [CLSCompliant(false)]
  133. public static explicit operator UInt64(BigInteger self) {
  134. return (UInt64)self.Value;
  135. }
  136. public static implicit operator BigInteger(BigInt value) {
  137. return new BigInteger(value);
  138. }
  139. public static implicit operator BigInt(BigInteger value) {
  140. return value.Value;
  141. }
  142. public BigInteger(BigInteger copy) {
  143. if (object.ReferenceEquals(copy, null)) {
  144. throw new ArgumentNullException("copy");
  145. }
  146. Value = copy.Value;
  147. }
  148. public BigInteger(byte[] data) {
  149. ContractUtils.RequiresNotNull(data, "data");
  150. Value = new BigInt(data);
  151. }
  152. public BigInteger(int sign, byte[] data) {
  153. ContractUtils.RequiresNotNull(data, "data");
  154. ContractUtils.Requires(sign >= -1 && sign <= +1, "sign");
  155. Value = new BigInt(data);
  156. if (sign < 0) {
  157. Value = -Value;
  158. }
  159. }
  160. [CLSCompliant(false)]
  161. public BigInteger(int sign, uint[] data) {
  162. ContractUtils.RequiresNotNull(data, "data");
  163. ContractUtils.Requires(sign >= -1 && sign <= +1, "sign");
  164. int length = GetLength(data);
  165. ContractUtils.Requires(length == 0 || sign != 0, "sign");
  166. if (length == 0) {
  167. Value = 0;
  168. return;
  169. }
  170. bool highest = (data[length - 1] & 0x80000000) != 0;
  171. byte[] bytes = new byte[length * 4 + (highest ? 1 : 0)];
  172. int j = 0;
  173. for (int i = 0; i < length; i++) {
  174. ulong w = data[i];
  175. bytes[j++] = (byte)(w & 0xff);
  176. bytes[j++] = (byte)((w >> 8) & 0xff);
  177. bytes[j++] = (byte)((w >> 16) & 0xff);
  178. bytes[j++] = (byte)((w >> 24) & 0xff);
  179. }
  180. Value = new BigInt(bytes);
  181. if (sign < 0) {
  182. Value = -Value;
  183. }
  184. }
  185. [CLSCompliant(false)]
  186. public uint[] GetWords() {
  187. return Value.GetWords();
  188. }
  189. public int GetBitCount() {
  190. return Value.GetBitCount();
  191. }
  192. public int GetWordCount() {
  193. return Value.GetWordCount();
  194. }
  195. public int GetByteCount() {
  196. return Value.GetByteCount();
  197. }
  198. /// <summary>
  199. /// Return the sign of this BigInteger: -1, 0, or 1.
  200. /// </summary>
  201. public int Sign {
  202. get {
  203. return Value.Sign;
  204. }
  205. }
  206. public bool AsInt64(out long ret) {
  207. if (Value >= Int64.MinValue && Value <= Int64.MaxValue) {
  208. ret = (long)Value;
  209. return true;
  210. }
  211. ret = 0;
  212. return false;
  213. }
  214. [CLSCompliant(false)]
  215. public bool AsUInt32(out uint ret) {
  216. if (Value >= UInt32.MinValue && Value <= UInt32.MaxValue) {
  217. ret = (UInt32)Value;
  218. return true;
  219. }
  220. ret = 0;
  221. return false;
  222. }
  223. [CLSCompliant(false)]
  224. public bool AsUInt64(out ulong ret) {
  225. if (Value >= UInt64.MinValue && Value <= UInt64.MaxValue) {
  226. ret = (UInt64)Value;
  227. return true;
  228. }
  229. ret = 0;
  230. return false;
  231. }
  232. public bool AsInt32(out int ret) {
  233. if (Value >= Int32.MinValue && Value <= Int32.MaxValue) {
  234. ret = (Int32)Value;
  235. return true;
  236. }
  237. ret = 0;
  238. return false;
  239. }
  240. [CLSCompliant(false)]
  241. public uint ToUInt32() {
  242. return (uint)Value;
  243. }
  244. public int ToInt32() {
  245. return (int)Value;
  246. }
  247. public decimal ToDecimal() {
  248. return (decimal)Value;
  249. }
  250. [CLSCompliant(false)]
  251. public ulong ToUInt64() {
  252. return (ulong)Value;
  253. }
  254. public long ToInt64() {
  255. return (long)Value;
  256. }
  257. private static int GetLength(uint[] data) {
  258. int ret = data.Length - 1;
  259. while (ret >= 0 && data[ret] == 0) ret--;
  260. return ret + 1;
  261. }
  262. public static int Compare(BigInteger x, BigInteger y) {
  263. return BigInt.Compare(x.Value, y.Value);
  264. }
  265. public static bool operator ==(BigInteger x, int y) {
  266. return x.Value == y;
  267. }
  268. public static bool operator !=(BigInteger x, int y) {
  269. return x.Value != y;
  270. }
  271. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
  272. public static bool operator ==(BigInteger x, double y) {
  273. if (object.ReferenceEquals(x, null)) {
  274. throw new ArgumentNullException("x");
  275. }
  276. // we can hold all double values, but not all double values
  277. // can hold BigInteger values, and we may lose precision. Convert
  278. // the double to a big int, then compare.
  279. if ((y % 1) != 0) return false; // not a whole number, can't be equal
  280. return x.Value == (BigInt)y;
  281. }
  282. public static bool operator ==(double x, BigInteger y) {
  283. return y == x;
  284. }
  285. public static bool operator !=(BigInteger x, double y) {
  286. return !(x == y);
  287. }
  288. public static bool operator !=(double x, BigInteger y) {
  289. return !(x == y);
  290. }
  291. public static bool operator ==(BigInteger x, BigInteger y) {
  292. return Compare(x, y) == 0;
  293. }
  294. public static bool operator !=(BigInteger x, BigInteger y) {
  295. return Compare(x, y) != 0;
  296. }
  297. public static bool operator <(BigInteger x, BigInteger y) {
  298. return Compare(x, y) < 0;
  299. }
  300. public static bool operator <=(BigInteger x, BigInteger y) {
  301. return Compare(x, y) <= 0;
  302. }
  303. public static bool operator >(BigInteger x, BigInteger y) {
  304. return Compare(x, y) > 0;
  305. }
  306. public static bool operator >=(BigInteger x, BigInteger y) {
  307. return Compare(x, y) >= 0;
  308. }
  309. public static BigInteger Add(BigInteger x, BigInteger y) {
  310. return x + y;
  311. }
  312. public static BigInteger operator +(BigInteger x, BigInteger y) {
  313. return new BigInteger(x.Value + y.Value);
  314. }
  315. public static BigInteger Subtract(BigInteger x, BigInteger y) {
  316. return x - y;
  317. }
  318. public static BigInteger operator -(BigInteger x, BigInteger y) {
  319. return new BigInteger(x.Value - y.Value);
  320. }
  321. public static BigInteger Multiply(BigInteger x, BigInteger y) {
  322. return x * y;
  323. }
  324. public static BigInteger operator *(BigInteger x, BigInteger y) {
  325. return new BigInteger(x.Value * y.Value);
  326. }
  327. public static BigInteger Divide(BigInteger x, BigInteger y) {
  328. return x / y;
  329. }
  330. public static BigInteger operator /(BigInteger x, BigInteger y) {
  331. BigInteger dummy;
  332. return DivRem(x, y, out dummy);
  333. }
  334. public static BigInteger Mod(BigInteger x, BigInteger y) {
  335. return x % y;
  336. }
  337. public static BigInteger operator %(BigInteger x, BigInteger y) {
  338. BigInteger ret;
  339. DivRem(x, y, out ret);
  340. return ret;
  341. }
  342. public static BigInteger DivRem(BigInteger x, BigInteger y, out BigInteger remainder) {
  343. BigInt rem;
  344. BigInt result = BigInt.DivRem(x.Value, y.Value, out rem);
  345. remainder = new BigInteger(rem);
  346. return new BigInteger(result);
  347. }
  348. public static BigInteger BitwiseAnd(BigInteger x, BigInteger y) {
  349. return x & y;
  350. }
  351. public static BigInteger operator &(BigInteger x, BigInteger y) {
  352. return new BigInteger(x.Value & y.Value);
  353. }
  354. public static BigInteger BitwiseOr(BigInteger x, BigInteger y) {
  355. return x | y;
  356. }
  357. public static BigInteger operator |(BigInteger x, BigInteger y) {
  358. return new BigInteger(x.Value | y.Value);
  359. }
  360. public static BigInteger Xor(BigInteger x, BigInteger y) {
  361. return x ^ y;
  362. }
  363. public static BigInteger operator ^(BigInteger x, BigInteger y) {
  364. return new BigInteger(x.Value ^ y.Value);
  365. }
  366. public static BigInteger LeftShift(BigInteger x, int shift) {
  367. return x << shift;
  368. }
  369. public static BigInteger operator <<(BigInteger x, int shift) {
  370. return new BigInteger(x.Value << shift);
  371. }
  372. public static BigInteger RightShift(BigInteger x, int shift) {
  373. return x >> shift;
  374. }
  375. public static BigInteger operator >>(BigInteger x, int shift) {
  376. return new BigInteger(x.Value >> shift);
  377. }
  378. public static BigInteger Negate(BigInteger x) {
  379. return -x;
  380. }
  381. public static BigInteger operator -(BigInteger x) {
  382. return new BigInteger(-x.Value);
  383. }
  384. public BigInteger OnesComplement() {
  385. return ~this;
  386. }
  387. public static BigInteger operator ~(BigInteger x) {
  388. return new BigInteger(~x.Value);
  389. }
  390. public BigInteger Abs() {
  391. return new BigInteger(BigInt.Abs(Value));
  392. }
  393. public BigInteger Power(int exp) {
  394. return new BigInteger(BigInt.Pow(Value, exp));
  395. }
  396. public BigInteger ModPow(int power, BigInteger mod) {
  397. return new BigInteger(BigInt.ModPow(Value, power, mod.Value));
  398. }
  399. public BigInteger ModPow(BigInteger power, BigInteger mod) {
  400. return new BigInteger(BigInt.ModPow(Value, power.Value, mod.Value));
  401. }
  402. public BigInteger Square() {
  403. return this * this;
  404. }
  405. #if !SILVERLIGHT
  406. public static BigInteger Parse(string str) {
  407. return new BigInteger(BigInt.Parse(str));
  408. }
  409. #endif
  410. public override string ToString() {
  411. return ToString(10);
  412. }
  413. public string ToString(int @base) {
  414. return MathUtils.BigIntegerToString(GetWords(), Sign, @base);
  415. }
  416. public override int GetHashCode() {
  417. return Value.GetHashCode();
  418. }
  419. public override bool Equals(object obj) {
  420. return Equals(obj as BigInteger);
  421. }
  422. public bool Equals(BigInteger other) {
  423. if (object.ReferenceEquals(other, null)) return false;
  424. return this == other;
  425. }
  426. public bool IsNegative() {
  427. return Value.Sign < 0;
  428. }
  429. public bool IsZero() {
  430. return Value.Sign == 0;
  431. }
  432. public bool IsPositive() {
  433. return Value.Sign > 0;
  434. }
  435. public bool IsEven {
  436. get { return Value.IsEven; }
  437. }
  438. public bool IsPowerOfTwo {
  439. get {
  440. return Value.IsPowerOfTwo;
  441. }
  442. }
  443. public double Log(Double newBase) {
  444. return BigInt.Log(Value, newBase);
  445. }
  446. /// <summary>
  447. /// Calculates the natural logarithm of the BigInteger.
  448. /// </summary>
  449. public double Log() {
  450. return BigInt.Log(Value);
  451. }
  452. /// <summary>
  453. /// Calculates log base 10 of a BigInteger.
  454. /// </summary>
  455. public double Log10() {
  456. return BigInt.Log10(Value);
  457. }
  458. #region IComparable Members
  459. public int CompareTo(object obj) {
  460. if (obj == null) {
  461. return 1;
  462. }
  463. BigInteger o = obj as BigInteger;
  464. if (object.ReferenceEquals(o, null)) {
  465. throw new ArgumentException("expected integer");
  466. }
  467. return Compare(this, o);
  468. }
  469. #endregion
  470. /// <summary>
  471. /// Return the value of this BigInteger as a little-endian twos-complement
  472. /// byte array, using the fewest number of bytes possible. If the value is zero,
  473. /// return an array of one byte whose element is 0x00.
  474. /// </summary>
  475. public byte[] ToByteArray() {
  476. return Value.ToByteArray();
  477. }
  478. [Confined]
  479. public string ToString(IFormatProvider provider) {
  480. return Value.ToString(provider);
  481. }
  482. #region IFormattable Members
  483. string IFormattable.ToString(string format, IFormatProvider formatProvider) {
  484. return Value.ToString(format, formatProvider);
  485. }
  486. #endregion
  487. }
  488. }
  489. #endif