예제 #1
0
        internal void SubtractPositive( Integer Result, Integer ToSub )
        {
            if( ToSub.IsULong() )
              {
              SubtractULong( Result, ToSub.GetAsULong());
              return;
              }

            if( ToSub.GetIndex() > Result.GetIndex() )
              throw( new Exception( "In Subtract() ToSub.Index > Index." ));

            for( int Count = 0; Count <= ToSub.GetIndex(); Count++ )
              SignedD[Count] = (long)Result.GetD( Count ) - (long)ToSub.GetD( Count );

            for( int Count = ToSub.GetIndex() + 1; Count <= Result.GetIndex(); Count++ )
              SignedD[Count] = (long)Result.GetD( Count );

            for( int Count = 0; Count < Result.GetIndex(); Count++ )
              {
              if( SignedD[Count] < 0 )
            {
            SignedD[Count] += (long)0xFFFFFFFF + 1;
            SignedD[Count + 1]--;
            }
              }

            if( SignedD[Result.GetIndex()] < 0 )
              throw( new Exception( "Subtract() SignedD[Index] < 0." ));

            for( int Count = 0; Count <= Result.GetIndex(); Count++ )
              Result.SetD( Count, (ulong)SignedD[Count] );

            for( int Count = Result.GetIndex(); Count >= 0; Count-- )
              {
              if( Result.GetD( Count ) != 0 )
            {
            Result.SetIndex( Count );
            return;
            }
              }

            // If it never found a non-zero digit it would get down to here.
            Result.SetIndex( 0 );
        }
예제 #2
0
        private void SetupQuadResArray( Integer Product )
        {
            // I'm doing this differently from finding y^2 = x^2 - N,
            // which I think would be faster, unless it complicates it too
            // much by having to use large Integers and doing subtraction.
            // Here it's looking for when
            // P + x^2 = y^2.

            // private uint[] QuadResArraySmall;
            // private uint[] QuadResArray;
            uint SmallBase = 2 * 3 * 5 * 7 * 11 * 13; // 30,030
            //               2   3   3   4    6    7
            int SmallBaseArraySize = 2 * 3 * 3 * 4 * 6 * 7; // This is not exact.
            uint[] QuadResArraySmall = new uint[SmallBaseArraySize];
            uint QuadResArraySmallLast = 0;
            uint ProductModSmall = (uint)IntMath.GetMod32( Product, SmallBase );
            QuadResArraySmallLast = 0;
            uint ProdMod4 = (uint)Product.GetD( 0 ) & 3;
            for( ulong Count = 0; Count < SmallBase; Count++ )
              {
              // P is odd.
              // if x is even then y is odd.
              // if x is odd then y is even.
              // If x is even then x^2 is divisible by 4.
              // If y is even then y^2 is divisible by 4.

              ulong Test = ProductModSmall + (Count * Count); // The Product plus a square.
              Test = Test % SmallBase;
              if( !IntegerMath.IsSmallQuadResidue( (uint)Test ))
            continue;

              // What Count was used to make a quad residue?
              QuadResArraySmall[QuadResArraySmallLast] = (uint)Count;
              QuadResArraySmallLast++;
              if( QuadResArraySmallLast >= SmallBaseArraySize )
            throw( new Exception( "Went past the small quad res array." ));

              }

            // Worker.ReportProgress( 0, "Finished setting up small quad res array." );

            QuadResBigBase = SmallBase * 17 * 19 * 23; // 223,092,870
            //                                             17   19   23
            int QuadResBaseArraySize = SmallBaseArraySize * 9 * 10 * 12; // This is not exact.

            QuadResArray = new uint[QuadResBaseArraySize];

            uint ProductMod = (uint)IntMath.GetMod32( Product, QuadResBigBase );
            int MaxLength = QuadResArray.Length;

            QuadResArrayLast = 0;
            for( ulong Count23 = 0; Count23 < (17 * 19 * 23); Count23++ )
              {
              if( Worker.CancellationPending )
            return;

              ulong BasePart = Count23 * SmallBase;
              for( uint Count = 0; Count < QuadResArraySmallLast; Count++ )
            {
            ulong CountPart = BasePart + QuadResArraySmall[Count];
            ulong Test = ProductMod + (CountPart * CountPart); // The Product plus a square.
            Test = Test % QuadResBigBase;
            if( !IntegerMath.IsQuadResidue17To23( (uint)Test ))
              continue;

            // What Count was used to make a quad residue?
            QuadResArray[QuadResArrayLast] = (uint)CountPart;
            QuadResArrayLast++;
            if( QuadResArrayLast >= MaxLength )
              throw( new Exception( "Went past the quad res array." ));

            }
              }

            Worker.ReportProgress( 0, "Finished setting up main quad res array." );
        }
