// This is the standard modular power algorithm that // you could find in any reference, but its use of // the new modular reduction algorithm is new. // The square and multiply method is in Wikipedia: // https://en.wikipedia.org/wiki/Exponentiation_by_squaring // x^n = (x^2)^((n - 1)/2) if n is odd. // x^n = (x^2)^(n/2) if n is even. internal void ModularPower( Integer Result, Integer Exponent, Integer Modulus, bool UsePresetBaseArray ) { if( Result.IsZero()) return; // With Result still zero. if( Result.IsEqual( Modulus )) { // It is congruent to zero % ModN. Result.SetToZero(); return; } // Result is not zero at this point. if( Exponent.IsZero() ) { Result.SetFromULong( 1 ); return; } if( Modulus.ParamIsGreater( Result )) { // throw( new Exception( "This is not supposed to be input for RSA plain text." )); IntMath.Divide( Result, Modulus, Quotient, Remainder ); Result.Copy( Remainder ); } if( Exponent.IsOne()) { // Result stays the same. return; } if( !UsePresetBaseArray ) SetupGeneralBaseArray( Modulus ); XForModPower.Copy( Result ); ExponentCopy.Copy( Exponent ); int TestIndex = 0; Result.SetFromULong( 1 ); while( true ) { if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1. { IntMath.Multiply( Result, XForModPower ); ModularReduction( TempForModPower, Result ); Result.Copy( TempForModPower ); } ExponentCopy.ShiftRight( 1 ); // Divide by 2. if( ExponentCopy.IsZero()) break; // Square it. IntMath.Multiply( XForModPower, XForModPower ); ModularReduction( TempForModPower, XForModPower ); XForModPower.Copy( TempForModPower ); } // When ModularReduction() gets called it multiplies a base number // by a uint sized digit. So that can make the result one digit bigger // than GeneralBase. Then when they are added up you can get carry // bits that can make it a little bigger. int HowBig = Result.GetIndex() - Modulus.GetIndex(); // if( HowBig > 1 ) // throw( new Exception( "This does happen. Diff: " + HowBig.ToString() )); if( HowBig > 2 ) throw( new Exception( "The never happens. Diff: " + HowBig.ToString() )); ModularReduction( TempForModPower, Result ); Result.Copy( TempForModPower ); IntMath.Divide( Result, Modulus, Quotient, Remainder ); Result.Copy( Remainder ); if( Quotient.GetIndex() > 1 ) throw( new Exception( "This never happens. The quotient index is never more than 1." )); }
// Copyright Eric Chauvin 2015. private int ModularReduction( Integer Result, Integer ToReduce ) { try { if( GeneralBaseArray == null ) throw( new Exception( "SetupGeneralBaseArray() should have already been called." )); Result.SetToZero(); int HowManyToAdd = ToReduce.GetIndex() + 1; if( HowManyToAdd > GeneralBaseArray.Length ) throw( new Exception( "Bug. The Input number should have been reduced first. HowManyToAdd > GeneralBaseArray.Length" )); int BiggestIndex = 0; for( int Count = 0; Count < HowManyToAdd; Count++ ) { // The size of the numbers in GeneralBaseArray are // all less than the size of GeneralBase. // This multiplication by a uint is with a number // that is not bigger than GeneralBase. Compare // this with the two full Muliply() calls done on // each digit of the quotient in LongDivide3(). // AccumulateBase is set to a new value here. int CheckIndex = IntMath.MultiplyUIntFromCopy( AccumulateBase, GeneralBaseArray[Count], ToReduce.GetD( Count )); if( CheckIndex > BiggestIndex ) BiggestIndex = CheckIndex; Result.Add( AccumulateBase ); } return Result.GetIndex(); } catch( Exception Except ) { throw( new Exception( "Exception in ModularReduction(): " + Except.Message )); } }
internal void MakeBaseNumbers() { try { MakeYBaseToPrimesArray(); if( Worker.CancellationPending ) return; Integer YTop = new Integer(); Integer Y = new Integer(); Integer XSquared = new Integer(); Integer Test = new Integer(); YTop.SetToZero(); uint XSquaredBitLength = 1; ExponentVectorNumber ExpNumber = new ExponentVectorNumber( IntMath ); uint Loops = 0; uint BSmoothCount = 0; uint BSmoothTestsCount = 0; uint IncrementYBy = 0; while( true ) { if( Worker.CancellationPending ) return; Loops++; if( (Loops & 0xF) == 0 ) { Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, "Loops: " + Loops.ToString( "N0" )); Worker.ReportProgress( 0, "BSmoothCount: " + BSmoothCount.ToString( "N0" )); Worker.ReportProgress( 0, "BSmoothTestsCount: " + BSmoothTestsCount.ToString( "N0" )); if( BSmoothTestsCount != 0 ) { double TestsRatio = (double)BSmoothCount / (double)BSmoothTestsCount; Worker.ReportProgress( 0, "TestsRatio: " + TestsRatio.ToString( "N3" )); } } /* if( (Loops & 0xFFFFF) == 0 ) { // Use Task Manager to tweak the CPU Utilization if you want // it be below 100 percent. Thread.Sleep( 1 ); } */ // About 98 percent of the time it is running IncrementBy(). IncrementYBy += IncrementConst; uint BitLength = IncrementBy(); const uint SomeOptimumBitLength = 2; if( BitLength < SomeOptimumBitLength ) continue; // This BitLength has to do with how many small factors you want // in the number. But it doesn't limit your factor base at all. // You can still have any size prime in your factor base (up to // IntegerMath.PrimeArrayLength). Compare the size of // YBaseToPrimesArrayLast to IntegerMath.PrimeArrayLength. BSmoothTestsCount++; YTop.AddULong( IncrementYBy ); IncrementYBy = 0; Y.Copy( ProductSqrRoot ); Y.Add( YTop ); XSquared.Copy( Y ); IntMath.DoSquare( XSquared ); if( XSquared.ParamIsGreater( Product )) throw( new Exception( "Bug. XSquared.ParamIsGreater( Product )." )); IntMath.Subtract( XSquared, Product ); XSquaredBitLength = (uint)(XSquared.GetIndex() * 32); uint TopDigit = (uint)XSquared.GetD( XSquared.GetIndex()); uint TopLength = GetBitLength( TopDigit ); XSquaredBitLength += TopLength; if( XSquaredBitLength == 0 ) XSquaredBitLength = 1; // if( ItIsTheAnswerAlready( XSquared )) It's too unlikely. // QuadResCombinatorics could run in parallel to check for that, // and it would be way ahead of this. GetOneMainFactor(); if( OneMainFactor.IsEqual( XSquared )) { MakeFastExpNumber( ExpNumber ); } else { if( OneMainFactor.IsZero()) throw( new Exception( "OneMainFactor.IsZero()." )); IntMath.Divide( XSquared, OneMainFactor, Quotient, Remainder ); ExpNumber.SetFromTraditionalInteger( Quotient ); ExpNumber.Multiply( ExpOneMainFactor ); ExpNumber.GetTraditionalInteger( Test ); if( !Test.IsEqual( XSquared )) throw( new Exception( "!Test.IsEqual( XSquared )." )); } if( ExpNumber.IsBSmooth()) { BSmoothCount++; string DelimS = IntMath.ToString10( Y ) + "\t" + ExpNumber.ToDelimString(); Worker.ReportProgress( 1, DelimS ); if( (BSmoothCount & 0x3F) == 0 ) { Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, "BitLength: " + BitLength.ToString()); Worker.ReportProgress( 0, "XSquaredBitLength: " + XSquaredBitLength.ToString()); Worker.ReportProgress( 0, ExpNumber.ToString() ); // What should BSmoothLimit be? // (Since FactorDictionary.cs will reduce the final factor base.) if( BSmoothCount > BSmoothLimit ) { Worker.ReportProgress( 0, "Found enough to make the matrix." ); Worker.ReportProgress( 0, "BSmoothCount: " + BSmoothCount.ToString( "N0" )); Worker.ReportProgress( 0, "BSmoothLimit: " + BSmoothLimit.ToString( "N0" )); Worker.ReportProgress( 0, "Seconds: " + StartTime.GetSecondsToNow().ToString( "N1" )); double Seconds = StartTime.GetSecondsToNow(); int Minutes = (int)Seconds / 60; int Hours = Minutes / 60; Minutes = Minutes % 60; Seconds = Seconds % 60; string ShowS = "Hours: " + Hours.ToString( "N0" ) + " Minutes: " + Minutes.ToString( "N0" ) + " Seconds: " + Seconds.ToString( "N0" ); Worker.ReportProgress( 0, ShowS ); return; } } } } } catch( Exception Except ) { throw( new Exception( "Exception in MakeBaseNumbers():\r\n" + Except.Message )); } }
internal bool FindTwoFactorsWithFermat( Integer Product, Integer P, Integer Q, ulong MinimumX ) { ECTime StartTime = new ECTime(); StartTime.SetToNow(); Integer TestSqrt = new Integer(); Integer TestSquared = new Integer(); Integer SqrRoot = new Integer(); TestSquared.Copy( Product ); IntMath.Multiply( TestSquared, Product ); IntMath.SquareRoot( TestSquared, SqrRoot ); TestSqrt.Copy( SqrRoot ); IntMath.DoSquare( TestSqrt ); // IntMath.Multiply( TestSqrt, SqrRoot ); if( !TestSqrt.IsEqual( TestSquared )) throw( new Exception( "The square test was bad." )); // Some primes: // 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, // 101, 103, 107 P.SetToZero(); Q.SetToZero(); Integer TestX = new Integer(); SetupQuadResArray( Product ); ulong BaseTo37 = QuadResBigBase * 29UL * 31UL * 37UL; // ulong BaseTo31 = QuadResBigBase * 29UL * 31UL; ulong ProdModTo37 = IntMath.GetMod64( Product, BaseTo37 ); // ulong ProdModTo31 = IntMath.GetMod64( Product, BaseTo31 ); for( ulong BaseCount = 0; BaseCount < (29 * 31 * 37); BaseCount++ ) { if( (BaseCount & 0xF) == 0 ) Worker.ReportProgress( 0, "Find with Fermat BaseCount: " + BaseCount.ToString() ); if( Worker.CancellationPending ) return false; ulong Base = (BaseCount + 1) * QuadResBigBase; // BaseCount times 223,092,870. if( Base < MinimumX ) continue; Base = BaseCount * QuadResBigBase; // BaseCount times 223,092,870. for( uint Count = 0; Count < QuadResArrayLast; Count++ ) { // The maximum CountPart can be is just under half the size of // the Product. (Like if Y - X was equal to 1, and Y + X was // equal to the Product.) If it got anywhere near that big it // would be inefficient to try and find it this way. ulong CountPart = Base + QuadResArray[Count]; ulong Test = ProdModTo37 + (CountPart * CountPart); // ulong Test = ProdModTo31 + (CountPart * CountPart); Test = Test % BaseTo37; // Test = Test % BaseTo31; if( !IntegerMath.IsQuadResidue29( Test )) continue; if( !IntegerMath.IsQuadResidue31( Test )) continue; if( !IntegerMath.IsQuadResidue37( Test )) continue; ulong TestBytes = (CountPart & 0xFFFFF); TestBytes *= (CountPart & 0xFFFFF); ulong ProdBytes = Product.GetD( 1 ); ProdBytes <<= 8; ProdBytes |= Product.GetD( 0 ); uint FirstBytes = (uint)(TestBytes + ProdBytes); if( !IntegerMath.FirstBytesAreQuadRes( FirstBytes )) { // Worker.ReportProgress( 0, "First bytes aren't quad res." ); continue; } TestX.SetFromULong( CountPart ); IntMath.MultiplyULong( TestX, CountPart ); TestX.Add( Product ); // uint Mod37 = (uint)IntMath.GetMod32( TestX, 37 ); // if( !IntegerMath.IsQuadResidue37( Mod37 )) // continue; // Do more of these tests with 41, 43, 47... // if( !IntegerMath.IsQuadResidue41( Mod37 )) // continue; // Avoid doing this square root at all costs. if( IntMath.SquareRoot( TestX, SqrRoot )) { Worker.ReportProgress( 0, " " ); if( (CountPart & 1) == 0 ) Worker.ReportProgress( 0, "CountPart was even." ); else Worker.ReportProgress( 0, "CountPart was odd." ); // Found an exact square root. // P + (CountPart * CountPart) = Y*Y // P = (Y + CountPart)Y - CountPart) P.Copy( SqrRoot ); Integer ForSub = new Integer(); ForSub.SetFromULong( CountPart ); IntMath.Subtract( P, ForSub ); // Make Q the bigger one and put them in order. Q.Copy( SqrRoot ); Q.AddULong( CountPart ); if( P.IsOne() || Q.IsOne()) { // This happens when testing with small primes. Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, "Went all the way to 1 in FindTwoFactorsWithFermat()." ); Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, " " ); P.SetToZero(); // It has no factors. Q.SetToZero(); return true; // Tested everything, so it's a prime. } Worker.ReportProgress( 0, "Found P: " + IntMath.ToString10( P ) ); Worker.ReportProgress( 0, "Found Q: " + IntMath.ToString10( Q ) ); Worker.ReportProgress( 0, "Seconds: " + StartTime.GetSecondsToNow().ToString( "N1" )); Worker.ReportProgress( 0, " " ); throw( new Exception( "Testing this." )); // return true; // With P and Q. } // else // Worker.ReportProgress( 0, "It was not an exact square root." ); } } // P and Q would still be zero if it never found them. return false; }
internal void Subtract( Integer Result, Integer ToSub ) { // This checks that the sign is equal too. if( Result.IsEqual( ToSub )) { Result.SetToZero(); return; } // ParamIsGreater() handles positive and negative values, so if the // parameter is more toward the positive side then it's true. It's greater. // The most common form. They are both positive. if( !Result.IsNegative && !ToSub.IsNegative ) { if( ToSub.ParamIsGreater( Result )) { SubtractPositive( Result, ToSub ); return; } // ToSub is bigger. TempSub1.Copy( Result ); TempSub2.Copy( ToSub ); SubtractPositive( TempSub2, TempSub1 ); Result.Copy( TempSub2 ); Result.IsNegative = true; return; } if( Result.IsNegative && !ToSub.IsNegative ) { TempSub1.Copy( Result ); TempSub1.IsNegative = false; TempSub1.Add( ToSub ); Result.Copy( TempSub1 ); Result.IsNegative = true; return; } if( !Result.IsNegative && ToSub.IsNegative ) { TempSub1.Copy( ToSub ); TempSub1.IsNegative = false; Result.Add( TempSub1 ); return; } if( Result.IsNegative && ToSub.IsNegative ) { TempSub1.Copy( Result ); TempSub1.IsNegative = false; TempSub2.Copy( ToSub ); TempSub2.IsNegative = false; // -12 - -7 = -12 + 7 = -5 // Comparing the positive numbers here. if( TempSub2.ParamIsGreater( TempSub1 )) { SubtractPositive( TempSub1, TempSub2 ); Result.Copy( TempSub1 ); Result.IsNegative = true; return; } // -7 - -12 = -7 + 12 = 5 SubtractPositive( TempSub2, TempSub1 ); Result.Copy( TempSub2 ); Result.IsNegative = false; return; } }
internal void Divide( Integer ToDivideOriginal, Integer DivideByOriginal, Integer Quotient, Integer Remainder ) { if( ToDivideOriginal.IsNegative ) throw( new Exception( "Divide() can't be called with negative numbers." )); if( DivideByOriginal.IsNegative ) throw( new Exception( "Divide() can't be called with negative numbers." )); // Returns true if it divides exactly with zero remainder. // This first checks for some basics before trying to divide it: if( DivideByOriginal.IsZero() ) throw( new Exception( "Divide() dividing by zero." )); ToDivide.Copy( ToDivideOriginal ); DivideBy.Copy( DivideByOriginal ); if( ToDivide.ParamIsGreater( DivideBy )) { Quotient.SetToZero(); Remainder.Copy( ToDivide ); return; // false; } if( ToDivide.IsEqual( DivideBy )) { Quotient.SetFromULong( 1 ); Remainder.SetToZero(); return; // true; } // At this point DivideBy is smaller than ToDivide. if( ToDivide.IsULong() ) { ulong ToDivideU = ToDivide.GetAsULong(); ulong DivideByU = DivideBy.GetAsULong(); ulong QuotientU = ToDivideU / DivideByU; ulong RemainderU = ToDivideU % DivideByU; Quotient.SetFromULong( QuotientU ); Remainder.SetFromULong( RemainderU ); // if( RemainderU == 0 ) return; // true; // else // return false; } if( DivideBy.GetIndex() == 0 ) { ShortDivide( ToDivide, DivideBy, Quotient, Remainder ); return; } // return LongDivide1( ToDivide, DivideBy, Quotient, Remainder ); // return LongDivide2( ToDivide, DivideBy, Quotient, Remainder ); LongDivide3( ToDivide, DivideBy, Quotient, Remainder ); }
internal void MultiplyULong( Integer Result, ulong ToMul ) { // Using compile-time checks, this one overflows: // const ulong Test = ((ulong)0xFFFFFFFF + 1) * ((ulong)0xFFFFFFFF + 1); // This one doesn't: // const ulong Test = (ulong)0xFFFFFFFF * ((ulong)0xFFFFFFFF + 1); if( Result.IsZero()) return; // Then the answer is zero, which it already is. if( ToMul == 0 ) { Result.SetToZero(); return; } ulong B0 = ToMul & 0xFFFFFFFF; ulong B1 = ToMul >> 32; if( B1 == 0 ) { MultiplyUInt( Result, (uint)B0 ); return; } // Since B1 is not zero: if( (Result.GetIndex() + 1) >= Integer.DigitArraySize ) throw( new Exception( "Overflow in MultiplyULong." )); for( int Column = 0; Column <= Result.GetIndex(); Column++ ) { M[Column, 0] = B0 * Result.GetD( Column ); // Column + 1 and Row is 1, so it's just like pen and paper. M[Column + 1, 1] = B1 * Result.GetD( Column ); } // Since B1 is not zero, the index is set one higher. Result.IncrementIndex(); // Might throw an exception if it goes out of range. M[Result.GetIndex(), 0] = 0; // Otherwise it would be undefined // when it's added up below. // Add these up with a carry. Result.SetD( 0, M[0, 0] & 0xFFFFFFFF ); ulong Carry = M[0, 0] >> 32; for( int Column = 1; Column <= Result.GetIndex(); Column++ ) { // This does overflow: // const ulong Test = ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF)) // + ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF)); // Split the ulongs into right and left sides // so that they don't overflow. ulong TotalLeft = 0; ulong TotalRight = 0; // There's only the two rows for this. for( int Row = 0; Row <= 1; Row++ ) { TotalRight += M[Column, Row] & 0xFFFFFFFF; TotalLeft += M[Column, Row] >> 32; } TotalRight += Carry; Result.SetD( Column, TotalRight & 0xFFFFFFFF ); Carry = TotalRight >> 32; Carry += TotalLeft; } if( Carry != 0 ) { Result.IncrementIndex(); // This can throw an exception. Result.SetD( Result.GetIndex(), Carry ); } }
internal void SetFromString( Integer Result, string InString ) { if( InString == null ) throw( new Exception( "InString was null in SetFromString()." )); if( InString.Length < 1 ) { Result.SetToZero(); return; } Base10Number Base10N = new Base10Number(); Integer Tens = new Integer(); Integer OnePart = new Integer(); // This might throw an exception if the string is bad. Base10N.SetFromString( InString ); Result.SetFromULong( Base10N.GetD( 0 )); Tens.SetFromULong( 10 ); for( int Count = 1; Count <= Base10N.GetIndex(); Count++ ) { OnePart.SetFromULong( Base10N.GetD( Count )); Multiply( OnePart, Tens ); Result.Add( OnePart ); MultiplyULong( Tens, 10 ); } }
internal void MultiplyUInt( Integer Result, ulong ToMul ) { try { if( ToMul == 0 ) { Result.SetToZero(); return; } if( ToMul == 1 ) return; for( int Column = 0; Column <= Result.GetIndex(); Column++ ) M[Column, 0] = ToMul * Result.GetD( Column ); // Add these up with a carry. Result.SetD( 0, M[0, 0] & 0xFFFFFFFF ); ulong Carry = M[0, 0] >> 32; for( int Column = 1; Column <= Result.GetIndex(); Column++ ) { // Using a compile-time check on this constant, // this Test value does not overflow: // const ulong Test = ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF)) + 0xFFFFFFFF; // ulong Total = checked( M[Column, 0] + Carry ); ulong Total = M[Column, 0] + Carry; Result.SetD( Column, Total & 0xFFFFFFFF ); Carry = Total >> 32; } if( Carry != 0 ) { Result.IncrementIndex(); // This might throw an exception if it overflows. Result.SetD( Result.GetIndex(), Carry ); } } catch( Exception Except ) { throw( new Exception( "Exception in MultiplyUInt(): " + Except.Message )); } }
internal void GetTraditionalInteger( CRTBase ToGetFrom, Integer ToSet ) { try { if( CRTBaseArray == null ) throw( new Exception( "Bug: The BaseArray should have been set up already." )); // This first one has the prime 2 as its base so // it's going to be set to either zero or one. if( ToGetFrom.GetDigitAt( 0 ) == 1 ) ToSet.SetToOne(); else ToSet.SetToZero(); Integer WorkingBase = new Integer(); for( int Count = 1; Count < ChineseRemainder.DigitsArraySize; Count++ ) { int BaseMult = ToGetFrom.GetDigitAt( Count ); WorkingBase.Copy( BaseArray[Count] ); IntMath.MultiplyUInt( WorkingBase, (uint)BaseMult ); ToSet.Add( WorkingBase ); } } catch( Exception Except ) { throw( new Exception( "Exception in GetTraditionalInteger(): " + Except.Message )); } }
internal void ModularPower( Integer Result, Integer Exponent, Integer GeneralBase ) { // The square and multiply method is in Wikipedia: // https://en.wikipedia.org/wiki/Exponentiation_by_squaring // x^n = (x^2)^((n - 1)/2) if n is odd. // x^n = (x^2)^(n/2) if n is even. if( Result.IsZero()) return; // With Result still zero. if( Result.IsEqual( GeneralBase )) { // It is congruent to zero % ModN. Result.SetToZero(); return; } // Result is not zero at this point. if( Exponent.IsZero() ) { Result.SetFromULong( 1 ); return; } if( GeneralBase.ParamIsGreater( Result )) { // throw( new Exception( "This is not supposed to be input for RSA plain text." )); IntMath.Divide( Result, GeneralBase, Quotient, Remainder ); Result.Copy( Remainder ); } if( Exponent.IsEqualToULong( 1 )) { // Result stays the same. return; } // This could also be called ahead of time if the base (the modulus) // doesn't change. Like when your public key doesn't change. SetupGeneralBaseArray( GeneralBase ); XForModPower.Copy( Result ); ExponentCopy.Copy( Exponent ); int TestIndex = 0; Result.SetFromULong( 1 ); while( true ) { if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1. { IntMath.Multiply( Result, XForModPower ); // Modular Reduction: AddByGeneralBaseArrays( TempForModPower, Result ); Result.Copy( TempForModPower ); } ExponentCopy.ShiftRight( 1 ); // Divide by 2. if( ExponentCopy.IsZero()) break; // Square it. IntMath.Multiply( XForModPower, XForModPower ); // Modular Reduction: AddByGeneralBaseArrays( TempForModPower, XForModPower ); XForModPower.Copy( TempForModPower ); } // When AddByGeneralBaseArrays() gets called it multiplies a number // by a uint sized digit. So that can make the result one digit bigger // than GeneralBase. Then when they are added up you can get carry // bits that can make it a little bigger. // If by chance you got a carry bit on _every_ addition that was done // in AddByGeneralBaseArrays() then this number could increase in size // by 1 bit for each addition that was done. It would take 32 bits of // carrying for HowBig to increase by 1. // See HowManyToAdd in AddByGeneralBaseArrays() for why this check is done. int HowBig = Result.GetIndex() - GeneralBase.GetIndex(); if( HowBig > 2 ) // I have not seen this happen yet. throw( new Exception( "The difference in index size was more than 2. Diff: " + HowBig.ToString() )); // So this Quotient has only one or two 32-bit digits in it. // And this Divide() is only called once at the end. Not in the loop. IntMath.Divide( Result, GeneralBase, Quotient, Remainder ); Result.Copy( Remainder ); }
// This is the Modular Reduction algorithm. It reduces // ToAdd to Result. private int AddByGeneralBaseArrays( Integer Result, Integer ToAdd ) { try { if( GeneralBaseArray == null ) throw( new Exception( "SetupGeneralBaseArray() should have already been called." )); Result.SetToZero(); // The Index size of ToAdd is usually double the length of the modulus // this is reducing it to. Like if you multiply P and Q to get N, then // the ToAdd that comes in here is about the size of N and the GeneralBase // is about the size of P. So the amount of work done here is proportional // to P times N. int HowManyToAdd = ToAdd.GetIndex() + 1; int BiggestIndex = 0; for( int Count = 0; Count < HowManyToAdd; Count++ ) { // The size of the numbers in GeneralBaseArray are all less than // the size of GeneralBase. // This multiplication by a uint is with a number that is not bigger // than GeneralBase. Compare this with the two full Muliply() // calls done on each digit of the quotient in LongDivide3(). // AccumulateArray[Count] is set to a new value here. int CheckIndex = IntMath.MultiplyUIntFromCopy( AccumulateArray[Count], GeneralBaseArray[Count], ToAdd.GetD( Count )); if( CheckIndex > BiggestIndex ) BiggestIndex = CheckIndex; } // Add all of them up at once. AddUpAccumulateArray( Result, HowManyToAdd, BiggestIndex ); return Result.GetIndex(); } catch( Exception Except ) { throw( new Exception( "Exception in AddByGeneralBaseArrays(): " + Except.Message )); } }
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; }