Normalize() private method

Normalizes this by setting the length to the actual number of uints used in data and by setting the sign to Sign.Zero if the value of this is 0.
private Normalize ( ) : void
return void
コード例 #1
0
            public static BigInteger RightShift(BigInteger bi, int n)
            {
                if (n == 0)
                {
                    return(new BigInteger(bi));
                }

                int w = n >> 5;
                int s = n & ((1 << 5) - 1);

                BigInteger ret = new BigInteger(Sign.Positive, bi.length - (uint)w + 1);
                uint       l   = (uint)ret.data.Length - 1;

                if (s != 0)
                {
                    uint x, carry = 0;

                    while (l-- > 0)
                    {
                        x           = bi.data[l + w];
                        ret.data[l] = (x >> n) | carry;
                        carry       = x << (32 - n);
                    }
                }
                else
                {
                    while (l-- > 0)
                    {
                        ret.data[l] = bi.data[l + w];
                    }
                }
                ret.Normalize();
                return(ret);
            }
コード例 #2
0
        public static BigInteger operator *(BigInteger bi1, BigInteger bi2)
        {
            if (bi1 == 0 || bi2 == 0)
            {
                return(0);
            }

            //
            // Validate pointers
            //
            if (bi1.data.Length < bi1.length)
            {
                throw new IndexOutOfRangeException("bi1 out of range");
            }
            if (bi2.data.Length < bi2.length)
            {
                throw new IndexOutOfRangeException("bi2 out of range");
            }

            BigInteger ret = new BigInteger(Sign.Positive, bi1.length + bi2.length);

            Kernel.Multiply(bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);

            ret.Normalize();
            return(ret);
        }
コード例 #3
0
            public static BigInteger Subtract(BigInteger big, BigInteger small)
            {
                BigInteger result = new BigInteger(Sign.Positive, big.length);

                uint[] r = result.data, b = big.data, s = small.data;
                uint   i = 0, c = 0;

                do
                {
                    uint x = s[i];
                    if (((x += c) < c) | ((r[i] = b[i] - x) > ~x))
                    {
                        c = 1;
                    }
                    else
                    {
                        c = 0;
                    }
                } while (++i < small.length);

                if (i == big.length)
                {
                    goto fixup;
                }

                if (c == 1)
                {
                    do
                    {
                        r[i] = b[i] - 1;
                    }while (b[i++] == 0 && i < big.length);

                    if (i == big.length)
                    {
                        goto fixup;
                    }
                }

                do
                {
                    r[i] = b[i];
                }while (++i < big.length);

fixup:

                result.Normalize();
                return(result);
            }
コード例 #4
0
            /// <summary>
            /// Performs n / d and n % d in one operation.
            /// </summary>
            /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
            /// <param name="d">The divisor</param>
            /// <returns>n % d</returns>
            public static uint SingleByteDivideInPlace(BigInteger n, uint d)
            {
                ulong r = 0;
                uint  i = n.length;

                while (i-- > 0)
                {
                    r       <<= 32;
                    r        |= n.data[i];
                    n.data[i] = (uint)(r / d);
                    r        %= d;
                }
                n.Normalize();

                return((uint)r);
            }
コード例 #5
0
            public static BigInteger MultiplyByDword(BigInteger n, uint f)
            {
                BigInteger ret = new BigInteger(Sign.Positive, n.length + 1);

                uint  i = 0;
                ulong c = 0;

                do
                {
                    c          += (ulong)n.data[i] * (ulong)f;
                    ret.data[i] = (uint)c;
                    c         >>= 32;
                } while (++i < n.length);
                ret.data[i] = (uint)c;
                ret.Normalize();
                return(ret);
            }
コード例 #6
0
            public static BigInteger DwordDiv(BigInteger n, uint d)
            {
                BigInteger ret = new BigInteger(Sign.Positive, n.length);

                ulong r = 0;
                uint  i = n.length;

                while (i-- > 0)
                {
                    r         <<= 32;
                    r          |= n.data[i];
                    ret.data[i] = (uint)(r / d);
                    r          %= d;
                }
                ret.Normalize();

                return(ret);
            }
