diff options
Diffstat (limited to 'Source/Basetypes/BigNum.cs')
-rw-r--r-- | Source/Basetypes/BigNum.cs | 722 |
1 files changed, 361 insertions, 361 deletions
diff --git a/Source/Basetypes/BigNum.cs b/Source/Basetypes/BigNum.cs index ff676bc6..4469f149 100644 --- a/Source/Basetypes/BigNum.cs +++ b/Source/Basetypes/BigNum.cs @@ -1,361 +1,361 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Text;
-using System.Diagnostics.Contracts;
-
-
-namespace Microsoft.Basetypes {
- using BIM = System.Numerics.BigInteger;
-
- /// <summary>
- /// A thin wrapper around System.Numerics.BigInteger
- /// (to be able to define equality, etc. properly)
- /// </summary>
- public struct BigNum {
-
- // the internal representation
- [Rep]
- internal readonly System.Numerics.BigInteger val;
- public static readonly BigNum ZERO = new BigNum(BIM.Zero);
- public static readonly BigNum ONE = new BigNum(BIM.One);
- public static readonly BigNum MINUS_ONE = new BigNum(-BIM.One);
-
- [Pure]
- public static BigNum FromInt(int v) {
- return new BigNum(new BIM(v));
- }
-
- [Pure]
- public static BigNum FromUInt(uint v) {
- return new BigNum(new BIM((long)v));
- }
-
- [Pure]
- public static BigNum FromLong(long v) {
- return new BigNum(new BIM(v));
- }
-
- [Pure]
- public static BigNum FromBigInt(System.Numerics.BigInteger v) {
- return new BigNum(v);
- }
-
- [Pure]
- public static BigNum FromULong(ulong v) {
- return FromString("" + v);
- }
-
- [Pure]
- public static BigNum FromString(string v) {
- try {
- return new BigNum(BIM.Parse(v));
- } catch (System.ArgumentException) {
- throw new FormatException();
- }
- }
-
- public static bool TryParse(string v, out BigNum res) {
- try {
- res = BigNum.FromString(v);
- return true;
- } catch (FormatException) {
- res = ZERO;
- return false;
- }
- }
-
- // Convert to int, without checking whether overflows occur
- public int ToInt {
- get {
- return (int)val;
- }
- }
-
- public BIM ToBigInteger {
- get {
- return val;
- }
- }
-
- // Convert to int; assert that no overflows occur
- public int ToIntSafe {
- get {
- Contract.Assert(this.InInt32);
- return this.ToInt;
- }
- }
-
- public Rational ToRational {
- get {
- return Rational.FromBignum(this);
- }
- }
-
- public byte[] ToByteArray()
- {
- return this.val.ToByteArray();
- }
-
- internal BigNum(System.Numerics.BigInteger val) {
- this.val = val;
- }
-
- public static bool operator ==(BigNum x, BigNum y) {
- return (x.val == y.val);
- }
-
- public static bool operator !=(BigNum x, BigNum y) {
- return !(x.val == y.val);
- }
-
- [Pure]
- [Reads(ReadsAttribute.Reads.Nothing)]
- public override bool Equals(object obj) {
- if (obj == null)
- return false;
- if (!(obj is BigNum))
- return false;
-
- BigNum other = (BigNum)obj;
- return (this.val == other.val);
- }
-
- [Pure]
- public override int GetHashCode() {
- return this.val.GetHashCode();
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return cce.NonNull(val.ToString());
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Very limited support for format strings
- // Note: Negative integers are linearised with a minus "-" in hexadecimal,
- // not in 2-complement notation (in contrast to what the method
- // int32.ToString(format) does)
-
- [Pure]
- public string/*!*/ ToString(string/*!*/ format) {
- Contract.Requires(format != null);
- Contract.Ensures(Contract.Result<string>() != null);
- if (format.StartsWith("d") || format.StartsWith("D")) {
- string res = this.Abs.ToString();
- Contract.Assert(res != null);
- return addMinus(this.Signum,
- prefixWithZeros(extractPrecision(format), res));
- } else if (format.StartsWith("x") || format.StartsWith("X")) {
- string res = this.toHex(format.Substring(0, 1));
- Contract.Assert(res != null);
- return addMinus(this.Signum,
- prefixWithZeros(extractPrecision(format), res));
- } else {
- throw new FormatException("Format " + format + " is not supported");
- }
- }
-
- private static readonly System.Numerics.BigInteger BI_2_TO_24 = new BIM(0x1000000);
-
- [Pure]
- private string/*!*/ toHex(string/*!*/ format) {
- Contract.Requires(format != null);
- Contract.Ensures(Contract.Result<string>() != null);
- string res = "";
- System.Numerics.BigInteger rem = this.Abs.val;
-
- while (rem > BIM.Zero) {
- res = ((int)(rem % BI_2_TO_24)).ToString(format) + res;
- rem = rem / BI_2_TO_24;
- }
-
- return res;
- }
-
- [Pure]
- private int extractPrecision(string/*!*/ format) {
- Contract.Requires(format != null);
- if (format.Length > 1)
- // will throw a FormatException if the precision is invalid;
- // that is ok
- return Int32.Parse(format.Substring(1));
- // always output at least one digit
- return 1;
- }
-
- [Pure]
- private string/*!*/ addMinus(int signum, string/*!*/ suffix) {
- Contract.Requires(suffix != null);
- Contract.Ensures(Contract.Result<string>() != null);
- if (signum < 0)
- return "-" + suffix;
- return suffix;
- }
-
- [Pure]
- private string/*!*/ prefixWithZeros(int minLength, string/*!*/ suffix) {
- Contract.Requires(suffix != null);
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder res = new StringBuilder();
- while (res.Length + suffix.Length < minLength)
- res.Append("0");
- res.Append(suffix);
- return res.ToString();
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Basic arithmetic operations
-
- public BigNum Abs {
- get {
- return new BigNum(BIM.Abs(this.val));
- }
- }
-
- public BigNum Neg {
- get {
- return new BigNum(-this.val);
- }
- }
-
- [Pure]
- public static BigNum operator -(BigNum x) {
- return x.Neg;
- }
-
- [Pure]
- public static BigNum operator +(BigNum x, BigNum y) {
- return new BigNum(x.val + y.val);
- }
-
- [Pure]
- public static BigNum operator -(BigNum x, BigNum y) {
- return new BigNum(x.val - y.val);
- }
-
- [Pure]
- public static BigNum operator *(BigNum x, BigNum y) {
- return new BigNum(x.val * y.val);
- }
-
- // TODO: check that this has a proper semantics (which? :-))
- [Pure]
- public static BigNum operator /(BigNum x, BigNum y) {
- return new BigNum(x.val / y.val);
- }
-
- // TODO: check that this has a proper semantics (which? :-))
- [Pure]
- public static BigNum operator %(BigNum x, BigNum y) {
- return new BigNum(x.val - ((x.val / y.val) * y.val));
- }
-
- [Pure]
- public BigNum Min(BigNum that) {
- return new BigNum(this.val <= that.val ? this.val : that.val);
- }
-
- [Pure]
- public BigNum Max(BigNum that) {
- return new BigNum(this.val >= that.val ? this.val : that.val);
- }
-
- /// <summary>
- /// Returns the greatest common divisor of this and _y.
- /// </summary>
- /// <param name="_y"></param>
- /// <returns></returns>
- public BigNum Gcd(BigNum _y) {
- Contract.Ensures(!Contract.Result<BigNum>().IsNegative);
- BigNum x = this.Abs;
- BigNum y = _y.Abs;
-
- while (true) {
- if (x < y) {
- y = y % x;
- if (y.IsZero) {
- return x;
- }
- } else {
- x = x % y;
- if (x.IsZero) {
- return y;
- }
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Some basic comparison operations
-
- public int Signum {
- get {
- return this.val.Sign;
- }
- }
-
- public bool IsPositive {
- get {
- return (this.val > BIM.Zero);
- }
- }
-
- public bool IsNegative {
- get {
- return (this.val < BIM.Zero);
- }
- }
-
- public bool IsZero {
- get {
- return this.val.IsZero;
- }
- }
-
- [Pure]
- public int CompareTo(BigNum that) {
- if (this.val == that.val)
- return 0;
- if (this.val < that.val)
- return -1;
- return 1;
- }
-
- [Pure]
- public static bool operator <(BigNum x, BigNum y) {
- return (x.val < y.val);
- }
-
- [Pure]
- public static bool operator >(BigNum x, BigNum y) {
- return (x.val > y.val);
- }
-
- [Pure]
- public static bool operator <=(BigNum x, BigNum y) {
- return (x.val <= y.val);
- }
-
- [Pure]
- public static bool operator >=(BigNum x, BigNum y) {
- return (x.val >= y.val);
- }
-
-
- private static readonly System.Numerics.BigInteger MaxInt32 =
- new BIM(Int32.MaxValue);
- private static readonly System.Numerics.BigInteger MinInt32 =
- new BIM(Int32.MinValue);
-
- public bool InInt32 {
- get {
- return (val >= MinInt32) && (val <= MaxInt32);
- }
- }
- }
-}
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.Text; +using System.Diagnostics.Contracts; + + +namespace Microsoft.Basetypes { + using BIM = System.Numerics.BigInteger; + + /// <summary> + /// A thin wrapper around System.Numerics.BigInteger + /// (to be able to define equality, etc. properly) + /// </summary> + public struct BigNum { + + // the internal representation + [Rep] + internal readonly System.Numerics.BigInteger val; + public static readonly BigNum ZERO = new BigNum(BIM.Zero); + public static readonly BigNum ONE = new BigNum(BIM.One); + public static readonly BigNum MINUS_ONE = new BigNum(-BIM.One); + + [Pure] + public static BigNum FromInt(int v) { + return new BigNum(new BIM(v)); + } + + [Pure] + public static BigNum FromUInt(uint v) { + return new BigNum(new BIM((long)v)); + } + + [Pure] + public static BigNum FromLong(long v) { + return new BigNum(new BIM(v)); + } + + [Pure] + public static BigNum FromBigInt(System.Numerics.BigInteger v) { + return new BigNum(v); + } + + [Pure] + public static BigNum FromULong(ulong v) { + return FromString("" + v); + } + + [Pure] + public static BigNum FromString(string v) { + try { + return new BigNum(BIM.Parse(v)); + } catch (System.ArgumentException) { + throw new FormatException(); + } + } + + public static bool TryParse(string v, out BigNum res) { + try { + res = BigNum.FromString(v); + return true; + } catch (FormatException) { + res = ZERO; + return false; + } + } + + // Convert to int, without checking whether overflows occur + public int ToInt { + get { + return (int)val; + } + } + + public BIM ToBigInteger { + get { + return val; + } + } + + // Convert to int; assert that no overflows occur + public int ToIntSafe { + get { + Contract.Assert(this.InInt32); + return this.ToInt; + } + } + + public Rational ToRational { + get { + return Rational.FromBignum(this); + } + } + + public byte[] ToByteArray() + { + return this.val.ToByteArray(); + } + + internal BigNum(System.Numerics.BigInteger val) { + this.val = val; + } + + public static bool operator ==(BigNum x, BigNum y) { + return (x.val == y.val); + } + + public static bool operator !=(BigNum x, BigNum y) { + return !(x.val == y.val); + } + + [Pure] + [Reads(ReadsAttribute.Reads.Nothing)] + public override bool Equals(object obj) { + if (obj == null) + return false; + if (!(obj is BigNum)) + return false; + + BigNum other = (BigNum)obj; + return (this.val == other.val); + } + + [Pure] + public override int GetHashCode() { + return this.val.GetHashCode(); + } + + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result<string>() != null); + return cce.NonNull(val.ToString()); + } + + ////////////////////////////////////////////////////////////////////////////// + // Very limited support for format strings + // Note: Negative integers are linearised with a minus "-" in hexadecimal, + // not in 2-complement notation (in contrast to what the method + // int32.ToString(format) does) + + [Pure] + public string/*!*/ ToString(string/*!*/ format) { + Contract.Requires(format != null); + Contract.Ensures(Contract.Result<string>() != null); + if (format.StartsWith("d") || format.StartsWith("D")) { + string res = this.Abs.ToString(); + Contract.Assert(res != null); + return addMinus(this.Signum, + prefixWithZeros(extractPrecision(format), res)); + } else if (format.StartsWith("x") || format.StartsWith("X")) { + string res = this.toHex(format.Substring(0, 1)); + Contract.Assert(res != null); + return addMinus(this.Signum, + prefixWithZeros(extractPrecision(format), res)); + } else { + throw new FormatException("Format " + format + " is not supported"); + } + } + + private static readonly System.Numerics.BigInteger BI_2_TO_24 = new BIM(0x1000000); + + [Pure] + private string/*!*/ toHex(string/*!*/ format) { + Contract.Requires(format != null); + Contract.Ensures(Contract.Result<string>() != null); + string res = ""; + System.Numerics.BigInteger rem = this.Abs.val; + + while (rem > BIM.Zero) { + res = ((int)(rem % BI_2_TO_24)).ToString(format) + res; + rem = rem / BI_2_TO_24; + } + + return res; + } + + [Pure] + private int extractPrecision(string/*!*/ format) { + Contract.Requires(format != null); + if (format.Length > 1) + // will throw a FormatException if the precision is invalid; + // that is ok + return Int32.Parse(format.Substring(1)); + // always output at least one digit + return 1; + } + + [Pure] + private string/*!*/ addMinus(int signum, string/*!*/ suffix) { + Contract.Requires(suffix != null); + Contract.Ensures(Contract.Result<string>() != null); + if (signum < 0) + return "-" + suffix; + return suffix; + } + + [Pure] + private string/*!*/ prefixWithZeros(int minLength, string/*!*/ suffix) { + Contract.Requires(suffix != null); + Contract.Ensures(Contract.Result<string>() != null); + StringBuilder res = new StringBuilder(); + while (res.Length + suffix.Length < minLength) + res.Append("0"); + res.Append(suffix); + return res.ToString(); + } + + //////////////////////////////////////////////////////////////////////////// + // Basic arithmetic operations + + public BigNum Abs { + get { + return new BigNum(BIM.Abs(this.val)); + } + } + + public BigNum Neg { + get { + return new BigNum(-this.val); + } + } + + [Pure] + public static BigNum operator -(BigNum x) { + return x.Neg; + } + + [Pure] + public static BigNum operator +(BigNum x, BigNum y) { + return new BigNum(x.val + y.val); + } + + [Pure] + public static BigNum operator -(BigNum x, BigNum y) { + return new BigNum(x.val - y.val); + } + + [Pure] + public static BigNum operator *(BigNum x, BigNum y) { + return new BigNum(x.val * y.val); + } + + // TODO: check that this has a proper semantics (which? :-)) + [Pure] + public static BigNum operator /(BigNum x, BigNum y) { + return new BigNum(x.val / y.val); + } + + // TODO: check that this has a proper semantics (which? :-)) + [Pure] + public static BigNum operator %(BigNum x, BigNum y) { + return new BigNum(x.val - ((x.val / y.val) * y.val)); + } + + [Pure] + public BigNum Min(BigNum that) { + return new BigNum(this.val <= that.val ? this.val : that.val); + } + + [Pure] + public BigNum Max(BigNum that) { + return new BigNum(this.val >= that.val ? this.val : that.val); + } + + /// <summary> + /// Returns the greatest common divisor of this and _y. + /// </summary> + /// <param name="_y"></param> + /// <returns></returns> + public BigNum Gcd(BigNum _y) { + Contract.Ensures(!Contract.Result<BigNum>().IsNegative); + BigNum x = this.Abs; + BigNum y = _y.Abs; + + while (true) { + if (x < y) { + y = y % x; + if (y.IsZero) { + return x; + } + } else { + x = x % y; + if (x.IsZero) { + return y; + } + } + } + } + + //////////////////////////////////////////////////////////////////////////// + // Some basic comparison operations + + public int Signum { + get { + return this.val.Sign; + } + } + + public bool IsPositive { + get { + return (this.val > BIM.Zero); + } + } + + public bool IsNegative { + get { + return (this.val < BIM.Zero); + } + } + + public bool IsZero { + get { + return this.val.IsZero; + } + } + + [Pure] + public int CompareTo(BigNum that) { + if (this.val == that.val) + return 0; + if (this.val < that.val) + return -1; + return 1; + } + + [Pure] + public static bool operator <(BigNum x, BigNum y) { + return (x.val < y.val); + } + + [Pure] + public static bool operator >(BigNum x, BigNum y) { + return (x.val > y.val); + } + + [Pure] + public static bool operator <=(BigNum x, BigNum y) { + return (x.val <= y.val); + } + + [Pure] + public static bool operator >=(BigNum x, BigNum y) { + return (x.val >= y.val); + } + + + private static readonly System.Numerics.BigInteger MaxInt32 = + new BIM(Int32.MaxValue); + private static readonly System.Numerics.BigInteger MinInt32 = + new BIM(Int32.MinValue); + + public bool InInt32 { + get { + return (val >= MinInt32) && (val <= MaxInt32); + } + } + } +} |