Normalize() 개인적인 메소드

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
리턴 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
            /// <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
            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
            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
            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
            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
            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
            /// <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
            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
        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
            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
            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;
            }