예제 #3
0
        // Factor1 is along the top.
        internal void SetFactor1( Integer UseBigIntToSet )
        {
            Integer BigIntToSet = new Integer();
            BigIntToSet.Copy( UseBigIntToSet );

            if( (BigIntToSet.GetD( 0 ) & 1 ) != 1 )
              throw( new Exception( "Factor1 can't be even." ));

            uint ToSet = MultArray[0].OneLine[0];
            ToSet = SetMult1( ToSet );
            ToSet = SetMult2( ToSet );
            ToSet = SetMult( ToSet );
            ToSet = SetAccumOut( ToSet );
            ToSet = ClearCarryOut( ToSet );
            MultArray[0].OneLine[0] = ToSet;

            // Factor1 has to be odd so Mult1 is set to
            // 1 all the way down the side.

            SetMult1AtColumn( 0 );

            BigIntToSet.ShiftRight( 1 );
            if( BigIntToSet.IsZero())
              throw( new Exception( "Factor1 can't be 1." ));

            // 107 = 64 + 32 + 8 + 2 + 1
            int Where = 1;
            for( int Column = 1; Column < MultArraySize; Column++ )
              {
              ToSet = MultArray[0].OneLine[Column];
              if( (BigIntToSet.GetD( 0 ) & 1 ) == 1 )
            ToSet = SetMult1( ToSet );
              else
            ToSet = ClearMult1( ToSet );

              MultArray[0].OneLine[Column] = ToSet;

              Where = Column;
              BigIntToSet.ShiftRight( 1 );
              if( BigIntToSet.IsZero())
            break;

              }

            // At the last 1 bit.
            // ToSet = MultArray[0].OneLine[Where];

            for( int Column = Where + 1; Column < MultArraySize; Column++ )
              {
              ToSet = MultArray[0].OneLine[Column];
              ToSet = ClearMult1( ToSet );
              ToSet = ClearMult( ToSet );
              ToSet = ClearAccumOut( ToSet );
              ToSet = ClearCarryOut( ToSet );
              MultArray[0].OneLine[Column] = ToSet;
              }
        }
예제 #4
0
        private void SetupBaseValues()
        {
            try
            {
            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, "Top of SetupBaseValues()." );

            // MakeQuadResDigitsArrayRec() sets up each record and its base,
            // so that base should already be set in this record.
            if( QuadResDigitsArray[0].Base == 0 )
              throw( new Exception( "Base was zero in SetupBaseValues() at: 0" ));

            Integer BigBase = new Integer();
            BigBase.SetFromULong( QuadResDigitsArray[0].Base );
            QuadResDigitsArray[0].BigBase = new Integer();
            QuadResDigitsArray[0].BigBase.Copy( BigBase );
            // Zero and one have the same base set here.

            // Count starts at 1, so it's the base at 1.
            int QRLength = QuadResDigitsArray.Length;
            for( int Count = 1; Count < QRLength; Count++ )
              {
              if( QuadResDigitsArray[Count].Base == 0 )
            throw( new Exception( "Base was zero in SetupBaseValues() at: " + Count.ToString() ));

              QuadResDigitsArray[Count].BigBase = new Integer();
              QuadResDigitsArray[Count].BigBase.Copy( BigBase );
              QuadResDigitsArray[Count].BigBaseBottomDigit = (uint)BigBase.GetD( 0 );
              QuadResDigitsArray[Count].BigBaseModCurrentBase = (uint)IntMath.GetMod32( QuadResDigitsArray[Count].BigBase, QuadResDigitsArray[Count].Base );

              // Multiply it by the current base for the next loop.
              IntMath.MultiplyUInt( BigBase, QuadResDigitsArray[Count].Base );
              }
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in SetupCRTBaseValues(): " + Except.Message ));
              }
        }
예제 #5
0
        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 ));
              }
        }
예제 #6
0
        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()." ));
        }
예제 #7
0
        /*
          private bool LongDivide1( Integer ToDivide,
                            Integer DivideBy,
                            Integer Quotient,
                            Integer Remainder )
        {
        Integer Test1 = new Integer();

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

          }

        Quotient.SetDigitAndClear( TestIndex, 1 );
        Quotient.D[TestIndex] = 0;
        uint BitTest = 0x80000000;
        while( true )
          {
          // For-loop to test each bit:
          for( int BitCount = 31; BitCount >= 0; BitCount-- )
        {
        Test1.Copy( Quotient );
        Test1.D[TestIndex] |= BitTest;
        Test1.Multiply( DivideBy );
        if( Test1.ParamIsGreaterOrEq( ToDivide ))
          Quotient.D[TestIndex] |= BitTest; // Then keep the bit.

        BitTest >>= 1;
        }

          if( TestIndex == 0 )
        break;

          TestIndex--;
          BitTest = 0x80000000;
          }

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

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

        // Does not divide it exactly.
        return false;
        }
        */
        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.

            // When you're not testing you wouldn't want to be creating these
            // and allocating the RAM for them each time it's called.
            // Integer Test1 = new Integer();
            // Integer Test2 = new Integer();

            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;
            }

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

            /*
            Test2.Copy( Quotient );
            Test2.SetD( TestIndex, Test2.GetD( TestIndex ) | BitTest );
            Multiply( Test2, DivideBy );

            if( !Test1.IsEqual( Test2 ))
              throw( new Exception( "!Test1.IsEqual( Test2 ) in TestDivideBits()." ));
            */

            }
              else
            {
            TestForBits.Copy( Quotient );
            TestForBits.SetD( TestIndex, TestForBits.GetD( TestIndex ) | BitTest );
            Multiply( TestForBits, DivideBy );
            }

              if( TestForBits.ParamIsGreaterOrEq( ToDivide ))
            Quotient.SetD( TestIndex, Quotient.GetD( TestIndex ) | BitTest ); // Keep the bit.

              BitTest >>= 1;
              }
        }
예제 #8
0
        internal uint IsDivisibleBySmallPrime( Integer ToTest )
        {
            if( (ToTest.GetD( 0 ) & 1) == 0 )
              return 2; // It's divisible by 2.

            for( int Count = 1; Count < PrimeArrayLength; Count++ )
              {
              if( 0 == GetMod32( ToTest, PrimeArray[Count] ))
            return PrimeArray[Count];

              }

            // No small primes divide it.
            return 0;
        }
