internal void SetFromString(Integer Result, string InString) { if (InString == null) { throw(new Exception("InString was null in SetFromString().")); } if (InString.Length < 1) { Result.SetToZero(); return; } Base10Number Base10N = new Base10Number(); Integer Tens = new Integer(); Integer OnePart = new Integer(); // This might throw an exception if the string is bad. Base10N.SetFromString(InString); Result.SetFromULong(Base10N.GetD(0)); Tens.SetFromULong(10); for (int Count = 1; Count <= Base10N.GetIndex(); Count++) { OnePart.SetFromULong(Base10N.GetD(Count)); Multiplier.Multiply(OnePart, Tens); Result.Add(OnePart); Multiplier.MultiplyULong(Tens, 10); } }
// 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)); } }
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 void Subtract(Integer Result, Integer ToSub) { // This checks that the sign is equal too. if (Result.IsEqual(ToSub)) { Result.SetToZero(); return; } // ParamIsGreater() handles positive and negative values, so if the // parameter is more toward the positive side then it's true. It's greater. // The most common form. They are both positive. if (!Result.IsNegative && !ToSub.IsNegative) { if (ToSub.ParamIsGreater(Result)) { SubtractPositive(Result, ToSub); return; } // ToSub is bigger. TempSub1.Copy(Result); TempSub2.Copy(ToSub); SubtractPositive(TempSub2, TempSub1); Result.Copy(TempSub2); Result.IsNegative = true; return; } if (Result.IsNegative && !ToSub.IsNegative) { TempSub1.Copy(Result); TempSub1.IsNegative = false; TempSub1.Add(ToSub); Result.Copy(TempSub1); Result.IsNegative = true; return; } if (!Result.IsNegative && ToSub.IsNegative) { TempSub1.Copy(ToSub); TempSub1.IsNegative = false; Result.Add(TempSub1); return; } if (Result.IsNegative && ToSub.IsNegative) { TempSub1.Copy(Result); TempSub1.IsNegative = false; TempSub2.Copy(ToSub); TempSub2.IsNegative = false; // -12 - -7 = -12 + 7 = -5 // Comparing the positive numbers here. if (TempSub2.ParamIsGreater(TempSub1)) { SubtractPositive(TempSub1, TempSub2); Result.Copy(TempSub1); Result.IsNegative = true; return; } // -7 - -12 = -7 + 12 = 5 SubtractPositive(TempSub2, TempSub1); Result.Copy(TempSub2); Result.IsNegative = false; return; } }
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 Divide(Integer ToDivideOriginal, Integer DivideByOriginal, Integer Quotient, Integer Remainder) { if (ToDivideOriginal.IsNegative) { throw(new Exception("Divide() can't be called with negative numbers.")); } if (DivideByOriginal.IsNegative) { throw(new Exception("Divide() can't be called with negative numbers.")); } // Returns true if it divides exactly with zero remainder. // This first checks for some basics before trying to divide it: if (DivideByOriginal.IsZero()) { throw(new Exception("Divide() dividing by zero.")); } ToDivide.Copy(ToDivideOriginal); DivideBy.Copy(DivideByOriginal); if (ToDivide.ParamIsGreater(DivideBy)) { Quotient.SetToZero(); Remainder.Copy(ToDivide); return; // false; } if (ToDivide.IsEqual(DivideBy)) { Quotient.SetFromULong(1); Remainder.SetToZero(); return; // true; } // At this point DivideBy is smaller than ToDivide. if (ToDivide.IsULong()) { ulong ToDivideU = ToDivide.GetAsULong(); ulong DivideByU = DivideBy.GetAsULong(); ulong QuotientU = ToDivideU / DivideByU; ulong RemainderU = ToDivideU % DivideByU; Quotient.SetFromULong(QuotientU); Remainder.SetFromULong(RemainderU); // if( RemainderU == 0 ) return; // true; // else // return false; } if (DivideBy.GetIndex() == 0) { ShortDivide(ToDivide, DivideBy, Quotient, Remainder); return; } Integer ToDivideTest2 = new Integer(); Integer DivideByTest2 = new Integer(); Integer QuotientTest2 = new Integer(); Integer RemainderTest2 = new Integer(); Integer ToDivideTest3 = new Integer(); Integer DivideByTest3 = new Integer(); Integer QuotientTest3 = new Integer(); Integer RemainderTest3 = new Integer(); ToDivideTest2.Copy(ToDivide); ToDivideTest3.Copy(ToDivide); DivideByTest2.Copy(DivideBy); DivideByTest3.Copy(DivideBy); LongDivide1(ToDivideTest2, DivideByTest2, QuotientTest2, RemainderTest2); LongDivide2(ToDivideTest3, DivideByTest3, QuotientTest3, RemainderTest3); LongDivide3(ToDivide, DivideBy, Quotient, Remainder); if (!Quotient.IsEqual(QuotientTest2)) { throw(new Exception("!Quotient.IsEqual( QuotientTest2 )")); } if (!Quotient.IsEqual(QuotientTest3)) { throw(new Exception("!Quotient.IsEqual( QuotientTest3 )")); } if (!Remainder.IsEqual(RemainderTest2)) { throw(new Exception("!Remainder.IsEqual( RemainderTest2 )")); } if (!Remainder.IsEqual(RemainderTest3)) { throw(new Exception("!Remainder.IsEqual( RemainderTest3 )")); } }
// 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.")); } }
internal bool MultiplicativeInverse(Integer X, Integer Modulus, Integer MultInverse) { // This is the extended Euclidean Algorithm. // A*X + B*Y = Gcd // A*X + B*Y = 1 If there's a multiplicative inverse. // A*X = 1 - B*Y so A is the multiplicative inverse of X mod Y. if (X.IsZero()) { throw(new Exception("Doing Multiplicative Inverse with a parameter that is zero.")); } if (Modulus.IsZero()) { throw(new Exception("Doing Multiplicative Inverse with a parameter that is zero.")); } // This happens sometimes: // if( Modulus.ParamIsGreaterOrEq( X )) // throw( new Exception( "Modulus.ParamIsGreaterOrEq( X ) for Euclid." )); // Worker.ReportProgress( 0, " " ); // Worker.ReportProgress( 0, " " ); // Worker.ReportProgress( 0, "Top of mod inverse." ); // U is the old part to keep. U0.SetToZero(); U1.SetToOne(); U2.Copy(Modulus); // Don't change the original numbers that came in as parameters. // V is the new part. V0.SetToOne(); V1.SetToZero(); V2.Copy(X); T0.SetToZero(); T1.SetToZero(); T2.SetToZero(); Quotient.SetToZero(); // while( not forever if there's a problem ) for (int Count = 0; Count < 10000; Count++) { if (U2.IsNegative) { throw(new Exception("U2 was negative.")); } if (V2.IsNegative) { throw(new Exception("V2 was negative.")); } IntMath.Divider.Divide(U2, V2, Quotient, Remainder); if (Remainder.IsZero()) { // Worker.ReportProgress( 0, "Remainder is zero. No multiplicative-inverse." ); return(false); } TempEuclid1.Copy(U0); TempEuclid2.Copy(V0); IntMath.Multiplier.Multiply(TempEuclid2, Quotient); IntMath.Subtract(TempEuclid1, TempEuclid2); T0.Copy(TempEuclid1); TempEuclid1.Copy(U1); TempEuclid2.Copy(V1); IntMath.Multiplier.Multiply(TempEuclid2, Quotient); IntMath.Subtract(TempEuclid1, TempEuclid2); T1.Copy(TempEuclid1); TempEuclid1.Copy(U2); TempEuclid2.Copy(V2); IntMath.Multiplier.Multiply(TempEuclid2, Quotient); IntMath.Subtract(TempEuclid1, TempEuclid2); T2.Copy(TempEuclid1); U0.Copy(V0); U1.Copy(V1); U2.Copy(V2); V0.Copy(T0); V1.Copy(T1); V2.Copy(T2); if (Remainder.IsOne()) { // Worker.ReportProgress( 0, " " ); // Worker.ReportProgress( 0, "Remainder is 1. There is a multiplicative-inverse." ); break; } } MultInverse.Copy(T0); if (MultInverse.IsNegative) { IntMath.Add(MultInverse, Modulus); } // Worker.ReportProgress( 0, "MultInverse: " + ToString10( MultInverse )); TestForModInverse1.Copy(MultInverse); TestForModInverse2.Copy(X); IntMath.Multiplier.Multiply(TestForModInverse1, TestForModInverse2); IntMath.Divider.Divide(TestForModInverse1, Modulus, Quotient, Remainder); if (!Remainder.IsOne()) // By the definition of Multiplicative inverse: { throw(new Exception("MultInverse is wrong: " + IntMath.ToString10(Remainder))); } // Worker.ReportProgress( 0, "MultInverse is the right number: " + ToString10( MultInverse )); return(true); }
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); } }