コード例 #7
0
            public static BigInteger LeftShift(BigInteger bi, int n)
            {
                if (n == 0)
                {
                    return(new BigInteger(bi, bi.length + 1));
                }

                int w = n >> 5;

                n &= ((1 << 5) - 1);

                BigInteger ret = new BigInteger(Sign.Positive, bi.length + 1 + (uint)w);

                uint i = 0, l = bi.length;

                if (n != 0)
                {
                    uint x, carry = 0;
                    while (i < l)
                    {
                        x = bi.data[i];
                        ret.data[i + w] = (x << n) | carry;
                        carry           = x >> (32 - n);
                        i++;
                    }
                    ret.data[i + w] = carry;
                }
                else
                {
                    while (i < l)
                    {
                        ret.data[i + w] = bi.data[i];
                        i++;
                    }
                }

                ret.Normalize();
                return(ret);
            }
コード例 #8
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            /// <summary>
            /// Performs n / d and n % d in one operation.
            /// </summary>
            /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
            /// <param name="d">The divisor</param>
            /// <returns>n % d</returns>
            public static uint SingleByteDivideInPlace(BigInteger n, uint d)
            {
                ulong r = 0;
                uint i = n.length;

                while (i-- > 0)
                {
                    r <<= 32;
                    r |= n.data[i];
                    n.data[i] = (uint)(r / d);
                    r %= d;
                }
                n.Normalize();

                return (uint)r;
            }
コード例 #9
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            public static BigInteger RightShift(BigInteger bi, int n)
            {
                if (n == 0) return new BigInteger(bi);

                int w = n >> 5;
                int s = n & ((1 << 5) - 1);

                BigInteger ret = new BigInteger(Sign.Positive, bi.length - (uint)w + 1);
                uint l = (uint)ret.data.Length - 1;

                if (s != 0)
                {

                    uint x, carry = 0;

                    while (l-- > 0)
                    {
                        x = bi.data[l + w];
                        ret.data[l] = (x >> n) | carry;
                        carry = x << (32 - n);
                    }
                }
                else
                {
                    while (l-- > 0)
                        ret.data[l] = bi.data[l + w];

                }
                ret.Normalize();
                return ret;
            }
コード例 #10
0
            public static BigInteger[] MultiByteDivide(BigInteger bi1, BigInteger bi2)
            {
                if (Compare(bi1, bi2) == Sign.Negative)
                {
                    return new BigInteger[2] {
                               0, new BigInteger(bi1)
                    }
                }
                ;

                bi1.Normalize(); bi2.Normalize();

                if (bi2.length == 1)
                {
                    return(DwordDivMod(bi1, bi2.data[0]));
                }

                var remainderLen = bi1.length + 1;
                var divisorLen   = (int)bi2.length + 1;

                var mask      = 0x80000000;
                var val       = bi2.data[bi2.length - 1];
                var shift     = 0;
                var resultPos = (int)bi1.length - (int)bi2.length;

                while (mask != 0 && (val & mask) == 0)
                {
                    shift++; mask >>= 1;
                }

                var quot = new BigInteger(Sign.Positive, bi1.length - bi2.length + 1);
                var rem  = (bi1 << shift);

                uint[] remainder = rem.data;

                bi2 = bi2 << shift;

                var j   = (int)(remainderLen - bi2.length);
                var pos = (int)remainderLen - 1;

                var   firstDivisorByte  = bi2.data[bi2.length - 1];
                ulong secondDivisorByte = bi2.data[bi2.length - 2];

                while (j > 0)
                {
                    var dividend = ((ulong)remainder[pos] << 32) + remainder[pos - 1];

                    var qHat = dividend / firstDivisorByte;
                    var rHat = dividend % firstDivisorByte;

                    do
                    {
                        if (qHat == 0x100000000 ||
                            (qHat * secondDivisorByte) > ((rHat << 32) + remainder[pos - 2]))
                        {
                            qHat--;
                            rHat += firstDivisorByte;

                            if (rHat < 0x100000000)
                            {
                                continue;
                            }
                        }
                        break;
                    } while (true);

                    //
                    // At this point, q_hat is either exact, or one too large
                    // (more likely to be exact) so, we attempt to multiply the
                    // divisor by q_hat, if we get a borrow, we just subtract
                    // one from q_hat and add the divisor back.
                    //

                    uint  dPos     = 0;
                    var   nPos     = pos - divisorLen + 1;
                    ulong mc       = 0;
                    var   uintQHat = (uint)qHat;
                    do
                    {
                        mc += bi2.data[dPos] * (ulong)uintQHat;
                        uint t = remainder[nPos];
                        remainder[nPos] -= (uint)mc;
                        mc >>= 32;
                        if (remainder[nPos] > t)
                        {
                            mc++;
                        }
                        dPos++; nPos++;
                    } while (dPos < divisorLen);

                    nPos = pos - divisorLen + 1;
                    dPos = 0;

                    // Overestimate
                    if (mc != 0)
                    {
                        uintQHat--;
                        ulong sum = 0;

                        do
                        {
                            sum             = remainder[nPos] + ((ulong)bi2.data[dPos]) + sum;
                            remainder[nPos] = (uint)sum;
                            sum           >>= 32;
                            dPos++; nPos++;
                        } while (dPos < divisorLen);
                    }

                    quot.data[resultPos--] = uintQHat;

                    pos--;
                    j--;
                }

                quot.Normalize();
                rem.Normalize();
                var ret = new[] { quot, rem };

                if (shift != 0)
                {
                    ret[1] >>= shift;
                }

                return(ret);
            }
