예제 #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."));
            }

            int Max = ToSub.GetIndex();

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

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

            Max = Result.GetIndex();
            for (int Count = 0; Count < Max; 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."));
            }

            Max = Result.GetIndex();
            for (int Count = 0; Count <= Max; 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 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);
            }
        }
예제 #3
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);
        }
예제 #4
0
        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.

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

                TestForBits.Copy(Quotient);

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

                if (TestForBits.ParamIsGreaterOrEq(ToDivide))
                {
                    // It passed the test, so keep the bit.
                    Quotient.SetD(TestIndex, Quotient.GetD(TestIndex) | BitTest);
                }

                BitTest >>= 1;
            }
        }
예제 #5
0
        internal int MultiplyUIntFromCopy(Integer Result, Integer FromCopy, ulong ToMul)
        {
            int FromCopyIndex = FromCopy.GetIndex();

            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());
        }
예제 #6
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."));
            }

            int ToMulIndex  = ToMul.GetIndex();
            int ResultIndex = Result.GetIndex();

            for (int Column = 0; Column <= ToMulIndex; Column++)
            {
                Result.SetD(Column + ResultIndex, ToMul.GetD(Column));
            }

            for (int Column = 0; Column < ResultIndex; Column++)
            {
                Result.SetD(Column, 0);
            }

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

            /*
             * }
             * catch( Exception ) // Except )
             * {
             * // "Exception in MultiplyTopOne: " + Except.Message
             * }
             */
        }
예제 #7
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:
            int ToMulIndex  = ToMul.GetIndex();
            int ResultIndex = Result.GetIndex();

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

            for (int Column = 0; Column < ResultIndex; Column++)
            {
                Result.SetD(Column, 0);
            }

            ulong Carry = 0;

            for (int Column = 0; Column <= ToMulIndex; Column++)
            {
                ulong Total = M[Column + ResultIndex, ResultIndex] + Carry;
                Result.SetD(Column + ResultIndex, 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 )
             * {
             * // "Exception in MultiplyTop: " + Except.Message
             * }
             */
        }
예제 #8
0
        internal void MultiplyUInt(Integer Result, ulong ToMul)
        {
            try
            {
                if (ToMul == 0)
                {
                    Result.SetToZero();
                    return;
                }

                if (ToMul == 1)
                {
                    return;
                }

                int CountTo = Result.GetIndex();
                for (int Column = 0; Column <= CountTo; 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;
                CountTo = Result.GetIndex();
                for (int Column = 1; Column <= CountTo; 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));
            }
        }
예제 #9
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 == Divider.GetMod32(ToTest, PrimeArray[Count]))
                {
                    return(PrimeArray[Count]);
                }
            }

            // No small primes divide it.
            return(0);
        }
예제 #10
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."));
            }

            int CountTo = Result.GetIndex();

            for (int Column = 0; Column <= CountTo; Column++)
            {
                ulong Digit = Result.GetD(Column);
                M[Column, 0] = B0 * Digit;
                // Column + 1 and Row is 1, so it's just like pen and paper.
                M[Column + 1, 1] = B1 * Digit;
            }

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

            CountTo = Result.GetIndex();
            for (int Column = 1; Column <= CountTo; 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++)
                {
                    ulong MValue = M[Column, Row];
                    TotalRight += MValue & 0xFFFFFFFF;
                    TotalLeft  += MValue >> 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);
            }
        }
예제 #11
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;
            }

            int Max = Result.GetIndex();

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

            Max = Result.GetIndex();
            for (int Count = 0; Count < Max; 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."));
            }

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

            Max = Result.GetIndex();
            for (int Count = Max; 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);
        }
예제 #12
0
        private void LongDivide3(Integer ToDivide,
                                 Integer DivideBy,
                                 Integer Quotient,
                                 Integer Remainder)
        {
            //////////////////
            Integer Test2 = new Integer();
            /////////////////

            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);
                IntMath.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);
            IntMath.MultiplyTop(TestForDivide1, DivideBy);