예제 #9
0
        // See also: http://en.wikipedia.org/wiki/Karatsuba_algorithm
        internal void Multiply( Integer Result, Integer ToMul )
        {
            // try
            // {

            if( Result.IsZero())
              return;

            if( ToMul.IsULong())
              {
              MultiplyULong( Result, ToMul.GetAsULong());
              SetMultiplySign( Result, ToMul );
              return;
              }

            // It could never get here if ToMul is zero because GetIsULong()
            // would be true for zero.
            // if( ToMul.IsZero())

            int TotalIndex = Result.GetIndex() + ToMul.GetIndex();
            if( TotalIndex >= Integer.DigitArraySize )
              throw( new Exception( "Multiply() overflow." ));

            for( int Row = 0; Row <= ToMul.GetIndex(); Row++ )
              {
              if( ToMul.GetD( Row ) == 0 )
            {
            for( int Column = 0; Column <= Result.GetIndex(); Column++ )
              M[Column + Row, Row] = 0;

            }
              else
            {
            for( int Column = 0; Column <= Result.GetIndex(); Column++ )
              M[Column + Row, Row] = ToMul.GetD( Row ) * Result.GetD( Column );

            }
              }

            // Add the columns up with a carry.
            Result.SetD( 0, M[0, 0] & 0xFFFFFFFF );
            ulong Carry = M[0, 0] >> 32;
            for( int Column = 1; Column <= TotalIndex; Column++ )
              {
              ulong TotalLeft = 0;
              ulong TotalRight = 0;
              for( int Row = 0; Row <= ToMul.GetIndex(); Row++ )
            {
            if( Row > Column )
              break;

            if( Column > (Result.GetIndex() + Row) )
              continue;

            // Split the ulongs into right and left sides
            // so that they don't overflow.
            TotalRight += M[Column, Row] & 0xFFFFFFFF;
            TotalLeft += M[Column, Row] >> 32;
            }

              TotalRight += Carry;
              Result.SetD( Column, TotalRight & 0xFFFFFFFF );
              Carry = TotalRight >> 32;
              Carry += TotalLeft;
              }

            Result.SetIndex( TotalIndex );
            if( Carry != 0 )
              {
              Result.IncrementIndex(); // This can throw an exception if it overflowed the index.
              Result.SetD( Result.GetIndex(), Carry );
              }

            SetMultiplySign( Result, ToMul );
        }
예제 #10
0
        private void AddUpAccumulateArray( Integer Result, int HowManyToAdd, int BiggestIndex )
        {
            try
            {
            for( int Count = 0; Count <= (BiggestIndex + 1); Count++ )
              Result.SetD( Count, 0 );

            Result.SetIndex( BiggestIndex );

            for( int Count = 0; Count < HowManyToAdd; Count++ )
              {
              int HowManyDigits = AccumulateArray[Count].GetIndex() + 1;
              for( int CountDigits = 0; CountDigits < HowManyDigits; CountDigits++ )
            {
            ulong Sum = AccumulateArray[Count].GetD( CountDigits ) + Result.GetD( CountDigits );
            Result.SetD( CountDigits, Sum );
            }
              }

            // This is like ax + by + cz + ... = Result.
            // You know what a, b, c... are.
            // But you don't know what x, y, and z are.
            // So how do you reverse this and get x, y and z?
            // Is this reversible?

            Result.OrganizeDigits();
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in AddUpAccumulateArray(): " + Except.Message ));
              }
        }
