Beispiel #1
0
        private void TestDivideBits(ulong MaxValue,
                                    bool IsTop,
                                    int TestIndex,
                                    Integer ToDivide,
                                    Integer DivideBy,
                                    Integer Quotient,
                                    Integer Remainder)
        {
            // For a particular value of TestIndex, this does
            // the for-loop to test each bit.

            uint BitTest = 0x80000000;

            for (int BitCount = 31; BitCount >= 0; BitCount--)
            {
                if ((Quotient.GetD(TestIndex) | BitTest) > MaxValue)
                {
                    // If it's more than the MaxValue then the
                    // multiplication test can be skipped for
                    // this bit.
                    // SkippedMultiplies++;
                    BitTest >>= 1;
                    continue;
                }

                TestForBits.Copy(Quotient);

                // Is it only doing the multiplication for the
                // top digit?
                if (IsTop)
                {
                    TestForBits.SetD(TestIndex, TestForBits.GetD(TestIndex) | BitTest);
                    IntMath.MultiplyTop(TestForBits, DivideBy);
                }
                else
                {
                    TestForBits.SetD(TestIndex, TestForBits.GetD(TestIndex) | BitTest);
                    IntMath.Multiply(TestForBits, DivideBy);
                }

                if (TestForBits.ParamIsGreaterOrEq(ToDivide))
                {
                    // It passed the test, so keep the bit.
                    Quotient.SetD(TestIndex, Quotient.GetD(TestIndex) | BitTest);
                }

                BitTest >>= 1;
            }
        }
Beispiel #2
0
        private void LongDivide3(Integer ToDivide,
                                 Integer DivideBy,
                                 Integer Quotient,
                                 Integer Remainder)
        {
            //////////////////
            Integer Test2 = new Integer();
            /////////////////

            int TestIndex = ToDivide.GetIndex() - DivideBy.GetIndex();

            if (TestIndex < 0)
            {
                throw(new Exception("TestIndex < 0 in Divide3."));
            }

            if (TestIndex != 0)
            {
                // Is 1 too high?
                TestForDivide1.SetDigitAndClear(TestIndex, 1);
                IntMath.MultiplyTopOne(TestForDivide1, DivideBy);
                if (ToDivide.ParamIsGreater(TestForDivide1))
                {
                    TestIndex--;
                }
            }

            // Keep a copy of the originals.
            ToDivideKeep.Copy(ToDivide);
            DivideByKeep.Copy(DivideBy);
            ulong TestBits = DivideBy.GetD(DivideBy.GetIndex());
            int   ShiftBy  = FindShiftBy(TestBits);

            ToDivide.ShiftLeft(ShiftBy); // Multiply the numerator and the denominator
            DivideBy.ShiftLeft(ShiftBy); // by the same amount.
            ulong MaxValue;

            if ((ToDivide.GetIndex() - 1) > (DivideBy.GetIndex() + TestIndex))
            {
                MaxValue = ToDivide.GetD(ToDivide.GetIndex());
            }
            else
            {
                MaxValue  = ToDivide.GetD(ToDivide.GetIndex()) << 32;
                MaxValue |= ToDivide.GetD(ToDivide.GetIndex() - 1);
            }

            ulong Denom = DivideBy.GetD(DivideBy.GetIndex());

            if (Denom != 0)
            {
                MaxValue = MaxValue / Denom;
            }
            else
            {
                MaxValue = 0xFFFFFFFF;
            }

            if (MaxValue > 0xFFFFFFFF)
            {
                MaxValue = 0xFFFFFFFF;
            }

            if (MaxValue == 0)
            {
                throw(new Exception("MaxValue is zero at the top in LongDivide3()."));
            }

            Quotient.SetDigitAndClear(TestIndex, 1);
            Quotient.SetD(TestIndex, 0);
            TestForDivide1.Copy(Quotient);
            TestForDivide1.SetD(TestIndex, MaxValue);
            IntMath.MultiplyTop(TestForDivide1, DivideBy);


/////////////
            Test2.Copy(Quotient);
            Test2.SetD(TestIndex, MaxValue);
            IntMath.Multiply(Test2, DivideBy);
            if (!Test2.IsEqual(TestForDivide1))
            {
                throw(new Exception("In Divide3() !IsEqual( Test2, TestForDivide1 )"));
            }
///////////



            if (TestForDivide1.ParamIsGreaterOrEq(ToDivide))
            {
                // ToMatchExactCount++;
                // Most of the time (roughly 5 out of every 6
                // times) this MaxValue estimate is exactly
                // right:
                Quotient.SetD(TestIndex, MaxValue);
            }
            else
            {
                // MaxValue can't be zero here. If it was it
                // would already be low enough before it got
                // here.
                MaxValue--;
                if (MaxValue == 0)
                {
                    throw(new Exception("After decrement: MaxValue is zero in LongDivide3()."));
                }

                TestForDivide1.Copy(Quotient);
                TestForDivide1.SetD(TestIndex, MaxValue);
                IntMath.MultiplyTop(TestForDivide1, DivideBy);
                if (TestForDivide1.ParamIsGreaterOrEq(ToDivide))
                {
                    // ToMatchDecCount++;
                    Quotient.SetD(TestIndex, MaxValue);
                }
                else
                {
                    // TestDivideBits is done as a last resort,
                    // but it's rare.  But it does at least limit
                    // it to a worst case scenario of trying 32
                    // bits, rather than 4 billion or so
                    // decrements.
                    TestDivideBits(MaxValue,
                                   true,
                                   TestIndex,
                                   ToDivide,
                                   DivideBy,
                                   Quotient,
                                   Remainder);
                }

                // TestGap = MaxValue - LgQuotient.D[TestIndex];
                // if( TestGap > HighestToMatchGap )
                // HighestToMatchGap = TestGap;

                // HighestToMatchGap: 4,294,967,293
                // uint size:         4,294,967,295 uint
            }

            // If it's done.
            if (TestIndex == 0)
            {
                TestForDivide1.Copy(Quotient);
                IntMath.Multiply(TestForDivide1, DivideByKeep);
                Remainder.Copy(ToDivideKeep);
                IntMath.Subtract(Remainder, TestForDivide1);
                if (DivideByKeep.ParamIsGreater(Remainder))
                {
                    throw(new Exception("Remainder > DivideBy in LongDivide3()."));
                }

                return;
            }

            // Now do the rest of the digits.
            TestIndex--;
            while (true)
            {
                TestForDivide1.Copy(Quotient);
                // First Multiply() for each digit.
                IntMath.Multiply(TestForDivide1, DivideBy);

                if (ToDivide.ParamIsGreater(TestForDivide1))
                {
                    throw(new Exception("Problem here in LongDivide3()."));
                }

                Remainder.Copy(ToDivide);
                IntMath.Subtract(Remainder, TestForDivide1);
                MaxValue = Remainder.GetD(Remainder.GetIndex()) << 32;
                int CheckIndex = Remainder.GetIndex() - 1;
                if (CheckIndex > 0)
                {
                    MaxValue |= Remainder.GetD(CheckIndex);
                }

                Denom = DivideBy.GetD(DivideBy.GetIndex());
                if (Denom != 0)
                {
                    MaxValue = MaxValue / Denom;
                }
                else
                {
                    MaxValue = 0xFFFFFFFF;
                }

                if (MaxValue > 0xFFFFFFFF)
                {
                    MaxValue = 0xFFFFFFFF;
                }

                TestForDivide1.Copy(Quotient);
                TestForDivide1.SetD(TestIndex, MaxValue);
                // There's a minimum of two full Multiply() operations per digit.
                IntMath.Multiply(TestForDivide1, DivideBy);
                if (TestForDivide1.ParamIsGreaterOrEq(ToDivide))
                {
                    // Most of the time this MaxValue estimate is exactly right:
                    // ToMatchExactCount++;
                    Quotient.SetD(TestIndex, MaxValue);
                }
                else
                {
                    MaxValue--;
                    TestForDivide1.Copy(Quotient);
                    TestForDivide1.SetD(TestIndex, MaxValue);
                    IntMath.Multiply(TestForDivide1, DivideBy);
                    if (TestForDivide1.ParamIsGreaterOrEq(ToDivide))
                    {
                        // ToMatchDecCount++;
                        Quotient.SetD(TestIndex, MaxValue);
                    }
                    else
                    {
                        TestDivideBits(MaxValue,
                                       false,
                                       TestIndex,
                                       ToDivide,
                                       DivideBy,
                                       Quotient,
                                       Remainder);

                        // TestGap = MaxValue - LgQuotient.D[TestIndex];
                        // if( TestGap > HighestToMatchGap )
                        // HighestToMatchGap = TestGap;
                    }
                }

                if (TestIndex == 0)
                {
                    break;
                }

                TestIndex--;
            }

            TestForDivide1.Copy(Quotient);
            IntMath.Multiply(TestForDivide1, DivideByKeep);
            Remainder.Copy(ToDivideKeep);
            IntMath.Subtract(Remainder, TestForDivide1);
            if (DivideByKeep.ParamIsGreater(Remainder))
            {
                throw(new Exception("Remainder > DivideBy in LongDivide3()."));
            }
        }