コード例 #11
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            public static BigInteger LeftShift(BigInteger bi, int n)
            {
                if (n == 0) return new BigInteger(bi, bi.length + 1);

                int w = n >> 5;
                n &= ((1 << 5) - 1);

                BigInteger ret = new BigInteger(Sign.Positive, bi.length + 1 + (uint)w);

                uint i = 0, l = bi.length;
                if (n != 0)
                {
                    uint x, carry = 0;
                    while (i < l)
                    {
                        x = bi.data[i];
                        ret.data[i + w] = (x << n) | carry;
                        carry = x >> (32 - n);
                        i++;
                    }
                    ret.data[i + w] = carry;
                }
                else
                {
                    while (i < l)
                    {
                        ret.data[i + w] = bi.data[i];
                        i++;
                    }
                }

                ret.Normalize();
                return ret;
            }
コード例 #12
0
            public void BarrettReduction(BigInteger x)
            {
                var  n         = mod;
                uint k         = n.length,
                     kPlusOne  = k + 1,
                     kMinusOne = k - 1;

                // x < mod, so nothing to do.
                if (x.length < k)
                {
                    return;
                }

                //
                // Validate pointers
                //
                if (x.data.Length < x.length)
                {
                    throw new IndexOutOfRangeException("x out of range");
                }

                // q1 = x / b^ (k-1)
                // q2 = q1 * constant
                // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne

                // TODO: We should the method in HAC p 604 to do this (14.45)
                var q3 = new BigInteger(Sign.Positive, x.length - kMinusOne + constant.length);

                Kernel.Multiply(x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);

                // r1 = x mod b^ (k+1)
                // i.e. keep the lowest (k+1) words

                var lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;

                x.length = lengthToCopy;
                x.Normalize();

                // r2 = (q3 * n) mod b^ (k+1)
                // partial multiplication of q3 and n

                var r2 = new BigInteger(Sign.Positive, kPlusOne);

                Kernel.MultiplyMod2p32pmod(q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);

                r2.Normalize();

                if (r2 <= x)
                {
                    Kernel.MinusEq(x, r2);
                }
                else
                {
                    var val = new BigInteger(Sign.Positive, kPlusOne + 1);
                    val.data[kPlusOne] = 0x00000001;

                    Kernel.MinusEq(val, r2);
                    Kernel.PlusEq(x, val);
                }

                while (x >= n)
                {
                    Kernel.MinusEq(x, n);
                }
            }
コード例 #13
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            public static BigInteger MultiplyByDword(BigInteger n, uint f)
            {
                BigInteger ret = new BigInteger(Sign.Positive, n.length + 1);

                uint i = 0;
                ulong c = 0;

                do
                {
                    c += (ulong)n.data[i] * (ulong)f;
                    ret.data[i] = (uint)c;
                    c >>= 32;
                } while (++i < n.length);
                ret.data[i] = (uint)c;
                ret.Normalize();
                return ret;

            }
