+++ /dev/null
-// Big Integer class for .NET
-// (c) The GHC Team 2001
-
-// TODO:
-// Constructors from Single, Double, Currency, String
-//
-
-using System;
-using System.Diagnostics;
-
-public class BigInteger : IComparable, IConvertible, IFormattable {
-
- int sign;
- int size;
- int used;
- byte[] body;
-
- const int B_BASE = 256;
- const double B_BASE_FLT = 256.0;
-
-
- // Constructors
-
- public BigInteger() {
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- }
-
- public BigInteger(Int32 n) {
- this.size = 4;
- this.body = new byte[this.size];
- this.sign = this.used = 0;
- if (n == 0) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- return;
- }
- if (n < 0) {
- this.sign = -1;
- }
- else {
- this.sign = 1;
- }
- if (n < 0) {
- n = -n;
- }
- while (n != 0) {
- this.body[this.used] = (byte)(n % B_BASE);
- n /= B_BASE;
- this.used++;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- }
-
- public BigInteger(UInt32 n) {
- this.size = 4;
- this.body = new byte[this.size];
- this.sign = this.used = 0;
- if (n == 0) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- return;
- }
- this.sign = 1;
- while (n != 0) {
- this.body[this.used] = (byte)(n % B_BASE);
- n /= B_BASE;
- this.used++;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- }
-
- public BigInteger(Int64 n) {
- this.size = 8;
- this.body = new byte[this.size];
- this.sign = this.used = 0;
- if (n == 0) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- return;
- }
- if (n < 0) {
- this.sign = -1;
- }
- else {
- this.sign = 1;
- }
- if (n < 0) {
- n = -n;
- }
- while (n != 0) {
- this.body[this.used] = (byte)(n % B_BASE);
- n /= B_BASE;
- this.used++;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- }
-
- public BigInteger(UInt64 n) {
- this.size = 8;
- this.body = new byte[this.size];
- this.sign = this.used = 0;
- if (n == 0) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- return;
- }
- this.sign = 1;
- while (n != 0) {
- this.body[this.used] = (byte)(n % B_BASE);
- n /= B_BASE;
- this.used++;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- }
-
- // NOTE: This only works currectly if B_BASE >= 10
- // TODO: Turn this into a Parse method taking a String
- public BigInteger (char [] str) {
- int sign, d, t, i, j, carry;
-
- for (i = 0; str[i] != 0; i++) {
- }
- this.size = i;
- this.body = new byte[this.size];
- this.sign = this.used = 0;
- sign = 1;
- i = 0;
- if (str[0] == '-') {
- i++;
- sign = -1;
- }
-
- while (Char.IsDigit(str[i])) {
-
- // multiply this by 10
- carry = 0;
- for (j = 0; j < this.used; j++) {
- t = 10 * this.body[j] + carry;
- this.body[j] = (byte)(t % B_BASE);
- carry = t / B_BASE;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(carry < B_BASE);
-#endif
- if (carry > 0) {
- this.body[this.used++] = (byte)carry;
- }
- // add a digit on
- d = str[i] - '0';
- i++;
-
- carry = d;
- for (j = 0; j < this.used; j++) {
- carry += this.body[j];
- this.body[j] = (byte)(carry % B_BASE);
- carry /= B_BASE;
- if (carry == 0) {
- break;
- }
- }
- if (carry > 0) {
- this.body[this.used++] = (byte)carry;
- }
- }
-
- this.sign = sign;
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- }
-
-
- // Constants
- static readonly BigInteger Zero = new BigInteger(0);
- static readonly BigInteger One = new BigInteger(1);
- static readonly BigInteger MinusOne = new BigInteger(-1);
-
-
- // Conversions
-
- // Implicit
- public static implicit operator BigInteger(SByte n) {
- return new BigInteger((Int32)n);
- }
-
- public static implicit operator BigInteger(Byte n) {
- return new BigInteger((UInt32)n);
- }
-
- public static implicit operator BigInteger(Int16 n) {
- return new BigInteger((Int32)n);
- }
-
- public static implicit operator BigInteger(UInt16 n) {
- return new BigInteger((UInt32)n);
- }
-
- public static implicit operator BigInteger(Char n) {
- return new BigInteger((Int32)n);
- }
-
- public static implicit operator BigInteger(Int32 n) {
- return new BigInteger(n);
- }
-
- public static implicit operator BigInteger(UInt32 n) {
- return new BigInteger(n);
- }
-
- public static implicit operator BigInteger(Int64 n) {
- return new BigInteger(n);
- }
-
- public static implicit operator BigInteger(UInt64 n) {
- return new BigInteger(n);
- }
-
- // Explicit
-
- public static Boolean ToBoolean(BigInteger n) {
- throw new InvalidCastException();
- }
-
- public static explicit operator Boolean(BigInteger n) {
- return ToBoolean(n);
- }
-
- Boolean IConvertible.ToBoolean(IFormatProvider p) {
- return ToBoolean(this);
- }
-
- public static DateTime ToDateTime(BigInteger n) {
- throw new InvalidCastException();
- }
-
- DateTime IConvertible.ToDateTime(IFormatProvider p) {
- return ToDateTime(this);
- }
-
- public static explicit operator DateTime(BigInteger n) {
- return ToDateTime(n);
- }
-
- public static SByte ToSByte(BigInteger n) {
- SByte res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- if (n.used > 0) {
- res = (SByte)n.body[0];
- }
- if (n.sign < 0) {
- res = (SByte)(-res);
- }
- return res;
- }
-
- SByte IConvertible.ToSByte(IFormatProvider p) {
- return ToSByte(this);
- }
-
- public static explicit operator SByte(BigInteger n) {
- return ToSByte(n);
- }
-
- public static Byte ToByte(BigInteger n) {
- Byte res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- if (n.used > 0) {
- res = (Byte)n.body[0];
- }
- return res;
- }
-
- Byte IConvertible.ToByte(IFormatProvider p) {
- return ToByte(this);
- }
-
- public static explicit operator Byte(BigInteger n) {
- return ToByte(n);
- }
-
- public static Int16 ToInt16(BigInteger n) {
- int i, d;
- Int16 res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = (Int16)(res * B_BASE + d);
- }
- if (n.sign < 0) {
- res = (Int16)(-res);
- }
- return res;
- }
-
- Int16 IConvertible.ToInt16(IFormatProvider p) {
- return ToInt16(this);
- }
-
- public static explicit operator Int16(BigInteger n) {
- return ToInt16(n);
- }
-
- public static UInt16 ToUInt16(BigInteger n) {
- int i, d;
- UInt16 res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = (UInt16)(res * B_BASE + d);
- }
- return res;
- }
-
- UInt16 IConvertible.ToUInt16(IFormatProvider p) {
- return ToUInt16(this);
- }
-
- public static explicit operator UInt16(BigInteger n) {
- return ToUInt16(n);
- }
-
- public static Char ToChar(BigInteger n) {
- throw new InvalidCastException();
- }
-
- Char IConvertible.ToChar(IFormatProvider p) {
- return ToChar(this);
- }
-
- public static explicit operator Char(BigInteger n) {
- return ToChar(n);
- }
-
- public static Int32 ToInt32(BigInteger n) {
- int i, d;
- Int32 res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = res * B_BASE + d;
- }
- if (n.sign < 0) {
- res = -res;
- }
- return res;
- }
-
- Int32 IConvertible.ToInt32(IFormatProvider p) {
- return ToInt32(this);
- }
-
- public static explicit operator Int32(BigInteger n) {
- return ToInt32(n);
- }
-
- public static UInt32 ToUInt32(BigInteger n) {
- int i, d;
- UInt32 res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = res * B_BASE + (UInt32)d;
- }
- return res;
- }
-
- UInt32 IConvertible.ToUInt32(IFormatProvider p) {
- return ToUInt32(this);
- }
-
- public static explicit operator UInt32(BigInteger n) {
- return ToUInt32(n);
- }
-
- public static Int64 ToInt64(BigInteger n) {
- int i, d;
- Int64 res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = res * B_BASE + d;
- }
- if (n.sign < 0) {
- res = -res;
- }
- return res;
- }
-
- Int64 IConvertible.ToInt64(IFormatProvider p) {
- return ToInt64(this);
- }
-
- public static explicit operator Int64(BigInteger n) {
- return ToInt64(n);
- }
-
- public static UInt64 ToUInt64(BigInteger n) {
- int i, d;
- UInt64 res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = res * B_BASE + (UInt64)d;
- }
- return res;
- }
-
- UInt64 IConvertible.ToUInt64(IFormatProvider p) {
- return ToUInt64(this);
- }
-
- public static explicit operator UInt64(BigInteger n) {
- return ToUInt64(n);
- }
-
- public static Decimal ToDecimal(BigInteger n) {
- int i, d;
- Decimal res;
- if (n.sign == 0) {
- return 0;
- }
- res = 0;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = res * B_BASE + (Decimal)d;
- }
- return res;
- }
-
- Decimal IConvertible.ToDecimal(IFormatProvider p) {
- return ToDecimal(this);
- }
-
- public static explicit operator Decimal(BigInteger n) {
- return ToDecimal(n);
- }
-
- public static Single ToSingle(BigInteger n) {
- int i, d;
- Single res;
- if (n.sign == 0) {
- return 0.0F;
- }
- res = 0.0F;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = res * (Single)B_BASE_FLT + d;
- }
- if (n.sign < 0) {
- res = -res;
- }
- return res;
- }
-
- Single IConvertible.ToSingle(IFormatProvider p) {
- return ToSingle(this);
- }
-
- public static explicit operator Single(BigInteger n) {
- return ToSingle(n);
- }
-
- public static Double ToDouble(BigInteger n) {
- int i, d;
- Double res;
- if (n.sign == 0) {
- return 0.0;
- }
- res = 0.0;
- for (i = n.used-1; i >= 0; i--) {
- d = n.body[i];
- res = res * B_BASE_FLT + d;
- }
- if (n.sign < 0) {
- res = -res;
- }
- return res;
- }
-
- Double IConvertible.ToDouble(IFormatProvider p) {
- return ToDouble(this);
- }
-
- public static explicit operator Double(BigInteger n) {
- return ToDouble(n);
- }
-
- override public String ToString() {
- int i;
- Console.Write ( "sign={0} used={1} size={2} ", this.sign, this.used, this.size );
- for (i = this.used-1; i >= 0; i--) {
- Console.Write ( "{0} ", (int)(this.body[i]) );
- }
- Console.Write ( "\n" );
- return "(some number or other)";
- }
-
- public String ToString(IFormatProvider p) {
- return ToString(null, p);
- }
-
- public String ToString(String fmt) {
- return this.ToString();
- }
-
- public String ToString(String fmt, IFormatProvider p) {
- throw new InvalidCastException();
- }
-
- public Object ToType(Type ty, IFormatProvider n) {
- throw new InvalidCastException();
- }
-
- // public object GetFormat(Type
-
- public TypeCode GetTypeCode() {
- return TypeCode.Int64;
- }
-
- // Basics
-
- bool sane() {
- if (this.sign == 0 && this.used != 0) {
- return false;
- }
- if (this.sign != -1 && this.sign != 0 && this.sign != 1) {
- return false;
- }
- if (this.used < 0) {
- return false;
- }
- if (this.size < 0) {
- return false;
- }
- if (this.used > this.size) {
- return false;
- }
- if (this.used == 0) {
- return true;
- }
- if (this.body[this.used-1] == 0) {
- return false;
- }
- return true;
- }
-
- void u_renormalise() {
- while (this.used > 0 && this.body[this.used-1] == 0) {
- this.used--;
- }
- if (this.used == 0) {
- this.sign = 0;
- }
- else {
- this.sign = 1;
- }
- }
-
-
- public void renormalise() {
- while (this.used > 0 && this.body[this.used-1] == 0) {
- this.used--;
- }
- if (this.used == 0) {
- this.sign = 0;
- }
- }
-
-
- // Size of things
-
- static int maxused_addsub ( BigInteger x, BigInteger y ) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
- return 1 + (x.used > y.used ? x.used : y.used);
- }
-
- static int maxused_mul ( BigInteger x, BigInteger y ) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
- return x.used + y.used;
- }
-
- static int maxused_qrm ( BigInteger x, BigInteger y ) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
- return (x.used > y.used ? x.used : y.used);
- }
-
- int maxused_neg() {
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- return this.used;
- }
-
-
- // Signed ops
-
- // A helper for signed + and -. sdiff(x,y) ignores the signs of x and y
- // sets p to the signed value abs(x)-abs(y).
- static void sdiff(BigInteger x, BigInteger y, BigInteger res) {
- int t;
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
- Debug.Assert(res.size == maxused_addsub(x,y));
-#endif
- t = ucmp(x,y);
- if (t == 0) {
- res.sign = res.used = 0;
- return;
- }
- if (t == -1) {
- // x < y
- usub(y,x,res);
- res.sign = -1;
- }
- else {
- // x > y
- usub(x,y,res);
- res.sign = 1;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sane());
-#endif
- }
-
- public BigInteger Negate() {
-#if BIGINTEGER_DEBUG
- Debug.Assert(this.sane());
-#endif
- BigInteger res = new BigInteger();
- res.size = this.used;
- res.body = new byte[res.used];
- res.used = this.used;
- for (int i = 0; i < this.used; i++) {
- res.body[i] = this.body[i];
- }
- res.sign = -(this.sign);
- return res;
- }
-
- public static BigInteger Add(BigInteger x, BigInteger y) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
- BigInteger res = new BigInteger();
- res.size = maxused_addsub(x, y);
- res.used = res.sign = 0;
-
- if ( (x.sign >= 0 && y.sign >= 0) ||
- (x.sign < 0 && y.sign < 0)) {
- // same sign; add magnitude and clone sign
- uadd(x,y,res);
- if (x.sign < 0 && res.sign != 0) {
- res.sign = -1;
- }
- }
- else {
- // signs differ; use sdiff
- if (x.sign >= 0 && y.sign < 0) {
- sdiff(x,y,res);
- }
- else {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sign < 0 && y.sign >= 0);
-#endif
- sdiff(y,x,res);
- }
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sane());
-#endif
- return res;
- }
-
- public BigInteger Increment() {
- return this + 1;
- }
-
- public static BigInteger Sub(BigInteger x, BigInteger y) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
- BigInteger res = new BigInteger();
- res.size = maxused_addsub(x, y);
- res.used = res.sign = 0;
-
- if ( (x.sign >= 0 && y.sign < 0) ||
- (x.sign < 0 && y.sign >= 0)) {
- // opposite signs; add magnitudes and clone sign of x
- uadd(x,y,res);
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sign != 0);
-#endif
- if (x.sign < 0) {
- res.sign = -1;
- }
- }
- else
- // signs are the same; use sdiff
- if (x.sign >= 0 && y.sign >= 0) {
- sdiff(x,y,res);
- }
- else {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sign < 0 && y.sign < 0);
-#endif
- sdiff(y,x,res);
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sane());
-#endif
- return res;
- }
-
- public BigInteger Decrement() {
- return this - 1;
- }
-
- public static BigInteger Multiply(BigInteger x, BigInteger y) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
- BigInteger res = new BigInteger();
- res.size = maxused_mul(x, y);
- res.body = new byte[res.size];
- res.used = res.sign = 0;
-
- if (x.sign == 0 || y.sign == 0) {
- res.sign = res.used = 0;
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sane());
-#endif
- return res;
- }
- umul(x,y,res);
- if (x.sign != y.sign) {
- res.sign = -1;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sane());
-#endif
- return res;
- }
-
- public static BigInteger Divide(BigInteger x, BigInteger y) {
- BigInteger q, r;
- QuotientRemainder(x, y, out q, out r);
- return q;
- }
-
- public static BigInteger Remainder(BigInteger x, BigInteger y) {
- BigInteger q, r;
- QuotientRemainder(x, y, out q, out r);
- return r;
- }
-
- public static Int32 Compare(BigInteger x, BigInteger y) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
- if (x.sign < y.sign) {
- return -1;
- }
- if (x.sign > y.sign) {
- return 1;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sign == y.sign);
-#endif
- if (x.sign == 0) {
- return 0;
- }
- if (x.sign == 1) {
- return ucmp(x,y);
- }
- else {
- return ucmp(y,x);
- }
- }
-
- public Int32 CompareTo(Object o) {
- return Compare(this, (BigInteger)o);
- }
-
- public static Boolean Equals(BigInteger x, BigInteger y) {
- return Compare(x, y) == 0;
- }
-
- override public Boolean Equals(Object o) {
- return this == (BigInteger)o;
- }
-
- override public Int32 GetHashCode() {
- int i;
- UInt32 h = 0;
- for (i = 0; i < this.used; i++) {
- h = (h << 4) + this.body[i];
- UInt32 g = h & 0xf0000000;
- if (g != 0) {
- h ^= g >> 24;
- h ^= g;
- }
- }
- return (Int32)h;
- }
-
- // Overloaded operators
-
- public static BigInteger operator +(BigInteger x) {
- return x;
- }
-
- public static BigInteger operator -(BigInteger x) {
- return x.Negate();
- }
-
- public static BigInteger operator +(BigInteger x, BigInteger y) {
- return Add(x, y);
- }
-
- public static BigInteger operator -(BigInteger x, BigInteger y) {
- return Sub(x, y);
- }
-
- public static BigInteger operator ++(BigInteger x) {
- return x + 1;
- }
-
- public static BigInteger operator --(BigInteger x) {
- return x - 1;
- }
-
- public static BigInteger operator *(BigInteger x, BigInteger y) {
- return Multiply(x, y);
- }
-
- public static BigInteger operator /(BigInteger x, BigInteger y) {
- return Divide(x, y);
- }
-
- public static BigInteger operator %(BigInteger x, BigInteger y) {
- return Remainder(x, y);
- }
-
- public static Boolean operator ==(BigInteger x, BigInteger y) {
- return Equals(x, y);
- }
-
- public static Boolean operator !=(BigInteger x, BigInteger y) {
- return !Equals(x, y);
- }
- public static Boolean operator <(BigInteger x, BigInteger y) {
- return Compare(x, y) == -1;
- }
-
- public static Boolean operator <=(BigInteger x, BigInteger y) {
- return Compare(x, y) < 1;
- }
-
- public static Boolean operator >(BigInteger x, BigInteger y) {
- return Compare(x, y) == 1;
- }
-
- public static Boolean operator >=(BigInteger x, BigInteger y) {
- return Compare(x, y) > 0;
- }
-
-
- // Quotient and remainder (private)
-
- public static void QuotientRemainder(BigInteger x, BigInteger y, out BigInteger q, out BigInteger r) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
-
- if (y.sign == 0) {
- throw(new System.DivideByZeroException());
- }
-
- if (x.sign == 0) {
- q = new BigInteger();
- r = new BigInteger();
- q.used = r.used = q.sign = r.sign = 0;
-#if BIGINTEGER_DEBUG
- Debug.Assert(q.sane());
- Debug.Assert(r.sane());
-#endif
- return;
- }
-
- uqrm(x, y, out q, out r);
- if (x.sign != y.sign && q.sign != 0) {
- q.sign = -1;
- }
- if (x.sign == -1 && r.sign != 0) {
- r.sign = -1;
- }
-
-#if BIGINTEGER_DEBUG
- Debug.Assert(q.sane());
- Debug.Assert(r.sane());
-#endif
- }
-
-
- // Unsigned ops (private)
-
- static int ucmp(BigInteger x, BigInteger y) {
- int i;
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
-#endif
- if (x.used < y.used) {
- return -1;
- }
- if (x.used > y.used) {
- return 1;
- }
- for (i = x.used-1; i >= 0; i--) {
- if (x.body[i] < y.body[i]) {
- return -1;
- }
- if (x.body[i] > y.body[i]) {
- return 1;
- }
- }
- return 0;
- }
-
- static void uadd ( BigInteger x, BigInteger y, BigInteger res ) {
- int c, i, t, n;
- BigInteger longer;
-
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
- Debug.Assert (res.size == maxused_addsub(x,y));
-#endif
- res.used = res.size;
- res.body[res.used-1] = 0;
-
- if (x.used > y.used) {
- n = y.used;
- longer = x;
- }
- else {
- n = x.used;
- longer = y;
- }
-
- c = 0;
- for (i = 0; i < n; i++) {
- t = x.body[i] + y.body[i] + c;
- if (t >= B_BASE) {
- res.body[i] = (byte)(t-B_BASE);
- c = 1;
- }
- else {
- res.body[i] = (byte)t;
- c = 0;
- }
- }
-
- for (i = n; i < longer.used; i++) {
- t = longer.body[i] + c;
- if (t >= B_BASE) {
- res.body[i] = (byte)(t-B_BASE);
- }
- else {
- res.body[i] = (byte)t;
- c = 0;
- }
- }
- if (c > 0) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.used == longer.used+1);
-#endif
- res.body[longer.used] = (byte)c;
- }
-
- res.u_renormalise();
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sane());
-#endif
- }
-
- static void usub(BigInteger x, BigInteger y, BigInteger res) {
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
- Debug.Assert(x.used >= y.used);
- Debug.Assert(res.size == maxused_addsub(x,y));
-#endif
-
- int b, i, t;
-
- b = 0;
- for (i = 0; i < y.used; i++) {
- t = x.body[i] - y.body[i] - b;
- if (t < 0) {
- res.body[i] = (byte)(t + B_BASE);
- b = 1;
- }
- else {
- res.body[i] = (byte)t;
- b = 0;
- }
- }
-
- for (i = y.used; i < x.used; i++) {
- t = x.body[i] - b;
- if (t < 0) {
- res.body[i] = (byte)(t + B_BASE);
- }
- else {
- res.body[i] = (byte)t;
- b = 0;
- }
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert (b == 0);
-#endif
-
- res.used = x.used;
- res.u_renormalise();
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sane());
-#endif
- }
-
- static void umul(BigInteger x, BigInteger y, BigInteger res) {
- int i, j, carry;
-
-#if BIGINTEGER_DEBUG
- Debug.Assert(x.sane());
- Debug.Assert(y.sane());
- Debug.Assert(res.size == maxused_mul(x,y));
-#endif
-
- for (j = 0; j < y.used; j++) {
- res.body[j] = 0;
- }
-
- for (i = 0; i < x.used; i++) {
- carry = 0;
- for (j = 0; j < y.used; j++) {
- carry += res.body[i+j] + x.body[i]*y.body[j];
- res.body[i+j] = (byte)(carry % B_BASE);
- carry /= B_BASE;
-#if BIGINTEGER_DEBUG
- Debug.Assert (carry < B_BASE);
-#endif
- }
- res.body[i+y.used] = (byte)carry;
- }
-
- res.used = x.used+y.used;
- res.u_renormalise();
-#if BIGINTEGER_DEBUG
- Debug.Assert(res.sane());
-#endif
- }
-
- static void uqrm(BigInteger dend, BigInteger isor, out BigInteger dres, out BigInteger mres) {
- int i, j, t, vh, delta, carry, scaleup;
- byte [] dend_body, isor_body, tmp;
- bool toolarge;
-
-#if BIGINTEGER_DEBUG
- Debug.Assert(isor.sane());
- Debug.Assert(dend.sane());
- Debug.Assert(isor.used > 0); // against division by zero
-#endif
- dres = new BigInteger();
- mres = new BigInteger();
- mres.size = dres.size = maxused_qrm(isor, dend);
- dres.body = new byte[dres.size];
- mres.body = new byte[mres.size];
-
- if (dend.used < isor.used) {
- // Result of division must be zero, since dividend has
- // fewer digits than the divisor. Remainder is the
- // original dividend.
- dres.used = 0;
- mres.used = dend.used;
- for (j = 0; j < mres.used; j++) {
- mres.body[j] = dend.body[j];
- }
- dres.u_renormalise();
- mres.u_renormalise();
-#if BIGINTEGER_DEBUG
- Debug.Assert(dres.sane());
- Debug.Assert(mres.sane());
-#endif
- return;
- }
-
- if (isor.used == 1) {
-
- // Simple case; divisor is a single digit
- carry = 0;
- for (j = dend.used-1; j >= 0; j--) {
- carry += dend.body[j];
- dres.body[j] = (byte)(carry/isor.body[0]);
- carry = B_BASE*(carry%isor.body[0]);
- }
- carry /= B_BASE;
- dres.used = dend.used;
- dres.u_renormalise();
-
- // Remainder is the final carry value
- mres.used = 0;
- if (carry > 0) {
- mres.used = 1;
- mres.body[0] = (byte)carry;
- }
- dres.u_renormalise();
- mres.u_renormalise();
-#if BIGINTEGER_DEBUG
- Debug.Assert(dres.sane());
- Debug.Assert(mres.sane());
-#endif
- return;
-
- }
- else {
-
- // Complex case: both dividend and divisor have two or more digits.
-#if BIGINTEGER_DEBUG
- Debug.Assert(isor.used >= 2);
- Debug.Assert(dend.used >= 2);
-#endif
-
- // Allocate space for a copy of both dividend and divisor, since we
- // need to mess with them. Also allocate tmp as a place to hold
- // values of the form quotient_digit * divisor.
- dend_body = new byte[dend.used+1];
- isor_body = new byte[isor.used];
- tmp = new byte[isor.used+1];
-
- // Calculate a scaling-up factor, and multiply both divisor and
- // dividend by it. Doing this reduces the number of corrections
- // needed to the quotient-digit-estimates made in the loop below,
- // and thus speeds up division, but is not actually needed to
- // get the correct results. The scaleup factor should not increase
- // the number of digits needed to represent either the divisor
- // (since the factor is derived from it) or the dividend (since
- // we already gave it a new leading zero).
- scaleup = B_BASE / (1 + isor.body[isor.used-1]);
-#if BIGINTEGER_DEBUG
- Debug.Assert (1 <= scaleup && scaleup <= B_BASE/2);
-#endif
-
- if (scaleup == 1) {
- // Don't bother to multiply; just copy.
- for (j = 0; j < dend.used; j++) {
- dend_body[j] = dend.body[j];
- }
- for (j = 0; j < isor.used; j++) {
- isor_body[j] = isor.body[j];
- }
-
- // Extend dividend with leading zero.
- dend_body[dend.used] = tmp[isor.used] = 0;
-
- }
- else {
- carry = 0;
- for (j = 0; j < isor.used; j++) {
- t = scaleup * isor.body[j] + carry;
- isor_body[j] = (byte)(t % B_BASE);
- carry = t / B_BASE;
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert (carry == 0);
-#endif
-
- carry = 0;
- for (j = 0; j < dend.used; j++) {
- t = scaleup * dend.body[j] + carry;
- dend_body[j] = (byte)(t % B_BASE);
- carry = t / B_BASE;
- }
- dend_body[dend.used] = (byte)carry;
- tmp[isor.used] = 0;
- }
-
- // For each quotient digit ...
- for (i = dend.used; i >= isor.used; i--) {
-#if BIGINTEGER_DEBUG
- Debug.Assert (i-2 >= 0);
- Debug.Assert (i <= dend.used);
- Debug.Assert (isor.used >= 2);
-#endif
-
-#if BIGINTEGER_DEBUG
- Console.WriteLine("\n---------\nqdigit {0}", i );
- Console.Write("dend_body is ");
- for (j = dend.used; j>= 0; j--) {
- Console.Write("{0} ",dend_body[j]);
- }
- Console.Write("\n");
-#endif
- // Make a guess vh of the quotient digit
- vh = (B_BASE*B_BASE*dend_body[i] + B_BASE*dend_body[i-1] + dend_body[i-2])
- /
- (B_BASE*isor_body[isor.used-1] + isor_body[isor.used-2]);
- if (vh > B_BASE-1) {
- vh = B_BASE-1;
- }
-#if BIGINTEGER_DEBUG
- Console.WriteLine("guess formed from {0} {1} {2} {3} {4}",
- dend_body[i], dend_body[i-1] , dend_body[i-2],
- isor_body[isor.used-1], isor_body[isor.used-2]);
- Console.WriteLine("guess is {0}", vh );
-#endif
- // Check if vh is too large (by 1). Calculate vh * isor into tmp
- // and see if it exceeds the same length prefix of dend. If so,
- // vh needs to be decremented.
- carry = 0;
- for (j = 0; j < isor.used; j++) {
- t = vh * isor_body[j] + carry;
- tmp[j] = (byte)(t % B_BASE);
- carry = t / B_BASE;
- }
- tmp[isor.used] = (byte)carry;
- delta = i - isor.used;
-#if BIGINTEGER_DEBUG
- Console.WriteLine("final carry is {0}", carry);
- Console.Write("vh * isor is " );
- for (j = isor.used; j >=0; j--) {
- Console.Write("{0} ",tmp[j]);Console.Write("\n");
- }
- Console.WriteLine("delta = {0}", delta );
-#endif
- toolarge = false;
- for (j = isor.used; j >= 0; j--) {
-#if BIGINTEGER_DEBUG
- Console.Write ( "({0},{1}) ", (int)(tmp[j]), (int)(dend_body[j+delta]) );
-#endif
- if (tmp[j] > dend_body[j+delta]) {
- toolarge=true;
- break;
- }
- if (tmp[j] < dend_body[j+delta]) {
- break;
- }
- }
-
- // If we did guess too large, decrement vh and subtract a copy of
- // isor from tmp. This had better not go negative!
- if (toolarge) {
-#if BIGINTEGER_DEBUG
- Console.WriteLine ( "guess too large" );
-#endif
- vh--;
- carry = 0;
- for (j = 0; j < isor.used; j++) {
- if (carry + isor_body[j] > tmp[j]) {
- tmp[j] = (byte)((B_BASE + tmp[j]) - isor_body[j] - carry);
- carry = 1;
- }
- else {
- tmp[j] = (byte)(tmp[j] - isor_body[j] - carry);
- carry = 0;
- }
- }
- //if (carry > 0) {pp(isor);pp(dend);};
- //Debug.Assert(carry == 0);
- if (carry > 0) {
- Debug.Assert(tmp[isor.used] > 0);
- tmp[isor.used]--;
- }
-#if BIGINTEGER_DEBUG
- Console.Write("after adjustment of tmp ");
- for (j = isor.used; j >=0; j--) {
- Console.Write("{0} ",tmp[j]);
- }
- Console.Write("\n");
-#endif
- }
-
- // Now vh really is the i'th quotient digit.
- // Subtract (tmp << delta) from
- // the dividend.
- carry = 0;
- for (j = 0; j <= isor.used; j++) {
- if (carry + tmp[j] > dend_body[j+delta]) {
- dend_body[j+delta] = (byte)((B_BASE+dend_body[j+delta]) - tmp[j]
- - carry);
- carry = 1;
- }
- else {
- dend_body[j+delta] = (byte)(dend_body[j+delta] - tmp[j] - carry);
- carry = 0;
- }
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert(carry==0);
-#endif
-
-#if BIGINTEGER_DEBUG
- Console.Write("after final sub ");
- for(j=dend.used; j>=0; j--) Console.Write("{0} ", dend_body[j]);
- Console.Write("\n");
-#endif
-
- // park vh in the result array
-#if DEBUG_SAINTEGER_UDIV
- Console.WriteLine("[{0}] <- {1}", i-isor.used, vh );
-#endif
- dres.body[i-isor.used] = (byte)vh;
- }
- }
-
- // Now we've got all the quotient digits. Zap leading zeroes.
- dres.used = dend.used - isor.used + 1;
- dres.u_renormalise();
-#if BIGINTEGER_DEBUG
- Debug.Assert(dres.sane());
-#endif
-
- // The remainder is in dend_body. Copy, divide by the original scaling
- // factor, and zap leading zeroes.
- mres.used = dend.used;
- for (j = 0; j < dend.used; j++) {
- mres.body[j] = dend_body[j];
- }
- mres.u_renormalise();
-#if BIGINTEGER_DEBUG
- Debug.Assert(mres.sane());
-#endif
-
- if (scaleup > 1) {
- carry = 0;
- for (j = mres.used-1; j >= 0; j--) {
- carry += mres.body[j];
- mres.body[j] = (byte)(carry/scaleup);
- carry = B_BASE*(carry%scaleup);
- }
-#if BIGINTEGER_DEBUG
- Debug.Assert (carry == 0);
-#endif
- mres.u_renormalise();
-#if BIGINTEGER_DEBUG
- Debug.Assert(mres.sane());
-#endif
- }
-
- }
-
-
- // Test framework
-
-#if BIGINTEGER_DEBUG
- public static void Test ( ) {
- int i, j, t, k, m;
- BigInteger bi, bj, bk, bm;
-
- BigInteger a, b;
- a = new BigInteger(1);
- for (int n = 1; n <= 10; n++) {
- b = new BigInteger(n);
- a *= n;
- }
- Console.WriteLine("{0}", (double)a);
-
- for (i = -10007; i <= 10007; i++) {
- Console.WriteLine ( "i = {0}", i );
-
- bi = new BigInteger(i);
- t = (int)bi;
- Debug.Assert(i == t);
-
- for (j = -10007; j <= 10007; j++) {
- bj = new BigInteger(j);
- t = (int)bj;
- Debug.Assert(j == t);
- bk = bi + bj;
- k = (int)bk;
- if (i+j != k) {
- bi.ToString();
- bj.ToString();
- bk.ToString();
- Debug.Assert(i + j == k);
- }
-
- bk = bi - bj;
- k = (int)bk;
- if (i-j != k) {
- bi.ToString();
- bj.ToString();
- bk.ToString();
- Debug.Assert(i - j == k);
- }
-
- bk = bi * bj;
- k = (int)bk;
- if (i*j != k) {
- bi.ToString();
- bj.ToString();
- bk.ToString();
- Debug.Assert(i * j == k);
- }
-
- if (j != 0) {
- QuotientRemainder(bi, bj, out bk, out bm);
- k = (int)bk;
- m = (int)bm;
- Debug.Assert(k == i / j);
- Debug.Assert(m == i % j);
- }
- }
- }
- Console.WriteLine("done");
- }
-#endif
-
-}