예제 #11
0
        private void DoCRTTest( Integer StartingNumber )
        {
            CRTMath CRTMath1 = new CRTMath( Worker );
            ECTime CRTTestTime = new ECTime();
            ChineseRemainder CRTTest = new ChineseRemainder( IntMath );
            ChineseRemainder CRTTest2 = new ChineseRemainder( IntMath );
            ChineseRemainder CRTAccumulate = new ChineseRemainder( IntMath );
            ChineseRemainder CRTToTest = new ChineseRemainder( IntMath );
            ChineseRemainder CRTTempEqual = new ChineseRemainder( IntMath );
            ChineseRemainder CRTTestEqual = new ChineseRemainder( IntMath );
            Integer BigBase = new Integer();
            Integer ToTest = new Integer();
            Integer Accumulate = new Integer();
            Integer Test1 = new Integer();
            Integer Test2 = new Integer();

            CRTTest.SetFromTraditionalInteger( StartingNumber );
            // If the digit array size isn't set right in relation to
            // Integer.DigitArraySize then it can cause an error here.
            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( StartingNumber ))
              throw( new Exception( "  !Accumulate.IsEqual( Result )." ));

            CRTTestEqual.SetFromTraditionalInteger( Accumulate );
            if( !CRTMath1.IsEqualToInteger( CRTTestEqual, Accumulate ))
              throw( new Exception( "IsEqualToInteger() didn't work." ));

            // Make sure it works with even numbers too.
            Test1.Copy( StartingNumber );
            Test1.SetD( 0, Test1.GetD( 0 ) & 0xFE );
            CRTTest.SetFromTraditionalInteger( Test1 );
            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( Test1 ))
              throw( new Exception( "For even numbers.  !Accumulate.IsEqual( Test )." ));
            ////////////

            // Make sure the size of this works with the Integer size because
            // an overflow is hard to find.
            CRTTestTime.SetToNow();
            Test1.SetToMaxValueForCRT();
            CRTTest.SetFromTraditionalInteger( Test1 );
            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( Test1 ))
              throw( new Exception( "For the max value. !Accumulate.IsEqual( Test1 )." ));

            // Worker.ReportProgress( 0, "CRT Max test seconds: " + CRTTestTime.GetSecondsToNow().ToString( "N1" ));
            // Worker.ReportProgress( 0, "MaxValue: " + IntMath.ToString10( Accumulate ));
            // Worker.ReportProgress( 0, "MaxValue.Index: " + Accumulate.GetIndex().ToString());

            // Multiplicative Inverse test:
            Integer TestDivideBy = new Integer();
            Integer TestProduct = new Integer();
            ChineseRemainder CRTTestDivideBy = new ChineseRemainder( IntMath );
            ChineseRemainder CRTTestProduct = new ChineseRemainder( IntMath );

            TestDivideBy.Copy( StartingNumber );
            TestProduct.Copy( StartingNumber );
            IntMath.Multiply( TestProduct, TestDivideBy );

            CRTTestDivideBy.SetFromTraditionalInteger( TestDivideBy );
            CRTTestProduct.SetFromTraditionalInteger( TestDivideBy );
            CRTTestProduct.Multiply( CRTTestDivideBy );

            CRTMath1.GetTraditionalInteger( Accumulate, CRTTestProduct );

            if( !Accumulate.IsEqual( TestProduct ))
              throw( new Exception( "Multiply test was bad." ));

            IntMath.Divide( TestProduct, TestDivideBy, Quotient, Remainder );
            if( !Remainder.IsZero())
              throw( new Exception( "This test won't work unless it divides it exactly." ));

            ChineseRemainder CRTTestQuotient = new ChineseRemainder( IntMath );
            CRTMath1.MultiplicativeInverse( CRTTestProduct, CRTTestDivideBy, CRTTestQuotient );

            // Yes, multiplicative inverse is the same number
            // as with regular division.
            Integer TestQuotient = new Integer();
            CRTMath1.GetTraditionalInteger( TestQuotient, CRTTestQuotient );
            if( !TestQuotient.IsEqual( Quotient ))
              throw( new Exception( "Modular Inverse in DoCRTTest didn't work." ));

            // Subtract
            Test1.Copy( StartingNumber );
            IntMath.SetFromString( Test2, "12345678901234567890123456789012345" );

            CRTTest.SetFromTraditionalInteger( Test1 );
            CRTTest2.SetFromTraditionalInteger( Test2 );

            CRTTest.Subtract( CRTTest2 );
            IntMath.Subtract( Test1, Test2 );

            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( Test1 ))
              throw( new Exception( "Subtract test was bad." ));

            // Add
            Test1.Copy( StartingNumber );
            IntMath.SetFromString( Test2, "12345678901234567890123456789012345" );

            CRTTest.SetFromTraditionalInteger( Test1 );
            CRTTest2.SetFromTraditionalInteger( Test2 );

            CRTTest.Add( CRTTest2 );
            IntMath.Add( Test1, Test2 );

            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( Test1 ))
              throw( new Exception( "Add test was bad." ));

            /////////
            CRTBaseMath CBaseMath = new CRTBaseMath( Worker, CRTMath1 );

            ChineseRemainder CRTInput = new ChineseRemainder( IntMath );
            CRTInput.SetFromTraditionalInteger( StartingNumber );

            Test1.Copy( StartingNumber );
            IntMath.SetFromString( Test2, "12345678901234567890123456789012345" );
            IntMath.Add( Test1, Test2 );

            Integer TestModulus = new Integer();
            TestModulus.Copy( Test1 );
            ChineseRemainder CRTTestModulus = new ChineseRemainder( IntMath );
            CRTTestModulus.SetFromTraditionalInteger( TestModulus );

            Integer Exponent = new Integer();
            Exponent.SetFromULong( PubKeyExponentUint );

            CBaseMath.ModularPower( CRTInput, Exponent, CRTTestModulus, false );
            IntMath.IntMathNew.ModularPower( StartingNumber, Exponent, TestModulus, false );

            if( !CRTMath1.IsEqualToInteger( CRTInput, StartingNumber ))
              throw( new Exception( "CRTBase ModularPower() didn't work." ));

            CRTBase ExpTest = new CRTBase( IntMath );
            CBaseMath.SetFromCRTNumber( ExpTest, CRTInput );
            CBaseMath.GetExponentForm( ExpTest, 37 );

            // Worker.ReportProgress( 0, "CRT was good." );
        }
예제 #12
0
        // 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 ));
              }
        }
