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