예제 #1
0
파일: Main.cs 프로젝트: Ribtoks/LongInt
 public static SLongIntB StupidGCD(SLongIntB a, SLongIntB b)
 {
     while (b != 0)
     {
         SLongIntB r = a % b;
         a.Assign(b);
         b.Assign(r);
     }
     return a;
 }
예제 #2
0
        /// <summary>
        /// Extended GCD algorithm. Finds U and V, that A*U + B*V = GCD(A, B)
        /// </summary>
        /// <param name="inputA">Number A</param>
        /// <param name="inputB">Number B</param>
        /// <param name="U">U</param>
        /// <param name="V">V</param>
        /// <returns>GCD of A and B</returns>
        public static SLongIntB eXtendedGCD(SLongIntB inputA, SLongIntB inputB, out SLongIntB U, out SLongIntB V)
        {
            // GCD == A*U + B*V

            SLongIntB A = inputA;
            SLongIntB B = inputB;

            U = (SLongIntB)1;
            SLongIntB D = new SLongIntB(A);

            if (B.IsZero())
            {
                V = (SLongIntB)0;

                return D;
            }

            SLongIntB v1 = (SLongIntB)0;
            SLongIntB v3 = new SLongIntB(B);

            SLongIntB Q = null;
            SLongIntB t3 = null;
            SLongIntB t1 = null;

            while (!v3.IsZero())
            {
                LongMath.Divide(D, v3, out Q, out t3);

                t1 = U - (Q*v1);

                U.Assign(v1);
                D.Assign(v3);

                v1.Assign(t1);
                v3.Assign(t3);
            }

            V = D - (U*A);
            V /= B;

            return D;
        }
예제 #3
0
        /// <summary>
        /// Calculates Jacobi symbol for long numbers A and B -  (A/B)
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <returns></returns>
        public static int JacobiSymbol(SLongIntB a, SLongIntB b)
        {
            if (b.IsZero())
            {
                if (a == 1 || a == -1)
                    return 1;
                else
                    return 0;
            }

            if (LongMath.IsEven(a) && LongMath.IsEven(b))
                return 0;

            SLongIntB A = new SLongIntB(a);
            SLongIntB B = new SLongIntB(b);

            sbyte[] mods = new sbyte[] { 0, 1, 0, -1, 0, -1, 0, 1 };

            int v = 0;
            SelfTwoFact(B, out v);

            int k = 1;

            if (v % 2 == 1)
                k = mods[A[0] & 7];

            LongMath.SelfAbs(B);
            if (A < 0)
                k = -k;

            while (A > 0)
            {
                SelfTwoFact(A, out v);

                if (v % 2 == 1)
                    k = mods[B[0] & 7] * k;

                if ((A[0] & B[0] & 2) != 0)
                    k = -k;

                SLongIntB r = LongMath.Abs(A);
                A.Assign(B % r);
                B.Assign(r);
            }

            if (B > 1)
                return 0;
            else
                return k;
        }
예제 #4
0
        /// <summary>
        /// Uses extended GCD Algorithm to find inverted by modulo element
        /// </summary>
        /// <param name="A">Number</param>
        /// <param name="N">Modulo</param>
        /// <param name="U">Inverted element. Can be less, than zero. 
        /// To get always positive number, use eXGCDInvernedSafe instead.</param>
        /// <returns>GCD of A and N</returns>
        public static SLongIntB eXGCDInverted(SLongIntB A, SLongIntB N, out SLongIntB U)
        {
            // 1 == A*U + N*V

            if (A.IsZero())
            {
                U = new SLongIntB();

                if (A.IsZero())
                    return new SLongIntB(N);
                else
                    return new SLongIntB(A);
            }

            U = (SLongIntB)1;
            SLongIntB G = new SLongIntB(A);

            SLongIntB v1 = (SLongIntB)0;
            SLongIntB v3 = new SLongIntB(N);

            SLongIntB Q = null;
            SLongIntB t3 = null;
            SLongIntB t1 = null;

            while (!v3.IsZero())
            {
                LongMath.Divide(G, v3, out Q, out t3);

                t1 = U - (Q*v1);

                U.Assign(v1);
                G.Assign(v3);

                v1.Assign(t1);
                v3.Assign(t3);
            }

            return G;
        }