예제 #13
0
        // Product is along the right side diagonal.
        internal void SetProduct( Integer UseBigIntToSet )
        {
            Integer BigIntToSet = new Integer();
            BigIntToSet.Copy( UseBigIntToSet );

            // Primes: 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
            // 71, 73, 79, 83, 89, 97, 101, 103, 107

            if( (BigIntToSet.GetD( 0 ) & 1 ) != 1 )
              throw( new Exception( "Product can't be even." ));

            int Where = 0;
            uint ToSet = 0;
            for( int Row = 0; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              if( (BigIntToSet.GetD( 0 ) & 1 ) == 1 )
            ToSet = SetAccumOut( ToSet );
              else
            ToSet = ClearAccumOut( ToSet );

              MultArray[Row].OneLine[0] = ToSet;

              Where = Row;
              BigIntToSet.ShiftRight( 1 );
              if( BigIntToSet.IsZero())
            break;

              }

            ProductBitIndex = Where;
            int HowMany = ProductBitIndex + 1;
            MForm.ShowStatus( "There were " + HowMany.ToString() + " bits in the product." );

            // At the last 1 bit.
            ToSet = MultArray[Where].OneLine[0];
            ToSet = ClearCarryOut( ToSet );
            MultArray[Where].OneLine[0] = ToSet;

            // The ProductBits can be:
            // Factor1Bits + Factor2Bits
            // or it can be:
            // Factor1Bits + Factor2Bits + 1
            // ProductBits - Factor1Bits = Factor2Bits ( + 1 or not)
            int Factor1Bits = GetHighestMult1BitIndex() + 1;
            int ProductBits = (Where + 1);
            // Factor2Bits might be this or it might be one
            // less than this.
            int MaximumFactor2Bits = ProductBits - Factor1Bits;
            // Factor2BitIndex = Factor2Bits - 1;

            // Test if the top bit of Factor2 is in the right place.
            // ToSet = MultArray[Factor2BitIndex].OneLine[0];
            // ToSet = SetMult( ToSet );
            // MultArray[Factor2BitIndex].OneLine[0] = ToSet;

            for( int Row = MaximumFactor2Bits + 1; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              ToSet = ClearMult2( ToSet );
              MultArray[Row].OneLine[0] = ToSet;
              }

            for( int Row = Where + 1; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              ToSet = ClearMult2( ToSet );
              ToSet = ClearMult( ToSet );
              ToSet = ClearAccumOut( ToSet );
              ToSet = ClearCarryOut( ToSet );
              MultArray[Row].OneLine[0] = ToSet;
              }
        }
예제 #14
0
        // Factor 2 is along the right side diagonal.
        internal void SetFactor2( Integer UseBigIntToSet )
        {
            Integer BigIntToSet = new Integer();
            BigIntToSet.Copy( UseBigIntToSet );

            if( (BigIntToSet.GetD( 0 ) & 1 ) != 1 )
              throw( new Exception( "Factor2 can't be even." ));

            uint ToSet = MultArray[0].OneLine[0];
            ToSet = SetMult1( ToSet );
            ToSet = SetMult2( ToSet );
            ToSet = SetMult( ToSet );
            ToSet = SetAccumOut( ToSet );
            ToSet = ClearCarryOut( ToSet );
            MultArray[0].OneLine[0] = ToSet;

            // Factor2 has to be odd so Mult2 is set to
            // 1 all the way across the top.
            SetMult2AtRow( 0 );

            BigIntToSet.ShiftRight( 1 );
            if( BigIntToSet.IsZero())
              throw( new Exception( "Factor2 can't be 1." ));

            // 107 = 64 + 32 + 8 + 2 + 1
            int Where = 1;
            for( int Row = 1; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              if( (BigIntToSet.GetD( 0 ) & 1 ) == 1 )
            ToSet = SetMult2( ToSet );
              else
            ToSet = ClearMult2( ToSet );

              MultArray[Row].OneLine[0] = ToSet;

              Where = Row;
              BigIntToSet.ShiftRight( 1 );
              if( BigIntToSet.IsZero())
            break;

              }

            // At the last 1 bit.
            // ToSet = MultArray[Where].OneLine[0];

            for( int Row = Where + 1; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              ToSet = ClearMult2( ToSet );
              MultArray[Row].OneLine[0] = ToSet;
              }
        }
예제 #15
0
        internal void SubtractULong( Integer Result, ulong ToSub )
        {
            if( Result.IsULong())
              {
              ulong ResultU = Result.GetAsULong();
              if( ToSub > ResultU )
            throw( new Exception( "SubULong() (IsULong() and (ToSub > Result)." ));

              ResultU = ResultU - ToSub;
              Result.SetD( 0, ResultU & 0xFFFFFFFF );
              Result.SetD( 1, ResultU >> 32 );
              if( Result.GetD( 1 ) == 0 )
            Result.SetIndex( 0 );
              else
            Result.SetIndex( 1 );

              return;
              }

            // If it got this far then Index is at least 2.
            SignedD[0] = (long)Result.GetD( 0 ) - (long)(ToSub & 0xFFFFFFFF);
            SignedD[1] = (long)Result.GetD( 1 ) - (long)(ToSub >> 32);

            if( (SignedD[0] >= 0) && (SignedD[1] >= 0) )
              {
              // No need to reorganize it.
              Result.SetD( 0, (ulong)SignedD[0] );
              Result.SetD( 1, (ulong)SignedD[1] );
              return;
              }

            for( int Count = 2; Count <= Result.GetIndex(); Count++ )
              SignedD[Count] = (long)Result.GetD( Count );

            for( int Count = 0; Count < Result.GetIndex(); Count++ )
              {
              if( SignedD[Count] < 0 )
            {
            SignedD[Count] += (long)0xFFFFFFFF + 1;
            SignedD[Count + 1]--;
            }
              }

            if( SignedD[Result.GetIndex()] < 0 )
              throw( new Exception( "SubULong() SignedD[Index] < 0." ));

            for( int Count = 0; Count <= Result.GetIndex(); Count++ )
              Result.SetD( Count, (ulong)SignedD[Count] );

            for( int Count = Result.GetIndex(); Count >= 0; Count-- )
              {
              if( Result.GetD( Count ) != 0 )
            {
            Result.SetIndex( Count );
            return;
            }
              }

            // If this was zero it wouldn't find a nonzero
            // digit to set the Index to and it would end up down here.
            Result.SetIndex( 0 );
        }
