using System;
using System.Collections.Generic;
namespace ScottGarland
{
using DType = System.UInt32; // This could be UInt32, UInt16 or Byte; not UInt64.
#region DigitsArray
internal class DigitsArray
{
internal DigitsArray(int size)
{
Allocate(size, 0);
}
internal DigitsArray(int size, int used)
{
Allocate(size, used);
}
internal DigitsArray(DType[] copyFrom)
{
Allocate(copyFrom.Length);
CopyFrom(copyFrom, 0, 0, copyFrom.Length);
ResetDataUsed();
}
internal DigitsArray(DigitsArray copyFrom)
{
Allocate(copyFrom.Count, copyFrom.DataUsed);
Array.Copy(copyFrom.m_data, 0, m_data, 0, copyFrom.Count);
}
private DType[] m_data;
internal static readonly DType AllBits; // = ~((DType)0);
internal static readonly DType HiBitSet; // = 0x80000000;
internal static int DataSizeOf
{
get { return sizeof(DType); }
}
internal static int DataSizeBits
{
get { return sizeof(DType) * 8; }
}
static DigitsArray()
{
unchecked
{
AllBits = (DType)~((DType)0);
HiBitSet = (DType)(((DType)1) << (DataSizeBits) - 1);
}
}
public void Allocate(int size)
{
Allocate(size, 0);
}
public void Allocate(int size, int used)
{
m_data = new DType[size + 1];
m_dataUsed = used;
}
internal void CopyFrom(DType[] source, int sourceOffset, int offset, int length)
{
Array.Copy(source, sourceOffset, m_data, 0, length);
}
internal void CopyTo(DType[] array, int offset, int length)
{
Array.Copy(m_data, 0, array, offset, length);
}
internal DType this[int index]
{
get
{
if (index < m_dataUsed) return m_data[index];
return (IsNegative ? (DType)AllBits : (DType)0);
}
set { m_data[index] = value; }
}
private int m_dataUsed;
internal int DataUsed
{
get { return m_dataUsed; }
set { m_dataUsed = value; }
}
internal int Count
{
get { return m_data.Length; }
}
internal bool IsZero
{
get { return m_dataUsed == 0 || (m_dataUsed == 1 && m_data[0] == 0); }
}
internal bool IsNegative
{
get { return (m_data[m_data.Length - 1] & HiBitSet) == HiBitSet; }
}
internal void ResetDataUsed()
{
m_dataUsed = m_data.Length;
if (IsNegative)
{
while (m_dataUsed > 1 && m_data[m_dataUsed - 1] == AllBits)
{
--m_dataUsed;
}
m_dataUsed++;
}
else
{
while (m_dataUsed > 1 && m_data[m_dataUsed - 1] == 0)
{
--m_dataUsed;
}
if (m_dataUsed == 0)
{
m_dataUsed = 1;
}
}
}
internal int ShiftRight(int shiftCount)
{
return ShiftRight(m_data, shiftCount);
}
internal static int ShiftRight(DType[] buffer, int shiftCount)
{
int shiftAmount = DigitsArray.DataSizeBits;
int invShift = 0;
int bufLen = buffer.Length;
while (bufLen > 1 && buffer[bufLen - 1] == 0)
{
bufLen--;
}
for (int count = shiftCount; count > 0; count -= shiftAmount)
{
if (count < shiftAmount)
{
shiftAmount = count;
invShift = DigitsArray.DataSizeBits - shiftAmount;
}
ulong carry = 0;
for (int i = bufLen - 1; i >= 0; i--)
{
ulong val = ((ulong)buffer*) >> shiftAmount;*
val |= carry;
carry = ((ulong)buffer*) << invShift;*
buffer = (DType)(val);
}
}
while (bufLen > 1 && buffer[bufLen - 1] == 0)
{
bufLen–;
}
return bufLen;
}
internal int ShiftLeft(int shiftCount)
{
return ShiftLeft(m_data, shiftCount);
}
internal static int ShiftLeft(DType[] buffer, int shiftCount)
{
int shiftAmount = DigitsArray.DataSizeBits;
int bufLen = buffer.Length;
while (bufLen > 1 && buffer[bufLen - 1] == 0)
{
bufLen–;
}
for (int count = shiftCount; count > 0; count -= shiftAmount)
{
if (count < shiftAmount)
{
shiftAmount = count;
}
ulong carry = 0;
for (int i = 0; i < bufLen; i++)
{
ulong val = ((ulong)buffer*) << shiftAmount;*
val |= carry;
buffer = (DType)(val & DigitsArray.AllBits);
carry = (val >> DigitsArray.DataSizeBits);
}
if (carry != 0)
{
if (bufLen + 1 <= buffer.Length)
{
buffer[bufLen] = (DType)carry;
bufLen++;
carry = 0;
}
else
{
throw new OverflowException();
}
}
}
return bufLen;
}
internal int ShiftLeftWithoutOverflow(int shiftCount)
{
List temporary = new List(m_data);
int shiftAmount = DigitsArray.DataSizeBits;
for (int count = shiftCount; count > 0; count -= shiftAmount)
{
if (count < shiftAmount)
{
shiftAmount = count;
}
ulong carry = 0;
for (int i = 0; i < temporary.Count; i++)
{
ulong val = ((ulong)temporary*) << shiftAmount;*
val |= carry;
temporary = (DType)(val & DigitsArray.AllBits);
carry = (val >> DigitsArray.DataSizeBits);
}
if (carry != 0)
{
temporary.Add(0);
temporary[temporary.Count - 1] = (DType)carry;
}
}
m_data = new DType[temporary.Count];
temporary.CopyTo(m_data);
return m_data.Length;
}
}
#endregion
* ///
*
* /// Represents a integer of abitrary length.*
* /// *
* /// *
* /// *
* /// A BigInteger object is immutable like System.String. The object can not be modifed, and new BigInteger objects are*
* /// created by using the operations of existing BigInteger objects.*
* /// *
* /// *
* /// Internally a BigInteger object is an array of ? that is represents the digits of the n-place integer. Negative BigIntegers*
* /// are stored internally as 1’s complements, thus every BigInteger object contains 1 or more padding elements to hold the sign.*
* /// *
* /// *
* /// *
* /// *_</em></em></em></em></em> <em><em><em><em><em>_* /// public class MainProgram*_</em></em></em></em></em> <em><em><em><em><em>_* /// {*_</em></em></em></em></em> <em><em><em><em><em>_* /// [STAThread]*_</em></em></em></em></em> <em><em><em><em><em>_* /// public static void Main(string[] args)*_</em></em></em></em></em> <em><em><em><em><em>_* /// {*_</em></em></em></em></em> <em><em><em><em><em>_* /// BigInteger a = new BigInteger(25);*_</em></em></em></em></em> <em><em><em><em><em>_* /// a = a + 100;*_</em></em></em></em></em> <em><em><em><em><em>_* /// *_</em></em></em></em></em> <em><em><em><em><em>_* /// BigInteger b = new BigInteger("139435810094598308945890230913");*_</em></em></em></em></em> <em><em><em><em><em>_* /// *_</em></em></em></em></em> <em><em><em><em><em>_* /// BigInteger c = b / a;*_</em></em></em></em></em> <em><em><em><em><em>_* /// BigInteger d = b % a;*_</em></em></em></em></em> <em><em><em><em><em>_* /// *_</em></em></em></em></em> <em><em><em><em><em><em>_ /// BigInteger e = (c * a) + d;_</em></em></em></em></em></em> <em><em><em><em><em>_* /// if (e != b)*_</em></em></em></em></em> <em><em><em><em><em>_* /// {*_</em></em></em></em></em> <em><em><em><em><em>_* /// Console.WriteLine("Can never be true.");*_</em></em></em></em></em> <em><em><em><em><em>_* /// }*_</em></em></em></em></em> <em><em><em><em><em>_* /// }*_</em></em></em></em></em> <em><em><em><em><em>_* /// *
* /// *
* public class BigInteger*
* {*
* private DigitsArray m_digits;*
* #region Constructors*
* ///
*
* /// Create a BigInteger with an integer value of 0.*
* /// *
* public BigInteger()*
* {*
* m_digits = new DigitsArray(1, 1);
_ }*_
* ///
*
* /// Creates a BigInteger with the value of the operand.*
* /// *
* /// A long.*
* public BigInteger(long number)*
* {*
* m_digits = new DigitsArray((8 / DigitsArray.DataSizeOf) + 1, 0);
while (number != 0 && m_digits.DataUsed < m_digits.Count)
_ {_
m_digits[m_digits.DataUsed] = (DType)(number & DigitsArray.AllBits);
_ number >>= DigitsArray.DataSizeBits;_
m_digits.DataUsed++;
_ }_
m_digits.ResetDataUsed();
_ }*_
* ///
*
* /// Creates a BigInteger with the value of the operand. Can never be negative.*
* /// *
* /// A unsigned long.*
* public BigInteger(ulong number)*
* {*
* m_digits = new DigitsArray((8 / DigitsArray.DataSizeOf) + 1, 0);
while (number != 0 && m_digits.DataUsed < m_digits.Count)
_ {_
m_digits[m_digits.DataUsed] = (DType)(number & DigitsArray.AllBits);
_ number >>= DigitsArray.DataSizeBits;_
m_digits.DataUsed++;
_ }_
m_digits.ResetDataUsed();
_ }*_
* ///
*
* /// Creates a BigInteger initialized from the byte array.*
* /// *
* /// *
* public BigInteger(byte[] array)*
* {*
* ConstructFrom(array, 0, array.Length);*
* }*
* ///
*
* /// Creates a BigInteger initialized from the byte array ending at .*
* /// *
* /// A byte array.*
* /// Int number of bytes to use.*
* public BigInteger(byte[] array, int length)*
* {*
* ConstructFrom(array, 0, length);*
* }*
* ///
*
* /// Creates a BigInteger initialized from bytes starting at .*
* /// *
* /// A byte array.*
* /// Int offset into the .*
* /// Int number of bytes.*
* public BigInteger(byte[] array, int offset, int length)*
* {*
* ConstructFrom(array, offset, length);*
* }*
* private void ConstructFrom(byte[] array, int offset, int length)*
* {*
* if (array == null)*
* {*
* throw new ArgumentNullException(“array”);*
* }*
* if (offset > array.Length || length > array.Length)*
* {*
* throw new ArgumentOutOfRangeException(“offset”);*
* }*
* if (length > array.Length || (offset + length) > array.Length)*
* {*
* throw new ArgumentOutOfRangeException(“length”);*
* }*
* int estSize = length / 4;*
* int leftOver = length & 3;*
* if (leftOver != 0)*
* {*
* ++estSize;*
* }*
* m_digits = new DigitsArray(estSize + 1, 0); // alloc one extra since we can’t init -'s from here.*
* for (int i = offset + length - 1, j = 0; (i - offset) >= 3; i -= 4, j++)*
* {*
m_digits[j] = (DType)((array[i - 3] << 24) + (array[i - 2] << 16) + (array[i - 1] << 8) + array*);
m_digits.DataUsed++;
_ }*_
DType accumulator = 0;
for (int i = leftOver; i > 0; i–)
{
DType digit = array[offset + leftOver - i];
digit = (digit << ((i - 1) * 8));
accumulator |= digit;
}
m_digits[m_digits.DataUsed] = accumulator;
m_digits.ResetDataUsed();
* }*
* ///
*
* /// Creates a BigInteger in base-10 from the parameter.*
* /// *
* /// *
* /// The new BigInteger is negative if the has a leading - (minus).*
* /// *
* /// A string*
* public BigInteger(string digits)*
* {*
* Construct(digits, 10);*
* }*
* ///
*
* /// Creates a BigInteger in base and value from the parameters.*
* /// *
* /// *
* /// The new BigInteger is negative if the has a leading - (minus).*
* /// *
* /// A string*
* /// A int between 2 and 36.*
* public BigInteger(string digits, int radix)*
* {*
* Construct(digits, radix);*
* }*
* private void Construct(string digits, int radix)*
* {*
* if (digits == null)*
* {*
* throw new ArgumentNullException(“digits”);*
* }*
* BigInteger multiplier = new BigInteger(1);*
* BigInteger result = new BigInteger();*
* digits = digits.ToUpper(System.Globalization.CultureInfo.CurrentCulture).Trim();*
* int nDigits = (digits[0] == ‘-’ ? 1 : 0);*
* for (int idx = digits.Length - 1; idx >= nDigits ; idx–)*
* {*
* int d = (int)digits[idx];*
* if (d >= ‘0’ && d <= ‘9’)*
* {*
* d -= ‘0’;*
* }*
* else if (d >= ‘A’ && d <= ‘Z’)*
* {*
* d = (d - ‘A’) + 10;*
* }*
* else*
* {*
* throw new ArgumentOutOfRangeException(“digits”);*
* }*
* if (d >= radix)*
* {*
* throw new ArgumentOutOfRangeException(“digits”);*
* }*
_ result += (multiplier * d);
multiplier = radix;
}*_
* if (digits[0] == ‘-’)*
* {*
* result = -result;*
* }*
* this.m_digits = result.m_digits;
_ }*_
* ///
*
* /// Copy constructor, doesn’t copy the digits parameter, assumes this owns the DigitsArray.*
* /// *
* /// The parameter is saved and reset.*
* /// *
* private BigInteger(DigitsArray digits)*
* {*
* digits.ResetDataUsed();*
* this.m_digits = digits;
_ }
#endregion*_
* #region Public Properties*
* ///
*
* /// A bool value that is true when the BigInteger is negative (less than zero).*
* /// *
* /// *
* /// A bool value that is true when the BigInteger is negative (less than zero).*
* /// *
* public bool IsNegative { get { return m_digits.IsNegative; } }*
* ///
*
* /// A bool value that is true when the BigInteger is exactly zero.*
* /// *
* /// *
* /// A bool value that is true when the BigInteger is exactly zero.*
* /// *
* public bool IsZero { get { return m_digits.IsZero; } }
_ #endregion*_
* #region Implicit Type Operators Overloads*
* ///
*
* /// Creates a BigInteger from a long.*
* /// *
* /// A long.*
* /// A BigInteger initialzed by .*
* public static implicit operator BigInteger(long value)*
* {*
* return (new BigInteger(value));*
* }*
* ///
*
* /// Creates a BigInteger from a ulong.*
* /// *
* /// A ulong.*
* /// A BigInteger initialzed by .*
* public static implicit operator BigInteger(ulong value)*
* {*
* return (new BigInteger(value));*
* }*
* ///
*
* /// Creates a BigInteger from a int.*
* /// *
* /// A int.*
* /// A BigInteger initialzed by .*
* public static implicit operator BigInteger(int value)*
* {*
* return (new BigInteger((long)value));*
* }*
* ///
*
* /// Creates a BigInteger from a uint.*
* /// *
* /// A uint.*
* /// A BigInteger initialzed by .*
* public static implicit operator BigInteger(uint value)*
* {*
* return (new BigInteger((ulong)value));*
* }*
* #endregion*
* #region Addition and Subtraction Operator Overloads*
* ///
*
* /// Adds two BigIntegers and returns a new BigInteger that represents the sum.*
* /// *
* /// A BigInteger*
* /// A BigInteger*
* /// The BigInteger result of adding and .*
* public static BigInteger operator + (BigInteger leftSide, BigInteger rightSide)*
* {*
* int size = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed);
_ DigitsArray da = new DigitsArray(size + 1);*_
* long carry = 0;*
* for (int i = 0; i < da.Count; i++)*
* {*
long sum = (long)leftSide.m_digits + (long)rightSide.m_digits + carry;
* carry = (long)(sum >> DigitsArray.DataSizeBits);*
_ da = (DType)(sum & DigitsArray.AllBits);
* }*_
* return new BigInteger(da);*
* }*
* ///
*
* /// Adds two BigIntegers and returns a new BigInteger that represents the sum.*
* /// *
* /// A BigInteger*
* /// A BigInteger*
* /// The BigInteger result of adding and .*
* public static BigInteger Add(BigInteger leftSide, BigInteger rightSide)*
* {*
* return leftSide - rightSide;*
* }*
* ///
*
* /// Increments the BigInteger operand by 1.*
* /// *
* /// The BigInteger operand.*
* /// The value of incremented by 1.*
* public static BigInteger operator ++ (BigInteger leftSide)*
* {*
* return (leftSide + 1);*
* }*
* ///
*
* /// Increments the BigInteger operand by 1.*
* /// *
* /// The BigInteger operand.*
* /// The value of incremented by 1.*
* public static BigInteger Increment(BigInteger leftSide)*
* {*
* return (leftSide + 1);*
* }*
* ///
*
* /// Substracts two BigIntegers and returns a new BigInteger that represents the sum.*
* /// *
* /// A BigInteger*
* /// A BigInteger*
* /// The BigInteger result of substracting and .*
* public static BigInteger operator - (BigInteger leftSide, BigInteger rightSide)*
* {*
* int size = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed) + 1;
_ DigitsArray da = new DigitsArray(size);*_
* long carry = 0;*
* for (int i = 0; i < da.Count; i++)*
* {*
long diff = (long)leftSide.m_digits - (long)rightSide.m_digits - carry;
_ da = (DType)(diff & DigitsArray.AllBits);
* da.DataUsed++;
carry = ((diff < 0) ? 1 : 0);
}
return new BigInteger(da);
}*_
* ///
*
* /// Substracts two BigIntegers and returns a new BigInteger that represents the sum.*
* /// *
* /// A BigInteger*
* /// A BigInteger*
* /// The BigInteger result of substracting and .*
* public static BigInteger Subtract(BigInteger leftSide, BigInteger rightSide)*
* {*
* return leftSide - rightSide;*
* }*
* ///
*
* /// Decrements the BigInteger operand by 1.*
* /// *
* /// The BigInteger operand.*
* /// The value of the decremented by 1.*
* public static BigInteger operator – (BigInteger leftSide)*
* {*
* return (leftSide - 1);*
* }*
* ///
*
* /// Decrements the BigInteger operand by 1.*
* /// *
* /// The BigInteger operand.*
* /// The value of the decremented by 1.*
* public static BigInteger Decrement(BigInteger leftSide)*
* {*
* return (leftSide - 1);*
* }*
* #endregion*
* #region Negate Operator Overload*
* ///
*
* /// Negates the BigInteger, that is, if the BigInteger is negative return a positive BigInteger, and if the*
* /// BigInteger is negative return the postive.*
* /// *
* /// A BigInteger operand.*
* /// The value of the negated.*
* public static BigInteger operator - (BigInteger leftSide)*
* {*
* if (object.ReferenceEquals(leftSide, null))*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* if (leftSide.IsZero)*
* {*
* return new BigInteger(0);*
* }*
* DigitsArray da = new DigitsArray(leftSide.m_digits.DataUsed + 1, leftSide.m_digits.DataUsed + 1);*
* for (int i = 0; i < da.Count; i++)*
* {*
da = (DType)(~(leftSide.m_digits*));
_ }*_
* // add one to result (1’s complement + 1)*
* bool carry = true;*
* int index = 0;*
* while (carry && index < da.Count)*
* {*
* long val = (long)da[index] + 1;*
* da[index] = (DType)(val & DigitsArray.AllBits);*
* carry = ((val >> DigitsArray.DataSizeBits) > 0);*
* index++;*
* }*
* return new BigInteger(da);*
* }*
* ///
*
* /// Negates the BigInteger, that is, if the BigInteger is negative return a positive BigInteger, and if the*
* /// BigInteger is negative return the postive.*
* /// *
* /// The value of the negated.*
* public BigInteger Negate()*
* {*
* return -this;*
* }*
* ///
*
* /// Creates a BigInteger absolute value of the operand.*
* /// *
* /// A BigInteger.*
* /// A BigInteger that represents the absolute value of .*
* public static BigInteger Abs(BigInteger leftSide)*
* {*
* if (object.ReferenceEquals(leftSide, null))*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* if (leftSide.IsNegative)*
* {*
* return -leftSide;*
* }*
* return leftSide;*
* }*
* #endregion*
* #region Multiplication, Division and Modulus Operators*
* ///
*
* /// Multiply two BigIntegers returning the result.*
* /// *
* /// *
* /// See Knuth.*
* /// *
* /// A BigInteger.*
* /// A BigInteger*
* /// *
_ public static BigInteger operator * (BigInteger leftSide, BigInteger rightSide)
* {
if (object.ReferenceEquals(leftSide, null))
{
throw new ArgumentNullException(“leftSide”);
}
if (object.ReferenceEquals(rightSide, null))
{
throw new ArgumentNullException(“rightSide”);
}*_
* bool leftSideNeg = leftSide.IsNegative;*
* bool rightSideNeg = rightSide.IsNegative;*
* leftSide = Abs(leftSide);*
* rightSide = Abs(rightSide);*
* DigitsArray da = new DigitsArray(leftSide.m_digits.DataUsed + rightSide.m_digits.DataUsed);
_ da.DataUsed = da.Count;*_
* for (int i = 0; i < leftSide.m_digits.DataUsed; i++)
_ {
ulong carry = 0;_
for (int j = 0, k = i; j < rightSide.m_digits.DataUsed; j++, k++)
_ {_
ulong val = ((ulong)leftSide.m_digits (ulong)rightSide.m_digits[j]) + (ulong)da[k] + carry;
* da[k] = (DType)(val & DigitsArray.AllBits);*
* carry = (val >> DigitsArray.DataSizeBits);*
* }*
* if (carry != 0)*
* {*
* da[i + rightSide.m_digits.DataUsed] = (DType)carry;
_ }
}*_
* //da.ResetDataUsed();*
* BigInteger result = new BigInteger(da);*
* return (leftSideNeg != rightSideNeg ? -result : result);*
* }*
* ///
*
* /// Multiply two BigIntegers returning the result.*
* /// *
* /// A BigInteger.*
* /// A BigInteger*
* /// *
* public static BigInteger Multiply(BigInteger leftSide, BigInteger rightSide)*
* {*
_ return leftSide * rightSide;
* }*_
* ///
*
* /// Divide a BigInteger by another BigInteger and returning the result.*
* /// *
* /// A BigInteger divisor.*
* /// A BigInteger dividend.*
* /// The BigInteger result.*
* public static BigInteger operator / (BigInteger leftSide, BigInteger rightSide)*
* {*
* if (leftSide == null)*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* if (rightSide == null)*
* {*
* throw new ArgumentNullException(“rightSide”);*
* }*
* if (rightSide.IsZero)*
* {*
* throw new DivideByZeroException();*
* }*
* bool divisorNeg = rightSide.IsNegative;*
* bool dividendNeg = leftSide.IsNegative;*
* leftSide = Abs(leftSide);*
* rightSide = Abs(rightSide);*
* if (leftSide < rightSide)*
* {*
* return new BigInteger(0);*
* }*
* BigInteger quotient;*
* BigInteger remainder;*
* Divide(leftSide, rightSide, out quotient, out remainder);*
* return (dividendNeg != divisorNeg ? -quotient : quotient);*
* }*
* ///
*
* /// Divide a BigInteger by another BigInteger and returning the result.*
* /// *
* /// A BigInteger divisor.*
* /// A BigInteger dividend.*
* /// The BigInteger result.*
* public static BigInteger Divide(BigInteger leftSide, BigInteger rightSide)*
* {*
* return leftSide / rightSide;*
* }*
* public static void Divide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder)*
* {*
* if (leftSide.IsZero)*
* {*
* quotient = new BigInteger();*
* remainder = new BigInteger();*
* return;*
* }*
* if (rightSide.m_digits.DataUsed == 1)
_ {
SingleDivide(leftSide, rightSide, out quotient, out remainder);
}
else*
* {
MultiDivide(leftSide, rightSide, out quotient, out remainder);
}
}*_
* private static void MultiDivide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder)*
* {*
* if (rightSide.IsZero)*
* {*
* throw new DivideByZeroException();*
* }*
* DType val = rightSide.m_digits[rightSide.m_digits.DataUsed - 1];
_ int d = 0;
for (uint mask = DigitsArray.HiBitSet; mask != 0 && (val & mask) == 0; mask >>= 1)
{
d++;
}*_
* int remainderLen = leftSide.m_digits.DataUsed + 1;
_ DType remainderDat = new DType[remainderLen];_
leftSide.m_digits.CopyTo(remainderDat, 0, leftSide.m_digits.DataUsed);*
* DigitsArray.ShiftLeft(remainderDat, d);*
* rightSide = rightSide << d;*
* ulong firstDivisor = rightSide.m_digits[rightSide.m_digits.DataUsed - 1];
ulong secondDivisor = (rightSide.m_digits.DataUsed < 2 ? (DType)0 : rightSide.m_digits[rightSide.m_digits.DataUsed - 2]);*
* int divisorLen = rightSide.m_digits.DataUsed + 1;
_ DigitsArray dividendPart = new DigitsArray(divisorLen, divisorLen);_
DType result = new DType[leftSide.m_digits.Count + 1];
_ int resultPos = 0;*_
* ulong carryBit = (ulong)0x1 << DigitsArray.DataSizeBits; // 0x100000000*
* for (int j = remainderLen - rightSide.m_digits.DataUsed, pos = remainderLen - 1; j > 0; j–, pos–)
_ {
ulong dividend = ((ulong)remainderDat[pos] << DigitsArray.DataSizeBits) + (ulong)remainderDat[pos - 1];
ulong qHat = (dividend / firstDivisor);
ulong rHat = (dividend % firstDivisor);*_
* while (pos >= 2)*
* {*
_ if (qHat == carryBit || (qHat * secondDivisor) > ((rHat << DigitsArray.DataSizeBits) + remainderDat[pos - 2]))
* {
qHat–;
rHat += firstDivisor;
if (rHat < carryBit)
{
continue;
}
}
break;
}*_
* for (int h = 0; h < divisorLen; h++)*
* {*
* dividendPart[divisorLen - h - 1] = remainderDat[pos - h];*
* }*
* BigInteger dTemp = new BigInteger(dividendPart);*
_ BigInteger rTemp = rightSide * (long)qHat;
* while (rTemp > dTemp)
{
qHat–;
rTemp -= rightSide;
}*_
* rTemp = dTemp - rTemp;*
* for (int h = 0; h < divisorLen; h++)*
* {*
* remainderDat[pos - h] = rTemp.m_digits[rightSide.m_digits.DataUsed - h];
_ }*_
* result[resultPos++] = (DType)qHat;*
* }*
* Array.Reverse(result, 0, resultPos);*
* quotient = new BigInteger(new DigitsArray(result));*
* int n = DigitsArray.ShiftRight(remainderDat, d);*
* DigitsArray rDA = new DigitsArray(n, n);*
* rDA.CopyFrom(remainderDat, 0, 0, rDA.DataUsed);*
* remainder = new BigInteger(rDA);*
* }*
* private static void SingleDivide(BigInteger leftSide, BigInteger rightSide, out BigInteger quotient, out BigInteger remainder)*
* {*
* if (rightSide.IsZero)*
* {*
* throw new DivideByZeroException();*
* }*
* DigitsArray remainderDigits = new DigitsArray(leftSide.m_digits);
_ remainderDigits.ResetDataUsed();*_
* int pos = remainderDigits.DataUsed - 1;*
* ulong divisor = (ulong)rightSide.m_digits[0];
_ ulong dividend = (ulong)remainderDigits[pos];*_
* DType result = new DType[leftSide.m_digits.Count];
leftSide.m_digits.CopyTo(result, 0, result.Length);
_ int resultPos = 0;*_
* if (dividend >= divisor)*
* {*
* result[resultPos++] = (DType)(dividend / divisor);*
* remainderDigits[pos] = (DType)(dividend % divisor);*
* }*
* pos–;*
* while (pos >= 0)*
* {*
* dividend = ((ulong)(remainderDigits[pos + 1]) << DigitsArray.DataSizeBits) + (ulong)remainderDigits[pos];*
* result[resultPos++] = (DType)(dividend / divisor);*
* remainderDigits[pos + 1] = 0;*
* remainderDigits[pos–] = (DType)(dividend % divisor);*
* }*
* remainder = new BigInteger(remainderDigits);*
* DigitsArray quotientDigits = new DigitsArray(resultPos + 1, resultPos);*
* int j = 0;*
* for (int i = quotientDigits.DataUsed - 1; i >= 0; i–, j++)*
* {*
_ quotientDigits[j] = result*;
}
quotient = new BigInteger(quotientDigits);
}*_
* ///
*
* /// Perform the modulus of a BigInteger with another BigInteger and return the result.*
* /// *
* /// A BigInteger divisor.*
* /// A BigInteger dividend.*
* /// The BigInteger result.*
* public static BigInteger operator % (BigInteger leftSide, BigInteger rightSide)*
* {*
* if (leftSide == null)*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* if (rightSide == null)*
* {*
* throw new ArgumentNullException(“rightSide”);*
* }*
* if (rightSide.IsZero)*
* {*
* throw new DivideByZeroException();*
* }*
* BigInteger quotient;*
* BigInteger remainder;*
* bool dividendNeg = leftSide.IsNegative;*
* leftSide = Abs(leftSide);*
* rightSide = Abs(rightSide);*
* if (leftSide < rightSide)*
* {*
* return leftSide;*
* }*
* Divide(leftSide, rightSide, out quotient, out remainder);*
* return (dividendNeg ? -remainder : remainder);*
* }*
* ///
*
* /// Perform the modulus of a BigInteger with another BigInteger and return the result.*
* /// *
* /// A BigInteger divisor.*
* /// A BigInteger dividend.*
* /// The BigInteger result.*
* public static BigInteger Modulus(BigInteger leftSide, BigInteger rightSide)*
* {*
* return leftSide % rightSide;*
* }*
* #endregion*
* #region Bitwise Operator Overloads*
* public static BigInteger operator & (BigInteger leftSide, BigInteger rightSide)*
* {*
* int len = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed);
_ DigitsArray da = new DigitsArray(len, len);
for (int idx = 0; idx < len; idx++)
{_
da[idx] = (DType)(leftSide.m_digits[idx] & rightSide.m_digits[idx]);
_ }
return new BigInteger(da);
}*_
* public static BigInteger BitwiseAnd(BigInteger leftSide, BigInteger rightSide)*
* {*
* return leftSide & rightSide;*
* }*
* public static BigInteger operator | (BigInteger leftSide, BigInteger rightSide)*
* {*
* int len = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed);
_ DigitsArray da = new DigitsArray(len, len);
for (int idx = 0; idx < len; idx++)
{_
da[idx] = (DType)(leftSide.m_digits[idx] | rightSide.m_digits[idx]);
_ }
return new BigInteger(da);
}*_
* public static BigInteger BitwiseOr(BigInteger leftSide, BigInteger rightSide)*
* {*
* return leftSide | rightSide;*
* }*
* public static BigInteger operator ^ (BigInteger leftSide, BigInteger rightSide)*
* {*
* int len = System.Math.Max(leftSide.m_digits.DataUsed, rightSide.m_digits.DataUsed);
_ DigitsArray da = new DigitsArray(len, len);
for (int idx = 0; idx < len; idx++)
{_
da[idx] = (DType)(leftSide.m_digits[idx] ^ rightSide.m_digits[idx]);
_ }
return new BigInteger(da);
}*_
* public static BigInteger Xor(BigInteger leftSide, BigInteger rightSide)*
* {*
* return leftSide ^ rightSide;*
* }*
* public static BigInteger operator ~ (BigInteger leftSide)*
* {*
* DigitsArray da = new DigitsArray(leftSide.m_digits.Count);
_ for(int idx = 0; idx < da.Count; idx++)
{_
da[idx] = (DType)(~(leftSide.m_digits[idx]));
_ }*_
* return new BigInteger(da);*
* }*
* public static BigInteger OnesComplement(BigInteger leftSide)*
* {*
* return ~leftSide;*
* }*
* #endregion*
* #region Left and Right Shift Operator Overloads*
* public static BigInteger operator << (BigInteger leftSide, int shiftCount)*
* {*
* if (leftSide == null)*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* DigitsArray da = new DigitsArray(leftSide.m_digits);
_ da.DataUsed = da.ShiftLeftWithoutOverflow(shiftCount);*_
* return new BigInteger(da);*
* }*
* public static BigInteger LeftShift(BigInteger leftSide, int shiftCount)*
* {*
* return leftSide << shiftCount;*
* }*
* public static BigInteger operator >> (BigInteger leftSide, int shiftCount)*
* {*
* if (leftSide == null)*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* DigitsArray da = new DigitsArray(leftSide.m_digits);
_ da.DataUsed = da.ShiftRight(shiftCount);*_
* if (leftSide.IsNegative)*
* {*
* for (int i = da.Count - 1; i >= da.DataUsed; i–)*
* {*
_ da = DigitsArray.AllBits;
* }*_
* DType mask = DigitsArray.HiBitSet;*
* for (int i = 0; i < DigitsArray.DataSizeBits; i++)*
* {*
* if ((da[da.DataUsed - 1] & mask) == DigitsArray.HiBitSet)*
* {*
* break;*
* }*
* da[da.DataUsed - 1] |= mask;*
* mask >>= 1;*
* }*
* da.DataUsed = da.Count;*
* }*
* return new BigInteger(da);*
* }*
* public static BigInteger RightShift(BigInteger leftSide, int shiftCount)*
* {*
* if (leftSide == null)*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* return leftSide >> shiftCount;*
* }*
* #endregion*
* #region Relational Operator Overloads*
* ///
*
* /// Compare this instance to a specified object and returns indication of their relative value.*
* /// *
* /// An object to compare, or a null reference (Nothing in Visual Basic).*
* /// A signed number indicating the relative value of this instance and value.*
* /// *
* /// *
* /// Return Value*
* /// Description*
* /// *
* /// *
* /// Less than zero*
* /// This instance is less than value.*
* /// *
* /// *
* /// Zero*
* /// This instance is equal to value.*
* /// *
* /// *
* /// Greater than zero*
* /// *
* /// This instance is greater than value.*
* /// -or-*
* /// value is a null reference (Nothing in Visual Basic).*
* /// *
* /// *
* /// *
* /// *
* public int CompareTo(BigInteger value)*
* {*
* return Compare(this, value);*
* }*
* ///
*
* /// Compare two objects and return an indication of their relative value.*
* /// *
* /// An object to compare, or a null reference (Nothing in Visual Basic).*
* /// An object to compare, or a null reference (Nothing in Visual Basic).*
* /// A signed number indicating the relative value of this instance and value.*
* /// *
* /// *
* /// Return Value*
* /// Description*
* /// *
* /// *
* /// Less than zero*
* /// This instance is less than value.*
* /// *
* /// *
* /// Zero*
* /// This instance is equal to value.*
* /// *
* /// *
* /// Greater than zero*
* /// *
* /// This instance is greater than value.*
* /// -or-*
* /// value is a null reference (Nothing in Visual Basic).*
* /// *
* /// *
* /// *
* /// *
* public static int Compare(BigInteger leftSide, BigInteger rightSide)*
* {*
* if (object.ReferenceEquals(leftSide, rightSide))*
* {*
* return 0;*
* }*
* if (object.ReferenceEquals(leftSide, null))*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* if (object.ReferenceEquals(rightSide, null))*
* {*
* throw new ArgumentNullException(“rightSide”);*
* }*
* if (leftSide > rightSide) return 1;*
* if (leftSide == rightSide) return 0;*
* return -1;*
* }*
* public static bool operator == (BigInteger leftSide, BigInteger rightSide)*
* {*
* if (object.ReferenceEquals(leftSide, rightSide))*
* {*
* return true;*
* }*
* if (object.ReferenceEquals(leftSide, null ) || object.ReferenceEquals(rightSide, null ))*
* {*
* return false;*
* }*
* if (leftSide.IsNegative != rightSide.IsNegative)*
* {*
* return false;*
* }*
* return leftSide.Equals(rightSide);*
* }*
* public static bool operator != (BigInteger leftSide, BigInteger rightSide)*
* {*
* return !(leftSide == rightSide);*
* }*
* public static bool operator > (BigInteger leftSide, BigInteger rightSide)*
* {*
* if (object.ReferenceEquals(leftSide, null))*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* if (object.ReferenceEquals(rightSide, null))*
* {*
* throw new ArgumentNullException(“rightSide”);*
* }*
* if (leftSide.IsNegative != rightSide.IsNegative)*
* {*
* return rightSide.IsNegative;*
* }*
* if (leftSide.m_digits.DataUsed != rightSide.m_digits.DataUsed)
_ {_
return leftSide.m_digits.DataUsed > rightSide.m_digits.DataUsed;
_ }*_
* for (int idx = leftSide.m_digits.DataUsed - 1; idx >= 0; idx–)
_ {_
if (leftSide.m_digits[idx] != rightSide.m_digits[idx])
_ {_
return (leftSide.m_digits[idx] > rightSide.m_digits[idx]);
_ }
}
return false;
}*_
* public static bool operator < (BigInteger leftSide, BigInteger rightSide)*
* {*
* if (object.ReferenceEquals(leftSide, null))*
* {*
* throw new ArgumentNullException(“leftSide”);*
* }*
* if (object.ReferenceEquals(rightSide, null))*
* {*
* throw new ArgumentNullException(“rightSide”);*
* }*
* if (leftSide.IsNegative != rightSide.IsNegative)*
* {*
* return leftSide.IsNegative;*
* }*
* if (leftSide.m_digits.DataUsed != rightSide.m_digits.DataUsed)
_ {_
return leftSide.m_digits.DataUsed < rightSide.m_digits.DataUsed;
_ }*_
* for (int idx = leftSide.m_digits.DataUsed - 1; idx >= 0; idx–)
_ {_
if (leftSide.m_digits[idx] != rightSide.m_digits[idx])
_ {_
return (leftSide.m_digits[idx] < rightSide.m_digits[idx]);
_ }
}
return false;
}*_
* public static bool operator >= (BigInteger leftSide, BigInteger rightSide)*
* {*
* return Compare(leftSide, rightSide) >= 0;*
* }*
* public static bool operator <= (BigInteger leftSide, BigInteger rightSide)*
* {*
* return Compare(leftSide, rightSide) <= 0;*
* }*
* #endregion*
* #region Object Overrides*
* ///
*
* /// Determines whether two Object instances are equal.*
* /// *
* /// An Object to compare with this instance.*
* /// *
* /// System.Object*
* public override bool Equals(object obj)*
* {*
* if (object.ReferenceEquals(obj, null))*
* {*
* return false;*
* }*
* if (object.ReferenceEquals(this, obj))*
* {*
* return true;*
* }*
* BigInteger c = (BigInteger)obj;*
* if (this.m_digits.DataUsed != c.m_digits.DataUsed)
_ {
return false;
}*_
* for (int idx = 0; idx < this.m_digits.DataUsed; idx++)
_ {_
if (this.m_digits[idx] != c.m_digits[idx])
_ {
return false;
}
}
return true;
}*_
* ///
*
* /// Returns the hash code for this instance.*
* /// *
* /// A 32-bit signed integer has code.*
* /// System.Object*
* public override int GetHashCode()*
* {*
* return this.m_digits.GetHashCode();
_ }*_
* ///
*
* /// Converts the numeric value of this instance to its equivalent base 10 string representation.*
* /// *
* /// A String in base 10.*
* /// System.Object*
* public override string ToString()*
* {*
* return ToString(10);*
* }*
* #endregion*
* #region Type Conversion Methods*
* ///
*
* /// Converts the numeric value of this instance to its equivalent string representation in specified base.*
* /// *
* /// Int radix between 2 and 36*
* /// A string.*
* public string ToString(int radix)*
* {*
* if (radix < 2 || radix > 36)*
* {*
* throw new ArgumentOutOfRangeException(“radix”);*
* }*
* if (IsZero)*
* {*
* return “0”;*
* }*
* BigInteger a = this;*
* bool negative = a.IsNegative;*
* a = Abs(this);*
* BigInteger quotient;*
* BigInteger remainder;*
* BigInteger biRadix = new BigInteger(radix);*
* const string charSet = “0123456789abcdefghijklmnopqrstuvwxyz”;*
* System.Collections.ArrayList al = new System.Collections.ArrayList();*
* while (a.m_digits.DataUsed > 1 || (a.m_digits.DataUsed == 1 && a.m_digits[0] != 0))
_ {
Divide(a, biRadix, out quotient, out remainder);_
al.Insert(0, charSet[(int)remainder.m_digits[0]]);
_ a = quotient;
}*_
* string result = new String((char[])al.ToArray(typeof(char)));*
* if (radix == 10 && negative)*
* {*
* return “-” + result;*
* }*
* return result;*
* }*
* ///
*
* /// Returns string in hexidecimal of the internal digit representation.*
* /// *
* /// *
* /// This is not the same as ToString(16). This method does not return the sign, but instead*
* /// dumps the digits array into a string representation in base 16.*
* /// *
* /// A string in base 16.*
* public string ToHexString()*
* {*
* System.Text.StringBuilder sb = new System.Text.StringBuilder();*
* sb.AppendFormat(“{0:X}”, m_digits[m_digits.DataUsed - 1]);*
string f = “{0:X” + (2 * DigitsArray.DataSizeOf) + “}”;
* for (int i = m_digits.DataUsed - 2; i >= 0; i–)
_ {_
sb.AppendFormat(f, m_digits);
_ }*_
* return sb.ToString();*
* }*
* ///
*
* /// Returns BigInteger as System.Int16 if possible.*
* /// *
* /// *
* /// Int value of BigInteger*
* /// When BigInteger is too large to fit into System.Int16*
* public static int ToInt16(BigInteger value)*
* {*
* if (object.ReferenceEquals(value, null))*
* {*
* throw new ArgumentNullException(“value”);*
* }*
* return System.Int16.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);*
* }*
* ///
*
* /// Returns BigInteger as System.UInt16 if possible.*
* /// *
* /// *
* /// *
* /// When BigInteger is too large to fit into System.UInt16*
* public static uint ToUInt16(BigInteger value)*
* {*
* if (object.ReferenceEquals(value, null))*
* {*
* throw new ArgumentNullException(“value”);*
* }*
* return System.UInt16.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);*
* }*
* ///
*
* /// Returns BigInteger as System.Int32 if possible.*
* /// *
* /// *
* /// *
* /// When BigInteger is too large to fit into System.Int32*
* public static int ToInt32(BigInteger value)*
* {*
* if (object.ReferenceEquals(value, null))*
* {*
* throw new ArgumentNullException(“value”);*
* }*
* return System.Int32.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);*
* }*
* ///
*
* /// Returns BigInteger as System.UInt32 if possible.*
* /// *
* /// *
* /// *
* /// When BigInteger is too large to fit into System.UInt32*
* public static uint ToUInt32(BigInteger value)*
* {*
* if (object.ReferenceEquals(value, null))*
* {*
* throw new ArgumentNullException(“value”);*
* }*
* return System.UInt32.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);*
* }*
* ///
*
* /// Returns BigInteger as System.Int64 if possible.*
* /// *
* /// *
* /// *
* /// When BigInteger is too large to fit into System.Int64*
* public static long ToInt64(BigInteger value)*
* {*
* if (object.ReferenceEquals(value, null))*
* {*
* throw new ArgumentNullException(“value”);*
* }*
* return System.Int64.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);*
* }*
* ///
*
* /// Returns BigInteger as System.UInt64 if possible.*
* /// *
* /// *
* /// *
* /// When BigInteger is too large to fit into System.UInt64*
* public static ulong ToUInt64(BigInteger value)*
* {*
* if (object.ReferenceEquals(value, null))*
* {*
* throw new ArgumentNullException(“value”);*
* }*
* return System.UInt64.Parse(value.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.CurrentCulture);*
* }*
* #endregion*
* }*
}