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); }
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); } }
// 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); }
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; } }
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()); }
// 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 * } */ }
// 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 * } */ }
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)); } }
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); }
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); } }
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); }
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().")); } }
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); } }
// 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); } }
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); }
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); }
// 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.")); } }
// 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)); } }