Beispiel #3
0
        private bool LongDivide1(Integer ToDivide,
                                 Integer DivideBy,
                                 Integer Quotient,
                                 Integer Remainder)
        {
            uint    Digit     = 0;
            Integer Test1     = new Integer();
            int     TestIndex = ToDivide.GetIndex() - DivideBy.GetIndex();

            if (TestIndex != 0)
            {
                // Is 1 too high?
                Test1.SetDigitAndClear(TestIndex, 1);
                IntMath.MultiplyTopOne(Test1, DivideBy);
                if (ToDivide.ParamIsGreater(Test1))
                {
                    TestIndex--;
                }
            }

            Quotient.SetDigitAndClear(TestIndex, 1);
            Quotient.SetD(TestIndex, 0);
            uint BitTest = 0x80000000;

            while (true)
            {
                // For-loop to test each bit:
                for (int BitCount = 31; BitCount >= 0; BitCount--)
                {
                    Test1.Copy(Quotient);
                    Digit = (uint)Test1.GetD(TestIndex) | BitTest;
                    Test1.SetD(TestIndex, Digit);
                    IntMath.Multiply(Test1, DivideBy);
                    if (Test1.ParamIsGreaterOrEq(ToDivide))
                    {
                        Digit = (uint)Quotient.GetD(TestIndex) | BitTest;
                        // I want to keep this bit because it
                        // passed the test.
                        Quotient.SetD(TestIndex, Digit);
                    }

                    BitTest >>= 1;
                }

                if (TestIndex == 0)
                {
                    break;
                }

                TestIndex--;
                BitTest = 0x80000000;
            }

            Test1.Copy(Quotient);
            IntMath.Multiply(Test1, DivideBy);
            if (Test1.IsEqual(ToDivide))
            {
                Remainder.SetToZero();
                return(true); // Divides exactly.
            }

            Remainder.Copy(ToDivide);
            IntMath.Subtract(Remainder, Test1);

            // Does not divide it exactly.
            return(false);
        }