コード例 #14
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            public static void PlusEq(BigInteger bi1, BigInteger bi2)
            {
                uint[] x, y;
                uint yMax, xMax, i = 0;
                bool flag = false;

                // x should be bigger
                if (bi1.length < bi2.length)
                {
                    flag = true;
                    x = bi2.data;
                    xMax = bi2.length;
                    y = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x = bi1.data;
                    xMax = bi1.length;
                    y = bi2.data;
                    yMax = bi2.length;
                }

                uint[] r = bi1.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum += ((ulong)x[i]) + ((ulong)y[i]);
                    r[i] = (uint)sum;
                    sum >>= 32;
                } while (++i < yMax);

                // Copy remainder of longer number while carry propagation is required
                bool carry = (sum != 0);

                if (carry)
                {

                    if (i < xMax)
                    {
                        do
                            carry = ((r[i] = x[i] + 1) == 0);
                        while (++i < xMax && carry);
                    }

                    if (carry)
                    {
                        r[i] = 1;
                        bi1.length = ++i;
                        return;
                    }
                }

                // Copy the rest
                if (flag && i < xMax - 1)
                {
                    do
                        r[i] = x[i];
                    while (++i < xMax);
                }

                bi1.length = xMax + 1;
                bi1.Normalize();
            }
コード例 #15
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            public static BigInteger Subtract(BigInteger big, BigInteger small)
            {
                BigInteger result = new BigInteger(Sign.Positive, big.length);

                uint[] r = result.data, b = big.data, s = small.data;
                uint i = 0, c = 0;

                do
                {

                    uint x = s[i];
                    if (((x += c) < c) | ((r[i] = b[i] - x) > ~x))
                        c = 1;
                    else
                        c = 0;

                } while (++i < small.length);

                if (i == big.length) goto fixup;

                if (c == 1)
                {
                    do
                        r[i] = b[i] - 1;
                    while (b[i++] == 0 && i < big.length);

                    if (i == big.length) goto fixup;
                }

                do
                    r[i] = b[i];
                while (++i < big.length);

            fixup:

                result.Normalize();
                return result;
            }
コード例 #16
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            /// <summary>
            /// Adds two numbers with the same sign.
            /// </summary>
            /// <param name="bi1">A BigInteger</param>
            /// <param name="bi2">A BigInteger</param>
            /// <returns>bi1 + bi2</returns>
            public static BigInteger AddSameSign(BigInteger bi1, BigInteger bi2)
            {
                uint[] x, y;
                uint yMax, xMax, i = 0;

                // x should be bigger
                if (bi1.length < bi2.length)
                {
                    x = bi2.data;
                    xMax = bi2.length;
                    y = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x = bi1.data;
                    xMax = bi1.length;
                    y = bi2.data;
                    yMax = bi2.length;
                }

                BigInteger result = new BigInteger(Sign.Positive, xMax + 1);

                uint[] r = result.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum = ((ulong)x[i]) + ((ulong)y[i]) + sum;
                    r[i] = (uint)sum;
                    sum >>= 32;
                } while (++i < yMax);

                // Copy remainder of longer number while carry propagation is required
                bool carry = (sum != 0);

                if (carry)
                {

                    if (i < xMax)
                    {
                        do
                            carry = ((r[i] = x[i] + 1) == 0);
                        while (++i < xMax && carry);
                    }

                    if (carry)
                    {
                        r[i] = 1;
                        result.length = ++i;
                        return result;
                    }
                }

                // Copy the rest
                if (i < xMax)
                {
                    do
                        r[i] = x[i];
                    while (++i < xMax);
                }

                result.Normalize();
                return result;
            }
