private void LongDivide3( Integer ToDivide, Integer DivideBy, Integer Quotient, Integer Remainder ) { 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 ); 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 ); MultiplyTop( TestForDivide1, DivideBy ); /* Test2.Copy( Quotient ); Test2.SetD( TestIndex, MaxValue ); 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 ); MultiplyTop( TestForDivide1, DivideBy ); /* Test2.Copy( Quotient ); Test2.SetD( TestIndex, MaxValue ); Multiply( Test2, DivideBy ); if( !Test2.IsEqual( Test1 )) throw( new Exception( "Top one. !Test2.IsEqual( Test1 ) in LongDivide3()" )); */ 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 ); Multiply( TestForDivide1, DivideByKeep ); Remainder.Copy( ToDivideKeep ); 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. Multiply( TestForDivide1, DivideBy ); // if( ToDivide.ParamIsGreater( TestForDivide1 )) // throw( new Exception( "Bug here in LongDivide3()." )); Remainder.Copy( ToDivide ); 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. 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 ); 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 ); Multiply( TestForDivide1, DivideByKeep ); Remainder.Copy( ToDivideKeep ); Subtract( Remainder, TestForDivide1 ); // if( DivideByKeep.ParamIsGreater( Remainder )) // throw( new Exception( "Remainder > DivideBy in LongDivide3()." )); }
internal bool GetProduct( Integer BigIntToSet ) { BigIntToSet.SetToZero(); if( !AllProductBitsAreKnown()) return false; int Highest = GetHighestProductBitIndex(); for( int Row = Highest; Row >= 0; Row-- ) { // The first time through it will just shift zero // to the left, so nothing happens with zero. BigIntToSet.ShiftLeft( 1 ); uint ToSet = MultArray[Row].OneLine[0]; if( GetAccumOutValue( ToSet )) { ulong D = BigIntToSet.GetD( 0 ); D |= 1; BigIntToSet.SetD( 0, D ); } } return true; }