分享.net大整数运算类

    [Serializable, StructLayout(LayoutKind.Sequential), ComVisible(false)]
    public struct BigInteger : IFormattable, IEquatable<BigInteger>, IComparable<BigInteger>, IComparable
    {

        #region Fields
        private const int DecimalScaleFactorMask = 0xff0000;
        private const int DecimalSignMask = -2147483648;
        private const int BitsPerDigit = 0x20;
        private const ulong Base = 0x100000000L;
        private const int UpperBoundForSchoolBookMultiplicationDigits = 0x40;
        private const int ForceSchoolBookMultiplicationThresholdDigits = 8;
        private static readonly uint[] maxCharsPerDigit;
        private static readonly uint[] groupRadixValues;
        private static readonly uint[] zeroArray;
        private readonly short _sign;
        private readonly uint[] _data;
        private int _length;
        #endregion

        #region Ctors

        static BigInteger()
        {
            maxCharsPerDigit = new uint[]
            {
                0, 0, 0x1f, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8,
                7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6,
                6, 6, 6, 6, 6
            };
            groupRadixValues = new uint[]
            {
                0, 0, 0x80000000, 0xcfd41b91, 0x40000000, 0x48c27395, 0x81bf1000, 0x75db9c97, 0x40000000, 0xcfd41b91, 0x3b9aca00, 0x8c8b6d2b, 0x19a10000, 0x309f1021, 0x57f6c100, 0x98c29b81,
                0x10000000, 0x18754571, 0x247dbc80, 0x3547667b, 0x4c4b4000, 0x6b5a6e1d, 0x94ace180, 0xcaf18367, 0xb640000, 0xe8d4a51, 0x1269ae40, 0x17179149, 0x1cb91000, 0x23744899, 0x2b73a840, 0x34e63b41,
                0x40000000, 0x4cfa3cc1, 0x5c13d840, 0x6d91b519, 0x81bf1000
            };
            zeroArray = new uint[0];
        }

        public BigInteger(int value)
        {
            if (value == 0)
            {
                this._sign = 0;
                this._data = new uint[0];
            }
            else if (value < 0)
            {
                this._sign = -1;
                this._data = new uint[] { (uint)-value };
            }
            else
            {
                this._sign = 1;
                this._data = new uint[] { (uint)value };
            }
            this._length = -1;
        }

        public BigInteger(long value)
        {
            ulong num = 0L;
            if (value < 0L)
            {
                num = (ulong)-value;
                this._sign = -1;
            }
            else if (value > 0L)
            {
                num = (ulong)value;
                this._sign = 1;
            }
            else
            {
                this._sign = 0;
            }
            if (num >= 0x100000000L)
            {
                this._data = new uint[] { (uint)num, (uint)(num >> 0x20) };
            }
            else
            {
                this._data = new uint[] { (uint)num };
            }
            this._length = -1;
        }

        [CLSCompliant(false)]
        public BigInteger(uint value)
        {
            if (value == 0)
            {
                this._sign = 0;
            }
            else
            {
                this._sign = 1;
            }
            this._data = new uint[] { value };
            this._length = -1;
        }

        [CLSCompliant(false)]
        public BigInteger(ulong value)
        {
            if (value == 0L)
            {
                this._sign = 0;
            }
            else
            {
                this._sign = 1;
            }
            if (value >= 0x100000000L)
            {
                this._data = new uint[] { (uint)value, (uint)(value >> 0x20) };
            }
            else
            {
                this._data = new uint[] { (uint)value };
            }
            this._length = -1;
        }

        public BigInteger(float value)
            : this((double)value)
        {
        }

        public BigInteger(double value)
        {
            if (double.IsInfinity(value))
                throw new OverflowException();
            if (double.IsNaN(value))
                throw new OverflowException();
            byte[] bytes = BitConverter.GetBytes(value);
            ulong num = Mantissa(bytes);
            if (num == 0L)
            {
                int num2 = Exponent(bytes);
                if (num2 == 0)
                {
                    this._sign = 0;
                    this._data = zeroArray;
                    this._length = 0;
                    return;
                }
                BigInteger x = IsNegative(bytes) ? Negate(One) : One;
                x = LeftShift(x, num2 - 0x3ff);
                this._sign = x._sign;
                this._data = x._data;
            }
            else
            {
                int num3 = Exponent(bytes);
                num |= (ulong)0x10000000000000L;
                BigInteger integer2 = new BigInteger(num);
                integer2 = (num3 > 0x433) ? LeftShift(integer2, num3 - 0x433) : RightShift(integer2, 0x433 - num3);
                this._sign = IsNegative(bytes) ? ((short)(integer2._sign * -1)) : integer2._sign;
                this._data = integer2._data;
            }
            this._length = -1;
        }

        public BigInteger(decimal value)
        {
            int[] bits = decimal.GetBits(decimal.Truncate(value));
            int num = 3;
            while ((num > 0) && (bits[num - 1] == 0))
            {
                num--;
            }
            this._length = num;
            if (num == 0)
            {
                this._sign = 0;
                this._data = new uint[0];
            }
            else
            {
                uint[] numArray2 = new uint[num];
                numArray2[0] = (uint)bits[0];
                if (num > 1)
                {
                    numArray2[1] = (uint)bits[1];
                }
                if (num > 2)
                {
                    numArray2[2] = (uint)bits[2];
                }
                this._sign = ((bits[3] & -2147483648) != 0) ? ((short)(-1)) : ((short)1);
                this._data = numArray2;
            }
        }

        public BigInteger(byte[] value)
            : this(value, false)
        {
        }

        public BigInteger(byte[] value, bool negative)
        {
            if (value == null)
                throw new ArgumentNullException("value");
            int index = value.Length / 4;
            int num2 = value.Length % 4;
            if (num2 > 0)
            {
                this._data = new uint[index + 1];
            }
            else
            {
                this._data = new uint[index];
            }
            Buffer.BlockCopy(value, 0, this._data, 0, index * 4);
            if (num2 > 0)
            {
                uint num3 = 0;
                for (int i = 0; i < num2; i++)
                {
                    num3 |= (uint)(value[(index * 4) + i] << (8 * i));
                }
                this._data[index] = num3;
            }
            this._sign = negative ? ((short)(-1)) : ((short)1);
            this._length = -1;
            if (this.Length == 0)
            {
                this._sign = 0;
                this._data = zeroArray;
            }
        }

        private BigInteger(int _sign, params uint[] _data)
        {
            if (GetLength(_data) == 0)
            {
                _sign = 0;
            }
            this._data = _data;
            this._sign = (short)_sign;
            this._length = -1;
        }

        #endregion

        #region Static Properties

        public static BigInteger Zero
        {
            get
            {
                return new BigInteger(0, zeroArray);
            }
        }
        public static BigInteger One
        {
            get
            {
                return new BigInteger(1);
            }
        }
        public static BigInteger MinusOne
        {
            get
            {
                return new BigInteger(-1);
            }
        }

        #endregion

        #region Static Methods

        public static BigInteger Abs(BigInteger x)
        {
            if (x._sign == -1)
            {
                return -x;
            }
            return x;
        }

        public static BigInteger GreatestCommonDivisor(BigInteger x, BigInteger y)
        {
            BigInteger integer;
            BigInteger integer2;
            if (x.Sign == 0)
                throw new ArgumentOutOfRangeException("x", "Must Be Positive");
            if (y.Sign == 0)
                throw new ArgumentOutOfRangeException("y", "MustBePositive");
            x = Abs(x);
            y = Abs(y);
            int num = Compare(x, y);
            if (num == 0)
            {
                return x;
            }
            if (num < 1)
            {
                integer = x;
                integer2 = y;
            }
            else
            {
                integer = y;
                integer2 = x;
            }
            do
            {
                BigInteger integer3;
                BigInteger integer4 = integer2;
                DivRem(integer, integer2, out integer3);
                integer2 = integer3;
                integer = integer4;
            }
            while (integer2 != 0);
            return integer;
        }

        public static BigInteger Remainder(BigInteger dividend, BigInteger divisor)
        {
            BigInteger integer;
            DivRem(dividend, divisor, out integer);
            return integer;
        }

        public static BigInteger Negate(BigInteger x)
        {
            BigInteger integer = new BigInteger(-x._sign, (x._data == null) ? zeroArray : x._data);
            integer._length = x._length;
            return integer;
        }

        public static BigInteger Pow(BigInteger baseValue, BigInteger exponent)
        {
            if (exponent < 0)
                throw new ArgumentOutOfRangeException("exponent", "NonNegative");
            if (exponent == 0)
            {
                return One;
            }
            BigInteger integer = baseValue;
            BigInteger result = One;
            while (exponent > 0)
            {
                if ((exponent._data[0] & 1) != 0)
                {
                    result *= integer;
                }
                if (exponent == 1)
                {
                    return result;
                }
                integer = integer.Square();
                exponent = RightShift(exponent, 1);
            }
            return result;
        }

        public static BigInteger ModPow(BigInteger baseValue, BigInteger exponent, BigInteger modulus)
        {
            if (exponent < 0)
                throw new ArgumentOutOfRangeException("exponent", "NonNegative");
            if (exponent == 0)
            {
                return One;
            }
            BigInteger integer = baseValue;
            BigInteger result = One;
            while (exponent > 0)
            {
                if ((exponent._data[0] & 1) != 0)
                {
                    result *= integer;
                    result = result % modulus;
                }
                if (exponent == 1)
                {
                    return result;
                }
                integer = integer.Square();
                exponent = RightShift(exponent, 1);
            }
            return result;
        }

        private static bool IsNegative(byte[] doubleBits)
        {
            return ((doubleBits[7] & 0x80) != 0);
        }

        private static ushort Exponent(byte[] doubleBits)
        {
            return (ushort)((((ushort)(doubleBits[7] & 0x7f)) << 4) | (((ushort)(doubleBits[6] & 240)) >> 4));
        }

        private static ulong Mantissa(byte[] doubleBits)
        {
            uint num = (uint)(((doubleBits[0] | (doubleBits[1] << 8)) | (doubleBits[2] << 0x10)) | (doubleBits[3] << 0x18));
            uint num2 = (uint)((doubleBits[4] | (doubleBits[5] << 8)) | ((doubleBits[6] & 15) << 0x10));
            return (num | (num2 << 0x20));
        }

        private static int GetLength(uint[] _data)
        {
            if (_data == null)
            {
                return 0;
            }
            int index = _data.Length - 1;
            while ((index >= 0) && (_data[index] == 0))
            {
                index--;
            }
            return (index + 1);
        }

        private static uint[] copy(uint[] v)
        {
            uint[] destinationArray = new uint[v.Length];
            Array.Copy(v, destinationArray, v.Length);
            return destinationArray;
        }

        private static uint[] resize(uint[] v, int len)
        {
            if (v.Length == len)
            {
                return v;
            }
            uint[] destinationArray = new uint[len];
            int length = Math.Min(v.Length, len);
            Array.Copy(v, destinationArray, length);
            return destinationArray;
        }

        private static uint[] add0(uint[] x, int xl, uint[] y, int yl)
        {
            if (xl >= yl)
            {
                return InternalAdd(x, xl, y, yl);
            }
            return InternalAdd(y, yl, x, xl);
        }

        private static uint[] InternalAdd(uint[] x, int xl, uint[] y, int yl)
        {
            uint[] result = new uint[xl];
            ulong temp = 0L;
            int index = 0;
            while (index < yl)
            {
                temp = temp + x[index] + y[index];
                result[index] = (uint)temp;
                temp = temp >> 0x20;
                index++;
            }
            while ((index < xl) && (temp != 0L))
            {
                temp += x[index];
                result[index] = (uint)temp;
                temp = temp >> 0x20;
                index++;
            }
            if (temp == 0L)
            {
                while (index < xl)
                {
                    result[index] = x[index];
                    index++;
                }
                return result;
            }
            result = resize(result, xl + 1);
            result[index] = (uint)temp;
            return result;
        }

        private static uint[] sub(uint[] x, int xl, uint[] y, int yl)
        {
            uint[] result = new uint[xl];
            bool flag = false;
            int index = 0;
            while (index < yl)
            {
                uint currentX = x[index];
                uint currentY = y[index];
                if (flag)
                {
                    if (currentX == 0)
                    {
                        currentX = uint.MaxValue;
                        flag = true;
                    }
                    else
                    {
                        currentX--;
                        flag = false;
                    }
                }
                if (currentY > currentX)
                {
                    flag = true;
                }
                result[index] = currentX - currentY;
                index++;
            }
            if (flag)
            {
                while (index < xl)
                {
                    uint currentX = x[index];
                    result[index] = currentX - 1;
                    if (currentX != 0)
                    {
                        index++;
                        break;
                    }
                    index++;
                }
            }
            while (index < xl)
            {
                result[index] = x[index];
                index++;
            }
            return result;
        }

        public static int Compare(BigInteger x, BigInteger y)
        {
            if (x._sign == y._sign)
            {
                int xLength = x.Length;
                int yLength = y.Length;
                if (xLength == yLength)
                {
                    for (int i = xLength - 1; i >= 0; i--)
                    {
                        if (x._data[i] != y._data[i])
                        {
                            if (x._data[i] <= y._data[i])
                            {
                                return -x._sign;
                            }
                            return x._sign;
                        }
                    }
                    return 0;
                }
                if (xLength <= yLength)
                {
                    return -x._sign;
                }
                return x._sign;
            }
            if (x._sign <= y._sign)
            {
                return -1;
            }
            return 1;
        }

        public static BigInteger Add(BigInteger x, BigInteger y)
        {
            return x + y;
        }

        public static BigInteger Subtract(BigInteger x, BigInteger y)
        {
            return x - y;
        }

        public static BigInteger Multiply(BigInteger x, BigInteger y)
        {
            int xLength = x.Length;
            int yLength = y.Length;
            if (xLength + yLength >= 0x40 && xLength >= 8 && yLength >= 8)
            {
                return MultiplyKaratsuba(x, y);
            }
            return MultiplySchoolBook(x, y);
        }

        private static BigInteger MultiplySchoolBook(BigInteger x, BigInteger y)
        {
            int xLength = x.Length;
            int yLength = y.Length;
            int xyLength = xLength + yLength;
            uint[] xData = x._data;
            uint[] yData = y._data;
            uint[] xyData = new uint[xyLength];
            for (int i = 0; i < xLength; i++)
            {
                uint xNum = xData[i];
                int index = i;
                ulong temp = 0L;
                for (int j = 0; j < yLength; j++)
                {
                    temp = (temp + ((ulong)xNum * yData[j])) + xyData[index];
                    xyData[index++] = (uint)temp;
                    temp = temp >> 0x20;
                }
                while (temp != 0L)
                {
                    temp += xyData[index];
                    xyData[index++] = (uint)temp;
                    temp = temp >> 0x20;
                }
            }
            return new BigInteger(x._sign * y._sign, xyData);
        }

        private static BigInteger MultiplyKaratsuba(BigInteger x, BigInteger y)
        {
            int halfLength = Math.Max(x.Length, y.Length) / 2;
            if (((halfLength <= 0x10) || (x.Length < 0x10)) || (y.Length < 0x10))
            {
                return MultiplySchoolBook(x, y);
            }
            int shift = 0x20 * halfLength;
            BigInteger int1 = RightShift(x, shift);
            BigInteger int2 = x.RestrictTo(halfLength);
            BigInteger int3 = RightShift(y, shift);
            BigInteger int4 = y.RestrictTo(halfLength);
            BigInteger int5 = Multiply(int1, int3);
            BigInteger int6 = Multiply(int2, int4);
            BigInteger int7 = Multiply(int1 + int2, int3 + int4) - (int5 + int6);
            return (int6 + LeftShift(int7 + LeftShift(int5, shift), shift));
        }

        public static BigInteger Divide(BigInteger dividend, BigInteger divisor)
        {
            return dividend / divisor;
        }

        private static int GetNormalizeShift(uint value)
        {
            int num = 0;
            if ((value & 0xffff0000) == 0)
            {
                value = value << 0x10;
                num += 0x10;
            }
            if ((value & 0xff000000) == 0)
            {
                value = value << 8;
                num += 8;
            }
            if ((value & 0xf0000000) == 0)
            {
                value = value << 4;
                num += 4;
            }
            if ((value & 0xc0000000) == 0)
            {
                value = value << 2;
                num += 2;
            }
            if ((value & 0x80000000) == 0)
            {
                value = value << 1;
                num++;
            }
            return num;
        }

        private static void Normalize(uint[] u, int l, uint[] un, int shift)
        {
            int index;
            uint temp = 0;
            if (shift > 0)
            {
                int sh = 0x20 - shift;
                for (index = 0; index < l; index++)
                {
                    uint current = u[index];
                    un[index] = (current << shift) | temp;
                    temp = current >> sh;
                }
            }
            else
            {
                index = 0;
                while (index < l)
                {
                    un[index] = u[index];
                    index++;
                }
            }
            while (index < un.Length)
            {
                un[index++] = 0;
            }
            if (temp != 0)
            {
                un[l] = temp;
            }
        }

        private static void Unnormalize(uint[] un, out uint[] r, int shift)
        {
            int length = GetLength(un);
            r = new uint[length];
            if (shift > 0)
            {
                int sh = 0x20 - shift;
                uint temp = 0;
                for (int i = length - 1; i >= 0; i--)
                {
                    uint current = un[i];
                    r[i] = (current >> shift) | temp;
                    temp = current << sh;
                }
            }
            else
            {
                for (int j = 0; j < length; j++)
                {
                    r[j] = un[j];
                }
            }
        }

        private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r)
        {
            int uLength = GetLength(u);
            int vLength = GetLength(v);
            if (vLength <= 1)
            {
                if (vLength == 0)
                {
                    throw new DivideByZeroException();
                }
                ulong temp = 0L;
                uint vCurrent = v[0];
                q = new uint[uLength];
                r = new uint[1];
                for (int i = uLength - 1; i >= 0; i--)
                {
                    temp *= (ulong)0x100000000L;
                    temp += u[i];
                    ulong temp2 = temp / ((ulong)vCurrent);
                    temp -= temp2 * vCurrent;
                    q[i] = (uint)temp2;
                }
                r[0] = (uint)temp;
            }
            else if (uLength >= vLength)
            {
                int normalizeShift = GetNormalizeShift(v[vLength - 1]);
                uint[] un = new uint[uLength + 1];
                uint[] vArray = new uint[vLength];
                Normalize(u, uLength, un, normalizeShift);
                Normalize(v, vLength, vArray, normalizeShift);
                q = new uint[(uLength - vLength) + 1];
                r = null;
                for (int i = uLength - vLength; i >= 0; i--)
                {
                    ulong temp = (ulong)((0x100000000L * un[i + vLength]) + un[(i + vLength) - 1]);
                    ulong current = temp / ((ulong)vArray[vLength - 1]);
                    temp -= current * vArray[vLength - 1];
                    do
                    {
                        if ((current < 0x100000000L) && ((current * vArray[vLength - 2]) <= ((temp * ((ulong)0x100000000L)) + un[(i + vLength) - 2])))
                        {
                            break;
                        }
                        current -= (ulong)1L;
                        temp += vArray[vLength - 1];
                    }
                    while (temp < 0x100000000L);
                    long temp2 = 0L;
                    long temp3 = 0L;
                    int index = 0;
                    while (index < vLength)
                    {
                        ulong temp4 = vArray[index] * current;
                        temp3 = (un[index + i] - ((uint)temp4)) - temp2;
                        un[index + i] = (uint)temp3;
                        temp4 = temp4 >> 0x20;
                        temp3 = temp3 >> 0x20;
                        temp2 = ((long)temp4) - temp3;
                        index++;
                    }
                    temp3 = un[i + vLength] - temp2;
                    un[i + vLength] = (uint)temp3;
                    q[i] = (uint)current;
                    if (temp3 < 0L)
                    {
                        q[i]--;
                        ulong num15 = 0L;
                        for (index = 0; index < vLength; index++)
                        {
                            num15 = (vArray[index] + un[i + index]) + num15;
                            un[i + index] = (uint)num15;
                            num15 = num15 >> 0x20;
                        }
                        num15 += un[i + vLength];
                        un[i + vLength] = (uint)num15;
                    }
                }
                Unnormalize(un, out r, normalizeShift);
            }
            else
            {
                q = zeroArray;
                r = u;
            }
        }

        public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)
        {
            uint[] q;
            uint[] r;
            DivModUnsigned((dividend._data == null) ? zeroArray : dividend._data, (divisor._data == null) ? zeroArray : divisor._data, out q, out r);
            remainder = new BigInteger(dividend._sign, r);
            return new BigInteger(dividend._sign * divisor._sign, q);
        }

        private static BigInteger LeftShift(BigInteger x, int shift)
        {
            if (shift == 0)
            {
                return x;
            }
            if (shift < 0)
            {
                return RightShift(x, -shift);
            }
            int sh = shift / 0x20;
            int sh2 = shift - (sh * 0x20);
            int xLength = x.Length;
            uint[] xData = x._data;
            int newLength = (xLength + sh) + 1;
            uint[] newArray = new uint[newLength];
            if (sh2 == 0)
            {
                for (int i = 0; i < xLength; i++)
                {
                    newArray[i + sh] = xData[i];
                }
            }
            else
            {
                int sh3 = 0x20 - sh2;
                uint temp = 0;
                int index = 0;
                while (index < xLength)
                {
                    uint current = xData[index];
                    newArray[index + sh] = (current << sh2) | temp;
                    temp = current >> sh3;
                    index++;
                }
                newArray[index + sh] = temp;
            }
            return new BigInteger(x._sign, newArray);
        }

        private static BigInteger RightShift(BigInteger x, int shift)
        {
            if (shift == 0)
            {
                return x;
            }
            if (shift < 0)
            {
                return LeftShift(x, -shift);
            }
            int sh = shift / 0x20;
            int sh2 = shift - (sh * 0x20);
            int xLength = x.Length;
            uint[] xData = x._data;
            int newLength = xLength - sh;
            if (newLength < 0)
            {
                newLength = 0;
            }
            uint[] newArray = new uint[newLength];
            if (sh2 == 0)
            {
                for (int i = xLength - 1; i >= sh; i--)
                {
                    newArray[i - sh] = xData[i];
                }
            }
            else
            {
                int sh3 = 0x20 - sh2;
                uint temp = 0;
                for (int j = xLength - 1; j >= sh; j--)
                {
                    uint current = xData[j];
                    newArray[j - sh] = (current >> sh2) | temp;
                    temp = current << sh3;
                }
            }
            return new BigInteger(x._sign, newArray);
        }

        public static BigInteger Parse(string s)
        {
            return Parse(s, CultureInfo.CurrentCulture);
        }

        public static BigInteger Parse(string s, IFormatProvider provider)
        {
            return Parse(s, NumberStyles.Integer, provider);
        }

        public static BigInteger Parse(string s, NumberStyles style)
        {
            return Parse(s, style, CultureInfo.CurrentCulture);
        }

        public static BigInteger Parse(string s, NumberStyles style, IFormatProvider provider)
        {
            BigInteger integer;
            string str;
            if (!TryParse(s, style, provider, out integer, out str))
            {
                throw new FormatException(str);
            }
            return integer;
        }

        public static bool TryParse(string s, out BigInteger b)
        {
            string str;
            return TryParse(s, NumberStyles.Integer, CultureInfo.CurrentCulture, out b, out str);
        }

        public static bool TryParse(string s, NumberStyles style, IFormatProvider formatProvider, out BigInteger value)
        {
            string str;
            return TryParse(s, style, formatProvider, out value, out str);
        }

        private static bool TryParse(string s, NumberStyles style, IFormatProvider formatProvider, out BigInteger value, out string error)
        {
            if (formatProvider == null)
            {
                formatProvider = CultureInfo.CurrentCulture;
            }
            if ((style & ~(NumberStyles.HexNumber | NumberStyles.AllowLeadingSign)) != NumberStyles.None)
            {
                throw new NotSupportedException(string.Format(CultureInfo.CurrentUICulture, "Unsupported Number Style {0}", new object[] { style }));
            }
            error = null;
            NumberFormatInfo format = (NumberFormatInfo)formatProvider.GetFormat(typeof(NumberFormatInfo));
            uint radix = (uint)(((style & NumberStyles.AllowHexSpecifier) != NumberStyles.None) ? 0x10 : 10);
            int index = 0;
            bool flag = false;
            if ((style & NumberStyles.AllowLeadingWhite) != NumberStyles.None)
            {
                while ((index < s.Length) && IsWhiteSpace(s[index]))
                {
                    index++;
                }
            }
            if ((style & NumberStyles.AllowLeadingSign) != NumberStyles.None)
            {
                int length = format.NegativeSign.Length;
                if (((length + index) < s.Length) && (string.Compare(s, index, format.NegativeSign, 0, length, false, CultureInfo.CurrentCulture) == 0))
                {
                    flag = true;
                    index += format.NegativeSign.Length;
                }
            }
            value = Zero;
            BigInteger rate = One;
            if (index == s.Length)
            {
                error = "ParsedStringWasInvalid";
                return false;
            }
            for (int i = s.Length - 1; i >= index; i--)
            {
                if (((style & NumberStyles.AllowTrailingWhite) != NumberStyles.None) && IsWhiteSpace(s[i]))
                {
                    int currentIndex = i;
                    while (currentIndex >= index)
                    {
                        if (!IsWhiteSpace(s[currentIndex]))
                        {
                            break;
                        }
                        currentIndex--;
                    }
                    if (currentIndex < index)
                    {
                        error = "ParsedStringWasInvalid";
                        return false;
                    }
                    i = currentIndex;
                }
                uint singleDigit = ParseSingleDigit(s[i], (ulong)radix, out error);
                if (error != null)
                {
                    return false;
                }
                if (singleDigit != 0)
                {
                    value += singleDigit * rate;
                }
                rate *= radix;
            }
            if ((value._sign == 1) && flag)
            {
                value = -value;
            }
            return true;
        }

        private static uint ParseSingleDigit(char c, ulong radix, out string error)
        {
            error = null;
            if ((c >= '0') && (c <= '9'))
            {
                return (uint)(c - '0');
            }
            if (radix == 0x10L)
            {
                c = (char)(c & '￟');
                if ((c >= 'A') && (c <= 'F'))
                {
                    return (uint)((c - 'A') + 10);
                }
            }
            error = "InvalidCharactersInString";
            return uint.MaxValue;
        }

        private static bool IsWhiteSpace(char ch)
        {
            return ((ch == ' ') || ((ch >= '/t') && (ch <= '/r')));
        }

        private static void AppendRadix(uint rem, uint radix, bool useCapitalHexDigits, char[] tmp, StringBuilder buf, bool leadingZeros)
        {
            string str = useCapitalHexDigits ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" : "0123456789abcdefghijklmnopqrstuvwxyz";
            int length = tmp.Length;
            int startIndex = length;
            while ((startIndex > 0) && (leadingZeros || (rem != 0)))
            {
                uint index = rem % radix;
                rem /= radix;
                tmp[--startIndex] = str[(int)index];
            }
            if (leadingZeros)
            {
                buf.Append(tmp);
            }
            else
            {
                buf.Append(tmp, startIndex, length - startIndex);
            }
        }

        private static uint div(uint[] n, ref int nl, uint d)
        {
            ulong num = 0L;
            int index = nl;
            bool flag = false;
            while (--index >= 0)
            {
                num = num << 0x20;
                num |= n[index];
                uint num3 = (uint)(num / ((ulong)d));
                n[index] = num3;
                if (num3 == 0)
                {
                    if (!flag)
                    {
                        nl--;
                    }
                }
                else
                {
                    flag = true;
                }
                num = num % ((ulong)d);
            }
            return (uint)num;
        }

        #endregion

        #region Operators

        public static BigInteger operator +(BigInteger value)
        {
            return value;
        }

        public static BigInteger operator -(BigInteger value)
        {
            return Negate(value);
        }

        public static BigInteger operator ++(BigInteger value)
        {
            if (value._sign >= 0)
            {
                return new BigInteger(1, add0(value._data, value.Length, new uint[] { 1 }, 1));
            }
            if ((value.Length == 1) && (value._data[0] == 1))
            {
                return Zero;
            }
            return new BigInteger(-1, sub(value._data, value.Length, new uint[] { 1 }, 1));
        }

        public static BigInteger operator --(BigInteger value)
        {
            uint[] numArray;
            int num;
            int length = value.Length;
            if (value._sign == 1)
            {
                if ((length == 1) && (value._data[0] == 1))
                {
                    return Zero;
                }
                numArray = sub(value._data, length, new uint[] { 1 }, 1);
                num = 1;
            }
            else
            {
                numArray = add0(value._data, length, new uint[] { 1 }, 1);
                num = -1;
            }
            return new BigInteger(num, numArray);
        }

        public static BigInteger operator +(BigInteger x, BigInteger y)
        {
            if (x._sign == y._sign)
            {
                return new BigInteger(x._sign, add0(x._data, x.Length, y._data, y.Length));
            }
            return (x - (-y));
        }

        public static BigInteger operator -(BigInteger x, BigInteger y)
        {
            uint[] array;
            int compare = Compare(x, y);
            if (compare != 0)
            {
                if (x._sign != y._sign)
                {
                    return new BigInteger(compare, add0(x._data, x.Length, y._data, y.Length));
                }
                switch ((compare * x._sign))
                {
                    case -1:
                        array = sub(y._data, y.Length, x._data, x.Length);
                        return new BigInteger(compare, array);

                    case 1:
                        array = sub(x._data, x.Length, y._data, y.Length);
                        return new BigInteger(compare, array);
                    default:
                        break;
                }
            }
            return Zero;
        }

        public static BigInteger operator *(BigInteger x, BigInteger y)
        {
            return Multiply(x, y);
        }

        public static BigInteger operator %(BigInteger x, BigInteger y)
        {
            BigInteger result;
            if ((x._sign == y._sign) && (x.Length < y.Length))
            {
                return x;
            }
            DivRem(x, y, out result);
            return result;
        }

        public static BigInteger operator /(BigInteger dividend, BigInteger divisor)
        {
            BigInteger integer;
            return DivRem(dividend, divisor, out integer);
        }

        public static bool operator ==(BigInteger x, BigInteger y)
        {
            return (Compare(x, y) == 0);
        }

        public static bool operator !=(BigInteger x, BigInteger y)
        {
            return (Compare(x, y) != 0);
        }

        public static bool operator <(BigInteger x, BigInteger y)
        {
            return (Compare(x, y) < 0);
        }

        public static bool operator <=(BigInteger x, BigInteger y)
        {
            return (Compare(x, y) <= 0);
        }

        public static bool operator >(BigInteger x, BigInteger y)
        {
            return (Compare(x, y) > 0);
        }

        public static bool operator >=(BigInteger x, BigInteger y)
        {
            return (Compare(x, y) >= 0);
        }

        public static explicit operator byte(BigInteger value)
        {
            if (value._sign == 0)
            {
                return 0;
            }
            if (value.Length > 1)
            {
                throw new OverflowException("Overflow Byte");
            }
            if (value._data[0] > 0xff)
            {
                throw new OverflowException("Overflow Byte");
            }
            if (value._sign < 0)
            {
                throw new OverflowException("Overflow Byte");
            }
            return (byte)value._data[0];
        }

        [CLSCompliant(false)]
        public static explicit operator sbyte(BigInteger value)
        {
            if (value._sign == 0)
            {
                return 0;
            }
            if (value.Length > 1)
            {
                throw new OverflowException("Overflow sbyte");
            }
            if (value._data[0] > 0x80)
            {
                throw new OverflowException("Overflow sbyte");
            }
            if ((value._data[0] == 0x80) && (value._sign == 1))
            {
                throw new OverflowException("Overflow sbyte");
            }
            sbyte num = (sbyte)value._data[0];
            return (sbyte)(num * ((sbyte)value._sign));
        }

        public static explicit operator short(BigInteger value)
        {
            if (value._sign == 0)
            {
                return 0;
            }
            if (value.Length > 1)
            {
                throw new OverflowException("Overflow int16");
            }
            if (value._data[0] > 0x8000)
            {
                throw new OverflowException("Overflow int16");
            }
            if ((value._data[0] == 0x8000) && (value._sign == 1))
            {
                throw new OverflowException("Overflow int16");
            }
            short num = (short)value._data[0];
            return (short)(num * value._sign);
        }

        [CLSCompliant(false)]
        public static explicit operator ushort(BigInteger value)
        {
            if (value._sign == 0)
            {
                return 0;
            }
            if (value.Length > 1)
            {
                throw new OverflowException("Overflow uint16");
            }
            if (value._data[0] > 0xffff)
            {
                throw new OverflowException("Overflow uint16");
            }
            if (value._sign < 0)
            {
                throw new OverflowException("Overflow uint16");
            }
            return (ushort)value._data[0];
        }

        public static explicit operator int(BigInteger value)
        {
            if (value._sign == 0)
            {
                return 0;
            }
            if (value.Length > 1)
            {
                throw new OverflowException("Overflow int32");
            }
            if (value._data[0] > 0x80000000)
            {
                throw new OverflowException("Overflow int32");
            }
            if ((value._data[0] == 0x80000000) && (value._sign == 1))
            {
                throw new OverflowException("Overflow int32");
            }
            int num = (int)value._data[0];
            return (num * value._sign);
        }

        [CLSCompliant(false)]
        public static explicit operator uint(BigInteger value)
        {
            if (value._sign == 0)
            {
                return 0;
            }
            if (value.Length > 1)
            {
                throw new OverflowException("Overflow uint32");
            }
            if (value._sign < 0)
            {
                throw new OverflowException("Overflow uint32");
            }
            return value._data[0];
        }

        public static explicit operator long(BigInteger value)
        {
            if (value._sign == 0)
            {
                return 0L;
            }
            if (value.Length > 2)
            {
                throw new OverflowException("Overflow int64");
            }
            if (value.Length == 1)
            {
                return (value._sign * value._data[0]);
            }
            ulong num2 = (value._data[1] << 0x20) | value._data[0];
            if (num2 > 9223372036854775808L)
            {
                throw new OverflowException("Overflow int64");
            }
            if ((num2 == 9223372036854775808L) && (value._sign == 1))
            {
                throw new OverflowException("Overflow int64");
            }
            return (long)num2 * (long)value._sign;
        }

        [CLSCompliant(false)]
        public static explicit operator ulong(BigInteger value)
        {
            ulong num = 0L;
            if (value._sign == 0)
            {
                return 0L;
            }
            if (value._sign < 0)
            {
                throw new OverflowException("Overflow uint64");
            }
            if (value.Length > 2)
            {
                throw new OverflowException("Overflow uint64");
            }
            num = value._data[0];
            if (value.Length > 1)
            {
                num |= value._data[1] << 0x20;
            }
            return num;
        }

        public static explicit operator float(BigInteger value)
        {
            float num;
            NumberFormatInfo numberFormat = CultureInfo.InvariantCulture.NumberFormat;
            if (!float.TryParse(value.ToString(10, false, numberFormat), NumberStyles.Number, (IFormatProvider)numberFormat, out num))
            {
                throw new OverflowException("Overflow single");
            }
            return num;
        }

        public static explicit operator double(BigInteger value)
        {
            double num;
            NumberFormatInfo numberFormat = CultureInfo.InvariantCulture.NumberFormat;
            if (!double.TryParse(value.ToString(10, false, numberFormat), NumberStyles.Number, (IFormatProvider)numberFormat, out num))
            {
                throw new OverflowException("Overflow double");
            }
            return num;
        }

        public static explicit operator decimal(BigInteger value)
        {
            if (value._sign == 0)
            {
                return 0M;
            }
            int length = value.Length;
            if (length > 3)
            {
                throw new OverflowException("Overflow Decimal");
            }
            int lo = 0;
            int mid = 0;
            int hi = 0;
            if (length > 2)
            {
                hi = (int)value._data[2];
            }
            if (length > 1)
            {
                mid = (int)value._data[1];
            }
            if (length > 0)
            {
                lo = (int)value._data[0];
            }
            return new decimal(lo, mid, hi, value._sign < 0, 0);
        }

        public static explicit operator BigInteger(float value)
        {
            return new BigInteger(value);
        }

        public static explicit operator BigInteger(double value)
        {
            return new BigInteger(value);
        }

        public static explicit operator BigInteger(decimal value)
        {
            return new BigInteger(value);
        }

        public static implicit operator BigInteger(byte value)
        {
            return new BigInteger(value);
        }

        [CLSCompliant(false)]
        public static implicit operator BigInteger(sbyte value)
        {
            return new BigInteger(value);
        }

        public static implicit operator BigInteger(short value)
        {
            return new BigInteger(value);
        }

        [CLSCompliant(false)]
        public static implicit operator BigInteger(ushort value)
        {
            return new BigInteger(value);
        }

        public static implicit operator BigInteger(int value)
        {
            return new BigInteger(value);
        }

        [CLSCompliant(false)]
        public static implicit operator BigInteger(uint value)
        {
            return new BigInteger(value);
        }

        public static implicit operator BigInteger(long value)
        {
            return new BigInteger(value);
        }

        [CLSCompliant(false)]
        public static implicit operator BigInteger(ulong value)
        {
            return new BigInteger(value);
        }

        #endregion

        #region Instance Properties

        public int Sign
        {
            get
            {
                return this._sign;
            }
        }

        private int Length
        {
            get
            {
                if (this._length == -1)
                {
                    this._length = GetLength(this._data);
                }
                return this._length;
            }
        }

        #endregion

        #region Instance Methods

        private BigInteger Square()
        {
            return (this * this);
        }

        public byte[] ToByteArray()
        {
            bool flag;
            return this.ToByteArray(out flag);
        }

        public byte[] ToByteArray(out bool isNegative)
        {
            int length = this.Length;
            byte[] result = new byte[length * 4];
            Buffer.BlockCopy(this._data, 0, result, 0, length * 4);
            isNegative = this._sign == -1;
            return result;
        }

        private BigInteger RestrictTo(int numDigits)
        {
            int length = Math.Min(numDigits, this.Length);
            if (length == this.Length)
            {
                return this;
            }
            BigInteger result = new BigInteger(this._sign, this._data);
            result._length = length;
            return result;
        }

        public string ToString(string format)
        {
            return this.ToString(format, CultureInfo.CurrentCulture);
        }

        public string ToString(IFormatProvider formatProvider)
        {
            if (formatProvider == null)
            {
                formatProvider = CultureInfo.CurrentCulture;
            }
            return this.ToString(10, false, (NumberFormatInfo)formatProvider.GetFormat(typeof(NumberFormatInfo)));
        }

        public string ToString(string format, IFormatProvider formatProvider)
        {
            if (formatProvider == null)
            {
                formatProvider = CultureInfo.CurrentCulture;
            }
            uint radix = 10;
            bool useCapitalHexDigits = false;
            if (!string.IsNullOrEmpty(format))
            {
                char ch = format[0];
                switch (ch)
                {
                    case 'X':
                    case 'x':
                        radix = 0x10;
                        useCapitalHexDigits = ch == 'X';
                        break;
                    default:
                        if (((ch != 'G') && (ch != 'g')) && ((ch != 'D') && (ch != 'd')))
                        {
                            throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Currently not supported format: {0}", new object[] { format }));
                        }
                        break;
                }
            }
            return this.ToString(radix, useCapitalHexDigits, (NumberFormatInfo)formatProvider.GetFormat(typeof(NumberFormatInfo)));
        }

        public override string ToString()
        {
            return this.ToString(10, false, CultureInfo.CurrentCulture.NumberFormat);
        }

        private string ToString(uint radix, bool useCapitalHexDigits, NumberFormatInfo info)
        {
            if (this._sign == 0)
            {
                return "0";
            }
            int length = this.Length;
            List<uint> list = new List<uint>();
            uint[] n = copy(this._data);
            int nl = this.Length;
            uint d = groupRadixValues[radix];
            while (nl > 0)
            {
                uint item = div(n, ref nl, d);
                list.Add(item);
            }
            StringBuilder sb = new StringBuilder();
            if (this._sign == -1)
            {
                sb.Append(info.NegativeSign);
            }
            int index = list.Count - 1;
            char[] tmp = new char[maxCharsPerDigit[radix]];
            AppendRadix(list[index--], radix, useCapitalHexDigits, tmp, sb, false);
            while (index >= 0)
            {
                AppendRadix(list[index--], radix, useCapitalHexDigits, tmp, sb, true);
            }
            return sb.ToString();
        }

        public override int GetHashCode()
        {
            if (this._sign == 0)
            {
                return 0;
            }
            return (int)this._data[0];
        }

        public bool Equals(BigInteger other)
        {
            if (this._sign != other._sign)
            {
                return false;
            }
            int length = this.Length;
            int otherLength = other.Length;
            if (length != otherLength)
            {
                return false;
            }
            for (uint i = 0; i < length; i++)
            {
                if (this._data[i] != other._data[i])
                {
                    return false;
                }
            }
            return true;
        }

        public override bool Equals(object obj)
        {
            return (((obj != null) && (obj is BigInteger)) && this.Equals((BigInteger)obj));
        }

        public int CompareTo(BigInteger other)
        {
            return Compare(this, other);
        }

        public int CompareTo(object obj)
        {
            if (obj == null)
            {
                return 1;
            }
            if (!(obj is BigInteger))
            {
                throw new ArgumentException("MustBeBigInt");
            }
            return Compare(this, (BigInteger)obj);
        }

        #endregion

    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值