BigInteger in Unity3D?

It doesn’t seem like the version of MONO that U3D is using supports the System.Numerics namespace, and I’m requiring the use of the BigInteger class for my project, does anybody have recommendations? ulong does not store high enough for my project.

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*
* }*
}

I made a simple class to do math with numbers in string format, it may be a strange alternative to BigInteger, but it works for me.
https://dl.dropboxusercontent.com/s/uq6tkbmpimk92xe/StringMath.cs?dl=0

if you want to use it, simply copy the cs file to your assets folder, and use it this way:

string a = "999999999999999999999";
string b = "8888888888888888888888;"
string c;
c = StringMath.Add(a,b) // c = a+b
c = StringMath.Sub(a,b) // c = a-b
c = StringMath.Mult(a,b) // c = a*b
c = StringMath.Dev(a,b) // c = a/b