예제 #16
0
        // This is an optimization for multiplying when only the top digit
        // of a number has been set and all of the other digits are zero.
        internal void MultiplyTop( Integer Result, Integer ToMul )
        {
            // try
            // {
            int TotalIndex = Result.GetIndex() + ToMul.GetIndex();
            if( TotalIndex >= Integer.DigitArraySize )
              throw( new Exception( "MultiplyTop() overflow." ));

            // Just like Multiply() except that all the other rows are zero:

            for( int Column = 0; Column <= ToMul.GetIndex(); Column++ )
              M[Column + Result.GetIndex(), Result.GetIndex()] = Result.GetD( Result.GetIndex() ) * ToMul.GetD( Column );

            for( int Column = 0; Column < Result.GetIndex(); Column++ )
              Result.SetD( Column, 0 );

            ulong Carry = 0;
            for( int Column = 0; Column <= ToMul.GetIndex(); Column++ )
              {
              ulong Total = M[Column + Result.GetIndex(), Result.GetIndex()] + Carry;
              Result.SetD( Column + Result.GetIndex(), Total & 0xFFFFFFFF );
              Carry = Total >> 32;
              }

            Result.SetIndex( TotalIndex );
            if( Carry != 0 )
              {
              Result.SetIndex( Result.GetIndex() + 1 );
              if( Result.GetIndex() >= Integer.DigitArraySize )
            throw( new Exception( "MultiplyTop() overflow." ));

              Result.SetD( Result.GetIndex(), Carry );
              }

            /*
            }
            catch( Exception ) // Except )
              {
              // "Bug in MultiplyTop: " + Except.Message
              }
            */
        }
예제 #17
0
        // Finding the square root of a number is similar to division since
        // it is a search algorithm.  The TestSqrtBits method shown next is
        // very much like TestDivideBits().  It works the same as
        // FindULSqrRoot(), but on a bigger scale.
        /*
          private void TestSqrtBits( int TestIndex, Integer Square, Integer SqrRoot )
        {
        Integer Test1 = new Integer();

        uint BitTest = 0x80000000;
        for( int BitCount = 31; BitCount >= 0; BitCount-- )
          {
          Test1.Copy( SqrRoot );
          Test1.D[TestIndex] |= BitTest;
          Test1.Square();
          if( !Square.ParamIsGreater( Test1 ) )
        SqrRoot.D[TestIndex] |= BitTest; // Use the bit.

          BitTest >>= 1;
          }
        }
        */
        // In the SquareRoot() method SqrRoot.Index is half of Square.Index.
        // Compare this to the Square() method where the Carry might or
        // might not increment the index to an odd number.  (So if the Index
        // was 5 its square root would have an Index of 5 / 2 = 2.)
        // The SquareRoot1() method uses FindULSqrRoot() either to find the
        // whole answer, if it's a small number, or it uses it to find the
        // top part.  Then from there it goes on to a bit by bit search
        // with TestSqrtBits().
        public bool SquareRoot( Integer Square, Integer SqrRoot )
        {
            ulong ToMatch;
            if( Square.IsULong() )
              {
              ToMatch = Square.GetAsULong();
              SqrRoot.SetD( 0, FindULSqrRoot( ToMatch ));
              SqrRoot.SetIndex( 0 );
              if( (SqrRoot.GetD(0 ) * SqrRoot.GetD( 0 )) == ToMatch )
            return true;
              else
            return false;

              }

            int TestIndex = Square.GetIndex() >> 1; // LgSquare.Index / 2;
            SqrRoot.SetDigitAndClear( TestIndex, 1 );
            // if( (TestIndex * 2) > (LgSquare.Index - 1) )
            if( (TestIndex << 1) > (Square.GetIndex() - 1) )
              {
              ToMatch = Square.GetD( Square.GetIndex());
              }
            else
              {
              // LgSquare.Index is at least 2 here.
              ToMatch = Square.GetD( Square.GetIndex()) << 32;
              ToMatch |= Square.GetD( Square.GetIndex() - 1 );
              }

            SqrRoot.SetD( TestIndex, FindULSqrRoot( ToMatch ));

            TestIndex--;
            while( true )
              {
              // TestSqrtBits( TestIndex, LgSquare, LgSqrRoot );
              SearchSqrtXPart( TestIndex, Square, SqrRoot );
              if( TestIndex == 0 )
            break;

              TestIndex--;
              }

            // Avoid squaring the whole thing to see if it's an exact square root:
            if( ((SqrRoot.GetD( 0 ) * SqrRoot.GetD( 0 )) & 0xFFFFFFFF) != Square.GetD( 0 ))
              return false;

            TestForSquareRoot.Copy( SqrRoot );
            DoSquare( TestForSquareRoot );
            if( Square.IsEqual( TestForSquareRoot ))
              return true;
            else
              return false;
        }
예제 #18
0
        // This is another optimization.  This is used when the top digit
        // is 1 and all of the other digits are zero.
        // This is effectively just a shift-left operation.
        internal void MultiplyTopOne( Integer Result, Integer ToMul )
        {
            // try
            // {
            int TotalIndex = Result.GetIndex() + ToMul.GetIndex();
            if( TotalIndex >= Integer.DigitArraySize )
              throw( new Exception( "MultiplyTopOne() overflow." ));

            for( int Column = 0; Column <= ToMul.GetIndex(); Column++ )
              Result.SetD( Column + Result.GetIndex(), ToMul.GetD( Column ));

            for( int Column = 0; Column < Result.GetIndex(); Column++ )
              Result.SetD( Column, 0 );

            // No Carrys need to be done.
            Result.SetIndex( TotalIndex );

            /*
            }
            catch( Exception ) // Except )
              {
              // "Bug in MultiplyTopOne: " + Except.Message
              }
              */
        }
