Ejemplo n.º 1
0
        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);
        }