1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
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.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
18 using System.Collections.Generic;
19 using System.Diagnostics;
20 using System.Diagnostics.CodeAnalysis;
21 using System.Globalization;
23 using Microsoft.Scripting.Utils;
24 using BigInt = System.Numerics.BigInteger;
26 namespace Microsoft.Scripting.Math {
28 /// arbitrary precision integers
31 public sealed class BigInteger : IFormattable, IComparable, IEquatable<BigInteger> {
32 internal readonly BigInt Value;
34 [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
35 public static readonly BigInteger Zero = new BigInteger((BigInt)0);
36 [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
37 public static readonly BigInteger One = new BigInteger((BigInt)1);
39 public BigInteger(BigInt value) {
44 public static BigInteger Create(ulong v) {
45 return new BigInteger(new BigInt(v));
49 public static BigInteger Create(uint v) {
50 return new BigInteger(new BigInt(v));
53 public static BigInteger Create(long v) {
54 return new BigInteger(new BigInt(v));
57 public static BigInteger Create(int v) {
58 return new BigInteger(new BigInt(v));
61 public static BigInteger Create(decimal v) {
62 return new BigInteger(new BigInt(v));
65 public static BigInteger Create(byte[] v) {
66 return new BigInteger(v);
69 public static BigInteger Create(double v) {
70 return new BigInteger(new BigInt(v));
73 public static implicit operator BigInteger(byte i) {
74 return new BigInteger((BigInt)i);
78 public static implicit operator BigInteger(sbyte i) {
79 return new BigInteger((BigInt)i);
82 public static implicit operator BigInteger(short i) {
83 return new BigInteger((BigInt)i);
87 public static implicit operator BigInteger(ushort i) {
88 return new BigInteger((BigInt)i);
92 public static implicit operator BigInteger(uint i) {
93 return new BigInteger((BigInt)i);
96 public static implicit operator BigInteger(int i) {
97 return new BigInteger((BigInt)i);
100 [CLSCompliant(false)]
101 public static implicit operator BigInteger(ulong i) {
102 return new BigInteger((BigInt)i);
105 public static implicit operator BigInteger(long i) {
106 return new BigInteger((BigInt)i);
109 public static implicit operator BigInteger(decimal self) {
110 return new BigInteger((BigInt)self);
113 public static explicit operator BigInteger(double self) {
114 return new BigInteger((BigInt)self);
117 public static explicit operator BigInteger(float self) {
118 return new BigInteger((BigInt)self);
121 public static explicit operator double(BigInteger self) {
122 return (double)self.Value;
125 public static explicit operator float(BigInteger self) {
126 return (float)self.Value;
129 public static explicit operator decimal(BigInteger self) {
130 return (decimal)self.Value;
133 public static explicit operator byte(BigInteger self) {
134 return (byte)self.Value;
137 [CLSCompliant(false)]
138 public static explicit operator sbyte(BigInteger self) {
139 return (sbyte)self.Value;
142 [CLSCompliant(false)]
143 public static explicit operator UInt16(BigInteger self) {
144 return (UInt16)self.Value;
147 public static explicit operator Int16(BigInteger self) {
148 return (Int16)self.Value;
151 [CLSCompliant(false)]
152 public static explicit operator UInt32(BigInteger self) {
153 return (UInt32)self.Value;
156 public static explicit operator Int32(BigInteger self) {
157 return (Int32)self.Value;
160 public static explicit operator Int64(BigInteger self) {
161 return (Int64)self.Value;
164 [CLSCompliant(false)]
165 public static explicit operator UInt64(BigInteger self) {
166 return (UInt64)self.Value;
169 public static implicit operator BigInteger(BigInt value) {
170 return new BigInteger(value);
173 public static implicit operator BigInt(BigInteger value) {
177 public BigInteger(BigInteger copy) {
178 if (object.ReferenceEquals(copy, null)) {
179 throw new ArgumentNullException("copy");
184 public BigInteger(byte[] data) {
185 ContractUtils.RequiresNotNull(data, "data");
187 Value = new BigInt(data);
190 public BigInteger(int sign, byte[] data) {
191 ContractUtils.RequiresNotNull(data, "data");
192 ContractUtils.Requires(sign >= -1 && sign <= +1, "sign");
194 Value = new BigInt(data);
200 [CLSCompliant(false)]
201 public BigInteger(int sign, uint[] data) {
202 ContractUtils.RequiresNotNull(data, "data");
203 ContractUtils.Requires(sign >= -1 && sign <= +1, "sign");
204 int length = GetLength(data);
205 ContractUtils.Requires(length == 0 || sign != 0, "sign");
211 bool highest = (data[length - 1] & 0x80000000) != 0;
212 byte[] bytes = new byte[length * 4 + (highest ? 1 : 0)];
214 for (int i = 0; i < length; i++) {
216 bytes[j++] = (byte)(w & 0xff);
217 bytes[j++] = (byte)((w >> 8) & 0xff);
218 bytes[j++] = (byte)((w >> 16) & 0xff);
219 bytes[j++] = (byte)((w >> 24) & 0xff);
222 Value = new BigInt(bytes);
228 [CLSCompliant(false)]
229 public uint[] GetWords() {
230 return Value.GetWords();
233 public int GetBitCount() {
234 return Value.GetBitCount();
237 public int GetWordCount() {
238 return Value.GetWordCount();
241 public int GetByteCount() {
242 return Value.GetByteCount();
246 /// Return the sign of this BigInteger: -1, 0, or 1.
254 public bool AsInt64(out long ret) {
255 if (Value >= Int64.MinValue && Value <= Int64.MaxValue) {
263 [CLSCompliant(false)]
264 public bool AsUInt32(out uint ret) {
265 if (Value >= UInt32.MinValue && Value <= UInt32.MaxValue) {
273 [CLSCompliant(false)]
274 public bool AsUInt64(out ulong ret) {
275 if (Value >= UInt64.MinValue && Value <= UInt64.MaxValue) {
283 public bool AsInt32(out int ret) {
284 if (Value >= Int32.MinValue && Value <= Int32.MaxValue) {
292 [CLSCompliant(false)]
293 public uint ToUInt32() {
297 public int ToInt32() {
301 public decimal ToDecimal() {
302 return (decimal)Value;
305 [CLSCompliant(false)]
306 public ulong ToUInt64() {
310 public long ToInt64() {
314 private static int GetLength(uint[] data) {
315 int ret = data.Length - 1;
316 while (ret >= 0 && data[ret] == 0) ret--;
320 public static int Compare(BigInteger x, BigInteger y) {
321 return BigInt.Compare(x.Value, y.Value);
324 public static bool operator ==(BigInteger x, int y) {
328 public static bool operator !=(BigInteger x, int y) {
332 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] // TODO: fix
333 public static bool operator ==(BigInteger x, double y) {
334 if (object.ReferenceEquals(x, null)) {
335 throw new ArgumentNullException("x");
338 // we can hold all double values, but not all double values
339 // can hold BigInteger values, and we may lose precision. Convert
340 // the double to a big int, then compare.
342 if ((y % 1) != 0) return false; // not a whole number, can't be equal
344 return x.Value == (BigInt)y;
347 public static bool operator ==(double x, BigInteger y) {
351 public static bool operator !=(BigInteger x, double y) {
355 public static bool operator !=(double x, BigInteger y) {
360 public static bool operator ==(BigInteger x, BigInteger y) {
361 return Compare(x, y) == 0;
364 public static bool operator !=(BigInteger x, BigInteger y) {
365 return Compare(x, y) != 0;
367 public static bool operator <(BigInteger x, BigInteger y) {
368 return Compare(x, y) < 0;
370 public static bool operator <=(BigInteger x, BigInteger y) {
371 return Compare(x, y) <= 0;
373 public static bool operator >(BigInteger x, BigInteger y) {
374 return Compare(x, y) > 0;
376 public static bool operator >=(BigInteger x, BigInteger y) {
377 return Compare(x, y) >= 0;
380 public static BigInteger Add(BigInteger x, BigInteger y) {
384 public static BigInteger operator +(BigInteger x, BigInteger y) {
385 return new BigInteger(x.Value + y.Value);
388 public static BigInteger Subtract(BigInteger x, BigInteger y) {
392 public static BigInteger operator -(BigInteger x, BigInteger y) {
393 return new BigInteger(x.Value - y.Value);
396 public static BigInteger Multiply(BigInteger x, BigInteger y) {
400 public static BigInteger operator *(BigInteger x, BigInteger y) {
401 return new BigInteger(x.Value * y.Value);
404 public static BigInteger Divide(BigInteger x, BigInteger y) {
408 public static BigInteger operator /(BigInteger x, BigInteger y) {
410 return DivRem(x, y, out dummy);
413 public static BigInteger Mod(BigInteger x, BigInteger y) {
417 public static BigInteger operator %(BigInteger x, BigInteger y) {
419 DivRem(x, y, out ret);
423 public static BigInteger DivRem(BigInteger x, BigInteger y, out BigInteger remainder) {
425 BigInt result = BigInt.DivRem(x.Value, y.Value, out rem);
426 remainder = new BigInteger(rem);
427 return new BigInteger(result);
430 public static BigInteger BitwiseAnd(BigInteger x, BigInteger y) {
434 public static BigInteger operator &(BigInteger x, BigInteger y) {
435 return new BigInteger(x.Value & y.Value);
438 public static BigInteger BitwiseOr(BigInteger x, BigInteger y) {
442 public static BigInteger operator |(BigInteger x, BigInteger y) {
443 return new BigInteger(x.Value | y.Value);
446 public static BigInteger Xor(BigInteger x, BigInteger y) {
450 public static BigInteger operator ^(BigInteger x, BigInteger y) {
451 return new BigInteger(x.Value ^ y.Value);
454 public static BigInteger LeftShift(BigInteger x, int shift) {
458 public static BigInteger operator <<(BigInteger x, int shift) {
459 return new BigInteger(x.Value << shift);
462 public static BigInteger RightShift(BigInteger x, int shift) {
466 public static BigInteger operator >>(BigInteger x, int shift) {
467 return new BigInteger(x.Value >> shift);
470 public static BigInteger Negate(BigInteger x) {
474 public static BigInteger operator -(BigInteger x) {
475 return new BigInteger(-x.Value);
478 public BigInteger OnesComplement() {
482 public static BigInteger operator ~(BigInteger x) {
483 return new BigInteger(~x.Value);
486 public BigInteger Abs() {
487 return new BigInteger(BigInt.Abs(Value));
490 public BigInteger Power(int exp) {
491 return new BigInteger(BigInt.Pow(Value, exp));
494 public BigInteger ModPow(int power, BigInteger mod) {
495 return new BigInteger(BigInt.ModPow(Value, power, mod.Value));
498 public BigInteger ModPow(BigInteger power, BigInteger mod) {
499 return new BigInteger(BigInt.ModPow(Value, power.Value, mod.Value));
502 public BigInteger Square() {
507 public static BigInteger Parse(string str) {
508 return new BigInteger(BigInt.Parse(str));
512 public override string ToString() {
516 public string ToString(int @base) {
517 return MathUtils.BigIntegerToString(GetWords(), Sign, @base, false);
520 public string ToString(string format) {
521 return Value.ToString(format);
524 public override int GetHashCode() {
525 return Value.GetHashCode();
528 public override bool Equals(object obj) {
529 return Equals(obj as BigInteger);
532 public bool Equals(BigInteger other) {
533 if (object.ReferenceEquals(other, null)) return false;
534 return this == other;
537 public bool IsNegative() {
538 return Value.Sign < 0;
541 public bool IsZero() {
542 return Value.Sign == 0;
545 public bool IsPositive() {
546 return Value.Sign > 0;
550 get { return Value.IsEven; }
553 public bool IsPowerOfTwo {
555 return Value.IsPowerOfTwo;
559 public double Log(Double newBase) {
560 return BigInt.Log(Value, newBase);
564 /// Calculates the natural logarithm of the BigInteger.
566 public double Log() {
567 return BigInt.Log(Value);
571 /// Calculates log base 10 of a BigInteger.
573 public double Log10() {
574 return BigInt.Log10(Value);
577 #region IComparable Members
579 public int CompareTo(object obj) {
583 BigInteger o = obj as BigInteger;
584 if (object.ReferenceEquals(o, null)) {
585 throw new ArgumentException("expected integer");
587 return Compare(this, o);
593 /// Return the value of this BigInteger as a little-endian twos-complement
594 /// byte array, using the fewest number of bytes possible. If the value is zero,
595 /// return an array of one byte whose element is 0x00.
597 public byte[] ToByteArray() {
598 return Value.ToByteArray();
601 public string ToString(IFormatProvider provider) {
602 return Value.ToString(provider);
605 #region IFormattable Members
607 string IFormattable.ToString(string format, IFormatProvider formatProvider) {
608 return Value.ToString(format, formatProvider);