예제 #19
0
        // The ShortDivide() algorithm works like dividing a polynomial which
        // looks like:
        // (ax3 + bx2 + cx + d) / N = (ax3 + bx2 + cx + d) * (1/N)
        // The 1/N distributes over the polynomial:
        // (ax3 * (1/N)) + (bx2 * (1/N)) + (cx * (1/N)) + (d * (1/N))
        // (ax3/N) + (bx2/N) + (cx/N) + (d/N)
        // The algorithm goes from left to right and reduces that polynomial
        // expression.  So it starts with Quotient being a copy of ToDivide
        // and then it reduces Quotient from left to right.
        private bool ShortDivide( Integer ToDivide,
                            Integer DivideBy,
                            Integer Quotient,
                            Integer Remainder )
        {
            Quotient.Copy( ToDivide );
            // DivideBy has an Index of zero:
            ulong DivideByU = DivideBy.GetD( 0 );
            ulong RemainderU = 0;

            // Get the first one set up.
            if( DivideByU > Quotient.GetD( Quotient.GetIndex()) )
              {
              Quotient.SetD( Quotient.GetIndex(), 0 );
              }
            else
              {
              ulong OneDigit = Quotient.GetD( Quotient.GetIndex() );
              Quotient.SetD( Quotient.GetIndex(), OneDigit / DivideByU );
              RemainderU = OneDigit % DivideByU;
              ToDivide.SetD( ToDivide.GetIndex(), RemainderU );
              }

            // Now do the rest.
            for( int Count = Quotient.GetIndex(); Count >= 1; Count-- )
              {
              ulong TwoDigits = ToDivide.GetD( Count );
              TwoDigits <<= 32;
              TwoDigits |= ToDivide.GetD( Count - 1 );
              Quotient.SetD( Count - 1, TwoDigits / DivideByU );
              RemainderU = TwoDigits % DivideByU;
              ToDivide.SetD( Count, 0 );
              ToDivide.SetD( Count - 1, RemainderU ); // What's left to divide.
              }

            // Set the index for the quotient.
            // The quotient would have to be at least 1 here,
            // so it will find where to set the index.
            for( int Count = Quotient.GetIndex(); Count >= 0; Count-- )
              {
              if( Quotient.GetD( Count ) != 0 )
            {
            Quotient.SetIndex( Count );
            break;
            }
              }

            Remainder.SetD( 0, RemainderU );
            Remainder.SetIndex( 0 );
            if( RemainderU == 0 )
              return true;
            else
              return false;
        }
예제 #20
0
        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 ));
              }
        }
예제 #21
0
        internal void DoSquare( Integer ToSquare )
        {
            if( ToSquare.GetIndex() == 0 )
              {
              ToSquare.Square0();
              return;
              }

            if( ToSquare.GetIndex() == 1 )
              {
              ToSquare.Square1();
              return;
              }

            if( ToSquare.GetIndex() == 2 )
              {
              ToSquare.Square2();
              return;
              }

            // Now Index is at least 3:
            int DoubleIndex = ToSquare.GetIndex() << 1;
            if( DoubleIndex >= Integer.DigitArraySize )
              {
              throw( new Exception( "Square() overflowed." ));
              }

            for( int Row = 0; Row <= ToSquare.GetIndex(); Row++ )
              {
              if( ToSquare.GetD( Row ) == 0 )
            {
            for( int Column = 0; Column <= ToSquare.GetIndex(); Column++ )
              M[Column + Row, Row] = 0;

            }
              else
            {
            for( int Column = 0; Column <= ToSquare.GetIndex(); Column++ )
              M[Column + Row, Row] = ToSquare.GetD( Row ) * ToSquare.GetD( Column );

            }
              }

            // Add the columns up with a carry.
            ToSquare.SetD( 0, M[0, 0] & 0xFFFFFFFF );
            ulong Carry = M[0, 0] >> 32;
            for( int Column = 1; Column <= DoubleIndex; Column++ )
              {
              ulong TotalLeft = 0;
              ulong TotalRight = 0;
              for( int Row = 0; Row <= Column; Row++ )
            {
            if( Row > ToSquare.GetIndex() )
              break;

            if( Column > (ToSquare.GetIndex() + Row) )
              continue;

            TotalRight += M[Column, Row] & 0xFFFFFFFF;
            TotalLeft += M[Column, Row] >> 32;
            }

              TotalRight += Carry;
              ToSquare.SetD( Column, TotalRight & 0xFFFFFFFF );
              Carry = TotalRight >> 32;
              Carry += TotalLeft;
              }

            ToSquare.SetIndex( DoubleIndex );
            if( Carry != 0 )
              {
              ToSquare.SetIndex( ToSquare.GetIndex() + 1 );
              if( ToSquare.GetIndex() >= Integer.DigitArraySize )
            throw( new Exception( "Square() overflow." ));

              ToSquare.SetD( ToSquare.GetIndex(), Carry );
              }
        }
