BigInteger.multiByteDivide C# (CSharp) Method

multiByteDivide() private static method

private static multiByteDivide ( BigInteger bi1, BigInteger bi2, BigInteger outQuotient, BigInteger outRemainder ) : void
bi1 BigInteger
bi2 BigInteger
outQuotient BigInteger
outRemainder BigInteger
return void
        private static void multiByteDivide(BigInteger bi1, BigInteger bi2,
                                            BigInteger outQuotient, BigInteger outRemainder)
        {
                uint[] result = new uint[maxLength];

                int remainderLen = bi1.dataLength + 1;
                uint[] remainder = new uint[remainderLen];

                uint mask = 0x80000000;
                uint val = bi2.data[bi2.dataLength - 1];
                int shift = 0, resultPos = 0;

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

                //Console.WriteLine("shift = {0}", shift);
                //Console.WriteLine("Before bi1 Len = {0}, bi2 Len = {1}", bi1.dataLength, bi2.dataLength);

                for(int i = 0; i < bi1.dataLength; i++)
                        remainder[i] = bi1.data[i];
                shiftLeft(remainder, shift);
                bi2 = bi2 << shift;

                /*
                Console.WriteLine("bi1 Len = {0}, bi2 Len = {1}", bi1.dataLength, bi2.dataLength);
                Console.WriteLine("dividend = " + bi1 + "\ndivisor = " + bi2);
                for(int q = remainderLen - 1; q >= 0; q--)
                        Console.Write("{0:x2}", remainder[q]);
                Console.WriteLine();
                */

                int j = remainderLen - bi2.dataLength;
                int pos = remainderLen - 1;

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

                int divisorLen = bi2.dataLength + 1;
                uint[] dividendPart = new uint[divisorLen];

                while(j > 0)
                {
                        ulong dividend = ((ulong)remainder[pos] << 32) + (ulong)remainder[pos-1];
                        //Console.WriteLine("dividend = {0}", dividend);

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

                        //Console.WriteLine("q_hat = {0:X}, r_hat = {1:X}", q_hat, r_hat);

                        bool done = false;
                        while(!done)
                        {
                                done = true;

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

                                        if(r_hat < 0x100000000)
                                                done = false;
                                }
                        }

                        for(int h = 0; h < divisorLen; h++)
                                dividendPart[h] = remainder[pos-h];

                        BigInteger kk = new BigInteger(dividendPart);
                        BigInteger ss = bi2 * (long)q_hat;

                        //Console.WriteLine("ss before = " + ss);
                        while(ss > kk)
                        {
                                q_hat--;
                                ss -= bi2;
                                //Console.WriteLine(ss);
                        }
                        BigInteger yy = kk - ss;

                        //Console.WriteLine("ss = " + ss);
                        //Console.WriteLine("kk = " + kk);
                        //Console.WriteLine("yy = " + yy);

                        for(int h = 0; h < divisorLen; h++)
                                remainder[pos-h] = yy.data[bi2.dataLength-h];

                        /*
                        Console.WriteLine("dividend = ");
                        for(int q = remainderLen - 1; q >= 0; q--)
                                Console.Write("{0:x2}", remainder[q]);
                        Console.WriteLine("\n************ q_hat = {0:X}\n", q_hat);
                        */

                        result[resultPos++] = (uint)q_hat;

                        pos--;
                        j--;
                }

                outQuotient.dataLength = resultPos;
                int y = 0;
                for(int x = outQuotient.dataLength - 1; x >= 0; x--, y++)
                        outQuotient.data[y] = result[x];
                for(; y < maxLength; y++)
                        outQuotient.data[y] = 0;

                while(outQuotient.dataLength > 1 && outQuotient.data[outQuotient.dataLength-1] == 0)
                        outQuotient.dataLength--;

                if(outQuotient.dataLength == 0)
                        outQuotient.dataLength = 1;

                outRemainder.dataLength = shiftRight(remainder, shift);

                for(y = 0; y < outRemainder.dataLength; y++)
                        outRemainder.data[y] = remainder[y];
                for(; y < maxLength; y++)
                        outRemainder.data[y] = 0;
        }