Beispiel #1
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;
        }
Beispiel #2
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 );
              }
        }
Beispiel #3
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 );
        }
Beispiel #4
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;
        }
Beispiel #5
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;
        }
Beispiel #6
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 );
        }
Beispiel #7
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();
        }
Beispiel #8
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
              }
              */
        }
Beispiel #9
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
              }
            */
        }
Beispiel #10
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 );
        }
        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 ));
              }
        }