예제 #22
0
        internal int MultiplyUIntFromCopy( Integer Result, Integer FromCopy, ulong ToMul )
        {
            int FromCopyIndex = FromCopy.GetIndex();
            // The compiler knows that FromCopyIndex doesn't change here so
            // it can do its range checking on the for-loop before it starts.

            Result.SetIndex( FromCopyIndex );
            for( int Column = 0; Column <= FromCopyIndex; Column++ )
              Scratch[Column] = ToMul * FromCopy.GetD( Column );

            // Add these up with a carry.
            Result.SetD( 0, Scratch[0] & 0xFFFFFFFF );
            ulong Carry = Scratch[0] >> 32;
            for( int Column = 1; Column <= FromCopyIndex; Column++ )
              {
              ulong Total = Scratch[Column] + Carry;
              Result.SetD( Column, Total & 0xFFFFFFFF );
              Carry = Total >> 32;
              }

            if( Carry != 0 )
              {
              Result.IncrementIndex(); // This might throw an exception if it overflows.
              Result.SetD( FromCopyIndex + 1, Carry );
              }

            return Result.GetIndex();
        }
예제 #23
0
        internal bool FindTheFactors()
        {
            MakeQuadResToPrimesArray();
            if( Worker.CancellationPending )
              return false;

            // ===========
            MakeQuadResDigitsArrayRec( 0, 0, 7 );
            MakeQuadResDigitsArrayRec( 1, 8, 9 );
            MakeQuadResDigitsArrayRec( 2, 10, 10 );
            // The last one should have an array that is
            // as large as possible because of
            // IncrementDigitsWithBitTest().
            MakeQuadResDigitsArrayRec( 3, 11, 12 );
            if( Worker.CancellationPending )
              return false;

            SetupBaseValues();
            if( Worker.CancellationPending )
              return false;

            MakeMatchingInverseArrays();
            if( Worker.CancellationPending )
              return false;

            Worker.ReportProgress( 0, "After MakeMatchingInverseArrays()." );

            Integer X = new Integer();
            Integer XSquared = new Integer();
            Integer SqrRoot = new Integer();
            Integer YSquared = new Integer();

            MakeGoodXBitsArray();
            Worker.ReportProgress( 0, "After MakeGoodXBitsArray();." );

            uint Loops = 0;
            while( true )
              {
              if( Worker.CancellationPending )
            return false;

              Loops++;
              if( (Loops & 0x3FFFFF) == 0 )
            {
            Worker.ReportProgress( 0, "Loops: " + Loops.ToString());
            }

              GetIntegerValue( X );
              if( !IsInGoodXBitsArray( (uint)X.GetD( 0 )))
            {
            // This happens with the increment bit test
            // because sometimes it just increments to the
            // next full accumulated value.

            if( !IncrementDigitsWithBitTest())
              {
              Worker.ReportProgress( 0, "Incremented to the end." );
              return false;
              }

            continue;
            }

              if( !IsGoodXForAllPrimes( X ))
            {
            if( !IncrementDigitsWithBitTest())
              {
              Worker.ReportProgress( 0, "Incremented to the end." );
              return false;
              }

            continue;
            }

              XSquared.Copy( X );
              IntMath.DoSquare( XSquared );
              YSquared.Copy( Product );
              YSquared.Add( XSquared );

              if( IntMath.SquareRoot( YSquared, SqrRoot ))
            {
            return IsSolution( X, SqrRoot );
            }

              if( !IncrementDigitsWithBitTest())
            {
            Worker.ReportProgress( 0, "Incremented to the end." );
            return false;
            }
              }
        }
예제 #24
0
        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 );
              }
        }
예제 #25
0
        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;
        }
예제 #26
0
        // This is a variation on ShortDivide that returns the remainder.
        // Also, DivideBy is a ulong.
        internal ulong ShortDivideRem( Integer ToDivideOriginal,
                               ulong DivideByU,
                               Integer Quotient )
        {
            if( ToDivideOriginal.IsULong())
              {
              ulong ToDiv = ToDivideOriginal.GetAsULong();
              ulong Q = ToDiv / DivideByU;
              Quotient.SetFromULong( Q );
              return ToDiv % DivideByU;
              }

            ToDivide.Copy( ToDivideOriginal );
            Quotient.Copy( ToDivide );

            ulong RemainderU = 0;
            if( DivideByU > Quotient.GetD( Quotient.GetIndex() ))
              {
              Quotient.SetD( Quotient.GetIndex(), 0 );
              }
            else
              {
              ulong OneDigit = Quotient.GetD( Quotient.GetIndex() );
              Quotient.SetD( Quotient.GetIndex(), OneDigit / DivideByU );
              RemainderU = OneDigit % DivideByU;
              ToDivide.SetD( ToDivide.GetIndex(), RemainderU );
              }

            for( int Count = Quotient.GetIndex(); Count >= 1; Count-- )
              {
              ulong TwoDigits = ToDivide.GetD( Count );
              TwoDigits <<= 32;
              TwoDigits |= ToDivide.GetD( Count - 1 );

              Quotient.SetD( Count - 1, TwoDigits / DivideByU );
              RemainderU = TwoDigits % DivideByU;

              ToDivide.SetD( Count, 0 );
              ToDivide.SetD( Count - 1, RemainderU );
              }

            for( int Count = Quotient.GetIndex(); Count >= 0; Count-- )
              {
              if( Quotient.GetD( Count ) != 0 )
            {
            Quotient.SetIndex( Count );
            break;
            }
              }

            return RemainderU;
        }
예제 #27
0
        // 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 ));
              }
        }
예제 #28
0
        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;
        }