コード例 #17
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            public void BarrettReduction(BigInteger x)
            {
                BigInteger n = mod;
                uint k = n.length,
                    kPlusOne = k + 1,
                    kMinusOne = k - 1;

                // x < mod, so nothing to do.
                if (x.length < k) return;

                BigInteger q3;

                //
                // Validate pointers
                //
                if (x.data.Length < x.length) throw new IndexOutOfRangeException("x out of range");

                // q1 = x / b^ (k-1)
                // q2 = q1 * constant
                // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne

                // TODO: We should the method in HAC p 604 to do this (14.45)
                q3 = new BigInteger(Sign.Positive, x.length - kMinusOne + constant.length);
                Kernel.Multiply(x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);

                // r1 = x mod b^ (k+1)
                // i.e. keep the lowest (k+1) words

                uint lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;

                x.length = lengthToCopy;
                x.Normalize();

                // r2 = (q3 * n) mod b^ (k+1)
                // partial multiplication of q3 and n

                BigInteger r2 = new BigInteger(Sign.Positive, kPlusOne);
                Kernel.MultiplyMod2p32pmod(q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);

                r2.Normalize();

                if (r2 <= x)
                {
                    Kernel.MinusEq(x, r2);
                }
                else
                {
                    BigInteger val = new BigInteger(Sign.Positive, kPlusOne + 1);
                    val.data[kPlusOne] = 0x00000001;

                    Kernel.MinusEq(val, r2);
                    Kernel.PlusEq(x, val);
                }

                while (x >= n)
                    Kernel.MinusEq(x, n);
            }
コード例 #18
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
        public static BigInteger operator *(BigInteger bi1, BigInteger bi2)
        {
            if (bi1 == 0 || bi2 == 0) return 0;

            //
            // Validate pointers
            //
            if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException("bi1 out of range");
            if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException("bi2 out of range");

            BigInteger ret = new BigInteger(Sign.Positive, bi1.length + bi2.length);

            Kernel.Multiply(bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);

            ret.Normalize();
            return ret;
        }
コード例 #19
0
            /// <summary>
            /// Adds two numbers with the same sign.
            /// </summary>
            /// <param name="bi1">A BigInteger</param>
            /// <param name="bi2">A BigInteger</param>
            /// <returns>bi1 + bi2</returns>
            public static BigInteger AddSameSign(BigInteger bi1, BigInteger bi2)
            {
                uint[] x, y;
                uint   yMax, xMax, i = 0;

                // x should be bigger
                if (bi1.length < bi2.length)
                {
                    x    = bi2.data;
                    xMax = bi2.length;
                    y    = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x    = bi1.data;
                    xMax = bi1.length;
                    y    = bi2.data;
                    yMax = bi2.length;
                }

                BigInteger result = new BigInteger(Sign.Positive, xMax + 1);

                uint[] r = result.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum   = ((ulong)x[i]) + ((ulong)y[i]) + sum;
                    r[i]  = (uint)sum;
                    sum >>= 32;
                } while (++i < yMax);

                // Copy remainder of longer number while carry propagation is required
                bool carry = (sum != 0);

                if (carry)
                {
                    if (i < xMax)
                    {
                        do
                        {
                            carry = ((r[i] = x[i] + 1) == 0);
                        }while (++i < xMax && carry);
                    }

                    if (carry)
                    {
                        r[i]          = 1;
                        result.length = ++i;
                        return(result);
                    }
                }

                // Copy the rest
                if (i < xMax)
                {
                    do
                    {
                        r[i] = x[i];
                    }while (++i < xMax);
                }

                result.Normalize();
                return(result);
            }
コード例 #20
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            public static BigInteger[] DwordDivMod(BigInteger n, uint d)
            {
                BigInteger ret = new BigInteger(Sign.Positive, n.length);

                ulong r = 0;
                uint i = n.length;

                while (i-- > 0)
                {
                    r <<= 32;
                    r |= n.data[i];
                    ret.data[i] = (uint)(r / d);
                    r %= d;
                }
                ret.Normalize();

                BigInteger rem = (uint)r;

                return new BigInteger[] { ret, rem };
            }
