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().")); } }