/////////////
            Test2.Copy(Quotient);
            Test2.SetD(TestIndex, MaxValue);
            IntMath.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);
                IntMath.MultiplyTop(TestForDivide1, DivideBy);
                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);
                IntMath.Multiply(TestForDivide1, DivideByKeep);
                Remainder.Copy(ToDivideKeep);
                IntMath.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.
                IntMath.Multiply(TestForDivide1, DivideBy);

                if (ToDivide.ParamIsGreater(TestForDivide1))
                {
                    throw(new Exception("Problem here in LongDivide3()."));
                }

                Remainder.Copy(ToDivide);
                IntMath.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.
                IntMath.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);
                    IntMath.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);
            IntMath.Multiply(TestForDivide1, DivideByKeep);
            Remainder.Copy(ToDivideKeep);
            IntMath.Subtract(Remainder, TestForDivide1);
            if (DivideByKeep.ParamIsGreater(Remainder))
            {
                throw(new Exception("Remainder > DivideBy in LongDivide3()."));
            }
        }
예제 #13
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);
            }
        }
예제 #14
0
        // This works like LongDivide1 except that it
        // estimates the maximum value for the digit and
        // the for-loop for bit testing is called
        // as a separate function.
        private bool LongDivide2(Integer ToDivide,
                                 Integer DivideBy,
                                 Integer Quotient,
                                 Integer Remainder)
        {
            Integer Test1     = new Integer();
            int     TestIndex = ToDivide.GetIndex() - DivideBy.GetIndex();

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

            // If you were multiplying 99 times 97 you'd get
            // 9,603 and the upper two digits [96] are used
            // to find the MaxValue.  But if you multiply
            // 12 * 13 you'd have 156 and only the upper one
            // digit is used to find the MaxValue.
            // Here it checks if it should use one digit or
            // two:
            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);
            }

            MaxValue = MaxValue / DivideBy.GetD(DivideBy.GetIndex());
            Quotient.SetDigitAndClear(TestIndex, 1);
            Quotient.SetD(TestIndex, 0);
            TestDivideBits(MaxValue,
                           true,
                           TestIndex,
                           ToDivide,
                           DivideBy,
                           Quotient,
                           Remainder);

            if (TestIndex == 0)
            {
                Test1.Copy(Quotient);
                IntMath.Multiply(Test1, DivideBy);
                Remainder.Copy(ToDivide);
                IntMath.Subtract(Remainder, Test1);
                ///////////////
                if (DivideBy.ParamIsGreater(Remainder))
                {
                    throw(new Exception("Remainder > DivideBy in LongDivide2()."));
                }

                //////////////
                if (Remainder.IsZero())
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            TestIndex--;
            while (true)
            {
                // This remainder is used the same way you do
                // long division with paper and pen and you
                // keep working with a remainder until the
                // remainder is reduced to something smaller
                // than DivideBy.  You look at the remainder
                // to estimate your next quotient digit.
                Test1.Copy(Quotient);
                IntMath.Multiply(Test1, DivideBy);
                Remainder.Copy(ToDivide);
                IntMath.Subtract(Remainder, Test1);
                MaxValue  = Remainder.GetD(Remainder.GetIndex()) << 32;
                MaxValue |= Remainder.GetD(Remainder.GetIndex() - 1);
                MaxValue  = MaxValue / DivideBy.GetD(DivideBy.GetIndex());
                TestDivideBits(MaxValue,
                               false,
                               TestIndex,
                               ToDivide,
                               DivideBy,
                               Quotient,
                               Remainder);

                if (TestIndex == 0)
                {
                    break;
                }

                TestIndex--;
            }

            Test1.Copy(Quotient);
            IntMath.Multiply(Test1, DivideBy);
            Remainder.Copy(ToDivide);
            IntMath.Subtract(Remainder, Test1);
            //////////////////////////////
            if (DivideBy.ParamIsGreater(Remainder))
            {
                throw(new Exception("Remainder > DivideBy in LongDivide2()."));
            }

            ////////////////////////////////
            if (Remainder.IsZero())
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #15
0
        private bool LongDivide1(Integer ToDivide,
                                 Integer DivideBy,
                                 Integer Quotient,
                                 Integer Remainder)
        {
            uint    Digit     = 0;
            Integer Test1     = new Integer();
            int     TestIndex = ToDivide.GetIndex() - DivideBy.GetIndex();

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

            Quotient.SetDigitAndClear(TestIndex, 1);
            Quotient.SetD(TestIndex, 0);
            uint BitTest = 0x80000000;

            while (true)
            {
                // For-loop to test each bit:
                for (int BitCount = 31; BitCount >= 0; BitCount--)
                {
                    Test1.Copy(Quotient);
                    Digit = (uint)Test1.GetD(TestIndex) | BitTest;
                    Test1.SetD(TestIndex, Digit);
                    IntMath.Multiply(Test1, DivideBy);
                    if (Test1.ParamIsGreaterOrEq(ToDivide))
                    {
                        Digit = (uint)Quotient.GetD(TestIndex) | BitTest;
                        // I want to keep this bit because it
                        // passed the test.
                        Quotient.SetD(TestIndex, Digit);
                    }

                    BitTest >>= 1;
                }

                if (TestIndex == 0)
                {
                    break;
                }

                TestIndex--;
                BitTest = 0x80000000;
            }

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

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

            // Does not divide it exactly.
            return(false);
        }
예제 #16
0
        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."));
            }

            int CountTo = ToMul.GetIndex();

            for (int Row = 0; Row <= CountTo; Row++)
            {
                if (ToMul.GetD(Row) == 0)
                {
                    int CountZeros = Result.GetIndex();
                    for (int Column = 0; Column <= CountZeros; Column++)
                    {
                        M[Column + Row, Row] = 0;
                    }
                }
                else
                {
                    int CountMult = Result.GetIndex();
                    for (int Column = 0; Column <= CountMult; 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;
            int   ResultIndex = Result.GetIndex();
            int   MulIndex    = ToMul.GetIndex();

            for (int Column = 1; Column <= TotalIndex; Column++)
            {
                ulong TotalLeft  = 0;
                ulong TotalRight = 0;
                for (int Row = 0; Row <= MulIndex; Row++)
                {
                    if (Row > Column)
                    {
                        break;
                    }

                    if (Column > (ResultIndex + 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);
        }
예제 #17
0
        // This is the standard modular power algorithm that
        // you could find in any reference, but its use of
        // my modular reduction algorithm in it is new (in 2015).
        // (I mean as opposed to using some other modular reduction
        // algorithm.)
        // The square and multiply method is in Wikipedia:
        // https://en.wikipedia.org/wiki/Exponentiation_by_squaring
        internal void ModularPower(Integer Result, Integer Exponent, Integer Modulus, bool UsePresetBaseArray)
        {
            if (Result.IsZero())
            {
                return; // With Result still zero.
            }
            if (Result.IsEqual(Modulus))
            {
                // It is congruent to zero % ModN.
                Result.SetToZero();
                return;
            }

            // Result is not zero at this point.
            if (Exponent.IsZero())
            {
                Result.SetFromULong(1);
                return;
            }

            if (Modulus.ParamIsGreater(Result))
            {
                // throw( new Exception( "This is not supposed to be input for RSA plain text." ));
                IntMath.Divider.Divide(Result, Modulus, Quotient, Remainder);
                Result.Copy(Remainder);
            }

            if (Exponent.IsOne())
            {
                // Result stays the same.
                return;
            }

            if (!UsePresetBaseArray)
            {
                IntMath.ModReduction.SetupGeneralBaseArray(Modulus);
            }

            XForModPower.Copy(Result);
            ExponentCopy.Copy(Exponent);
            // int TestIndex = 0;
            Result.SetFromULong(1);
            while (true)
            {
                if ((ExponentCopy.GetD(0) & 1) == 1) // If the bottom bit is 1.
                {
                    IntMath.Multiplier.Multiply(Result, XForModPower);

                    // if( Result.ParamIsGreater( CurrentModReductionBase ))
                    // TestForModReduction2.Copy( Result );

                    IntMath.ModReduction.Reduce(TempForModPower, Result);
                    // ModularReduction2( TestForModReduction2ForModPower, TestForModReduction2 );
                    // if( !TestForModReduction2ForModPower.IsEqual( TempForModPower ))
                    // {
                    // throw( new Exception( "Mod Reduction 2 is not right." ));
                    // }

                    Result.Copy(TempForModPower);
                }

                ExponentCopy.ShiftRight(1); // Divide by 2.
                if (ExponentCopy.IsZero())
                {
                    break;
                }

                // Square it.
                IntMath.Multiplier.Multiply(XForModPower, XForModPower);

                // if( XForModPower.ParamIsGreater( CurrentModReductionBase ))
                IntMath.ModReduction.Reduce(TempForModPower, XForModPower);
                XForModPower.Copy(TempForModPower);
            }

            // When ModularReduction() gets called it multiplies a base number
            // by a uint sized digit.  So that can make the result one digit bigger
            // than GeneralBase.  Then when they are added up you can get carry
            // bits that can make it a little bigger.
            int HowBig = Result.GetIndex() - Modulus.GetIndex();

            // if( HowBig > 1 )
            // throw( new Exception( "This does happen. Diff: " + HowBig.ToString() ));

            // Do a proof for how big this can be.
            if (HowBig > 2)
            {
                throw(new Exception("This never happens. Diff: " + HowBig.ToString()));
            }

            IntMath.ModReduction.Reduce(TempForModPower, Result);
            Result.Copy(TempForModPower);

            // Notice that this Divide() is done once.  Not
            // a thousand or two thousand times.

/*
 *  Integer ResultTest = new Integer();
 *  Integer ModulusTest = new Integer();
 *  Integer QuotientTest = new Integer();
 *  Integer RemainderTest = new Integer();
 *
 *  ResultTest.Copy( Result );
 *  ModulusTest.Copy( Modulus );
 *  IntMath.Divider.DivideForSmallQuotient( ResultTest,
 *                          ModulusTest,
 *                          QuotientTest,
 *                          RemainderTest );
 *
 */

            IntMath.Divider.Divide(Result, Modulus, Quotient, Remainder);

            // if( !RemainderTest.IsEqual( Remainder ))
            // throw( new Exception( "DivideForSmallQuotient() !RemainderTest.IsEqual( Remainder )." ));

            // if( !QuotientTest.IsEqual( Quotient ))
            // throw( new Exception( "DivideForSmallQuotient() !QuotientTest.IsEqual( Quotient )." ));


            Result.Copy(Remainder);
            if (Quotient.GetIndex() > 1)
            {
                throw(new Exception("This never happens. The quotient index is never more than 1."));
            }
        }
예제 #18
0
        // Copyright Eric Chauvin 2015 - 2018.
        internal int Reduce(Integer Result, Integer ToReduce)
        {
            try
            {
                if (ToReduce.ParamIsGreater(CurrentModReductionBase))
                {
                    Result.Copy(ToReduce);
                    return(Result.GetIndex());
                }

                if (GeneralBaseArray == null)
                {
                    throw(new Exception("SetupGeneralBaseArray() should have already been called."));
                }

                Result.SetToZero();
                int TopOfToReduce = ToReduce.GetIndex() + 1;
                if (TopOfToReduce > GeneralBaseArray.Length)
                {
                    throw(new Exception("The Input number should have been reduced first. HowManyToAdd > GeneralBaseArray.Length"));
                }

                // If it gets this far then ToReduce is at
                // least this big.

                int HighestCopyIndex = CurrentModReductionBase.GetIndex();
                Result.CopyUpTo(ToReduce, HighestCopyIndex - 1);

                int BiggestIndex = 0;
                for (int Count = HighestCopyIndex; Count < TopOfToReduce; 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));
            }
        }