コード例 #21
0
            public static void PlusEq(BigInteger bi1, BigInteger bi2)
            {
                uint[] x, y;
                uint   yMax, xMax, i = 0;
                bool   flag = false;

                // x should be bigger
                if (bi1.length < bi2.length)
                {
                    flag = true;
                    x    = bi2.data;
                    xMax = bi2.length;
                    y    = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x    = bi1.data;
                    xMax = bi1.length;
                    y    = bi2.data;
                    yMax = bi2.length;
                }

                uint[] r = bi1.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum  += ((ulong)x[i]) + ((ulong)y[i]);
                    r[i]  = (uint)sum;
                    sum >>= 32;
                } while (++i < yMax);

                // Copy remainder of longer number while carry propagation is required
                bool carry = (sum != 0);

                if (carry)
                {
                    if (i < xMax)
                    {
                        do
                        {
                            carry = ((r[i] = x[i] + 1) == 0);
                        }while (++i < xMax && carry);
                    }

                    if (carry)
                    {
                        r[i]       = 1;
                        bi1.length = ++i;
                        return;
                    }
                }

                // Copy the rest
                if (flag && i < xMax - 1)
                {
                    do
                    {
                        r[i] = x[i];
                    }while (++i < xMax);
                }

                bi1.length = xMax + 1;
                bi1.Normalize();
            }
コード例 #22
0
ファイル: BigInteger.cs プロジェクト: mrscylla/octotorrent
            public static BigInteger[] multiByteDivide(BigInteger bi1, BigInteger bi2)
            {
                if (Kernel.Compare(bi1, bi2) == Sign.Negative)
                    return new BigInteger[2] { 0, new BigInteger(bi1) };

                bi1.Normalize(); bi2.Normalize();

                if (bi2.length == 1)
                    return DwordDivMod(bi1, bi2.data[0]);

                uint remainderLen = bi1.length + 1;
                int divisorLen = (int)bi2.length + 1;

                uint mask = 0x80000000;
                uint val = bi2.data[bi2.length - 1];
                int shift = 0;
                int resultPos = (int)bi1.length - (int)bi2.length;

                while (mask != 0 && (val & mask) == 0)
                {
                    shift++; mask >>= 1;
                }

                BigInteger quot = new BigInteger(Sign.Positive, bi1.length - bi2.length + 1);
                BigInteger rem = (bi1 << shift);

                uint[] remainder = rem.data;

                bi2 = bi2 << shift;

                int j = (int)(remainderLen - bi2.length);
                int pos = (int)remainderLen - 1;

                uint firstDivisorByte = bi2.data[bi2.length - 1];
                ulong secondDivisorByte = bi2.data[bi2.length - 2];

                while (j > 0)
                {
                    ulong dividend = ((ulong)remainder[pos] << 32) + (ulong)remainder[pos - 1];

                    ulong q_hat = dividend / (ulong)firstDivisorByte;
                    ulong r_hat = dividend % (ulong)firstDivisorByte;

                    do
                    {

                        if (q_hat == 0x100000000 ||
                            (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder[pos - 2]))
                        {
                            q_hat--;
                            r_hat += (ulong)firstDivisorByte;

                            if (r_hat < 0x100000000)
                                continue;
                        }
                        break;
                    } while (true);

                    //
                    // At this point, q_hat is either exact, or one too large
                    // (more likely to be exact) so, we attempt to multiply the
                    // divisor by q_hat, if we get a borrow, we just subtract
                    // one from q_hat and add the divisor back.
                    //

                    uint t;
                    uint dPos = 0;
                    int nPos = pos - divisorLen + 1;
                    ulong mc = 0;
                    uint uint_q_hat = (uint)q_hat;
                    do
                    {
                        mc += (ulong)bi2.data[dPos] * (ulong)uint_q_hat;
                        t = remainder[nPos];
                        remainder[nPos] -= (uint)mc;
                        mc >>= 32;
                        if (remainder[nPos] > t) mc++;
                        dPos++; nPos++;
                    } while (dPos < divisorLen);

                    nPos = pos - divisorLen + 1;
                    dPos = 0;

                    // Overestimate
                    if (mc != 0)
                    {
                        uint_q_hat--;
                        ulong sum = 0;

                        do
                        {
                            sum = ((ulong)remainder[nPos]) + ((ulong)bi2.data[dPos]) + sum;
                            remainder[nPos] = (uint)sum;
                            sum >>= 32;
                            dPos++; nPos++;
                        } while (dPos < divisorLen);

                    }

                    quot.data[resultPos--] = (uint)uint_q_hat;

                    pos--;
                    j--;
                }

                quot.Normalize();
                rem.Normalize();
                BigInteger[] ret = new BigInteger[2] { quot, rem };

                if (shift != 0)
                    ret[1] >>= shift;

                return ret;
            }