Beispiel #1
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 );
              }
        }
Beispiel #2
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 ));
              }
        }
Beispiel #3
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 #4
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 );
        }