www.pudn.com > calc.rar > qres.c
/* qres.c */ #include#include #include "integer.h" #include "fun.h" int JACOBIB(MPI *N, MPI *M) /* * Evaluates the Jacobi symbol (N/M); M odd, M > 0. */ { int sign = 1; unsigned long parity, t; MPI *Tmp, *NN, *MM; NN = MOD(N, M); if (NN->S == 0) { FREEMPI(NN); return (0); } MM = COPYI(M); while (1) { parity = 0; while ((NN->V[0] & 1) == 0) { Tmp = NN; NN = INT0_(NN, (USL)2); FREEMPI(Tmp); parity = 1 - parity; } if (parity) { t = MM->V[0] & 7; if (t == 3 || t == 5) sign = -sign; } if (EQONEI(NN)) break; if ((MM->V[0] & 3) == 3 && (NN->V[0] & 3) == 3) sign = -sign; Tmp = NN; NN = MOD0(MM, NN); FREEMPI(MM); if (NN->S == 0) { FREEMPI(Tmp); FREEMPI(NN); return (0); } MM = Tmp; } FREEMPI(NN); FREEMPI(MM); return (sign); } int JACOBI(USL n, USL m) /* * Evaluates the Jacobi symbol (n/m); m odd, 0 < n < m. */ { int sign = 1; unsigned int parity, temp; unsigned long t; while (1) { parity = 0; while (n % 2 == 0) { n = n / 2; parity = 1 - parity; } if (parity) { t = m % 8; if (t == 3 || t == 5) sign = -sign; } if (n == 1) break; if (m % 4 == 3 && n % 4 == 3) sign = -sign; temp = n; n = m % n; if (n == 0) return (0); m = temp; } return (sign); } void MULTXm(USL a, USL b, USL c, USL d, USL *eptr, USL *fptr, USL x, USL p) /* * *eptr+(*fptr)*sqrt(x)=(a+b*sqrt(x))(c+dsqrt(x)) (mod p). Used in R.C. Peralta's * probabilistic method of finding sqrt(x) (mod p). */ { unsigned long u, v; u = (b * d) % p; v = (a * c) % p; u = (u * x) % p; *eptr = ADDm(v, u, p); u = (b * c) % p; v = (a * d) % p; *fptr = ADDm(v, u, p); return; } void POWERXm(USL a, USL b, USL n, USL *eptr, USL *fptr, USL x, USL p) /* * *eptr+(*fptr)*sqrt(x)=(a+b*sqrt(x))^n (mod p). Used in R.C. Peralta's * probabilistic method of finding sqrt(x) (mod p). */ { unsigned long x1, x2, z1, z2; x1 = a; x2 = b; z1 = 1; z2 = 0; while (n) { while (n % 2 == 0) { n = n / 2; MULTXm(x1, x2, x1, x2, &x1, &x2, x, p); } n = n - 1; MULTXm(z1, z2, x1, x2, &z1, &z2, x, p); } *eptr = z1; *fptr = z2; return; } unsigned long SQRTm(USL x, USL p) /* * Calculates sqrt(x) (mod p) using "A simple and fast probabilistic algorithm * for computing square roots modulo a prime number", I.E.E.E. Trans. Inform. * Theory, IT-32, 1986, 846-847, R. Peralta. * Here x is a quadratic residue mod p, 0 < x < p. */ { unsigned long r, z, u, v; z = (p - 1) / 2; if (p % 4 == 3) return (POWER_m(x, (z + 1) / 2, p)); for ( r = 1; r <= z; r++) { if ( x == (r * r) % p) return (r); POWERXm(r, (USL)1, z, &u, &v, x, p); if (u == 0) break; } return (INVERSEm(v, p)); } void MULTXM(MPI *a, MPI *b, MPI *c, MPI *d, MPI **eptr, MPI **fptr, MPI *x, MPI *p) /* * *eptr+(*fptr)*sqrt(x)=(a+b*sqrt(x))(c+dsqrt(x)) (mod p). Used in R.C. Peralta's * probabilistic method of finding sqrt(x) (mod p). */ { MPI *u, *v, *tmp1, *tmp2, *tmp3; tmp1 = MULTI(b, d); tmp2 = MOD(tmp1, p); FREEMPI(tmp1); tmp3 = MULTI(tmp2, x); FREEMPI(tmp2); u = MOD(tmp3, p); FREEMPI(tmp3); tmp1 = MULTI(a, c); v = MOD(tmp1, p); FREEMPI(tmp1); *eptr = ADDM(v, u, p); tmp2 = u; tmp1 = MULTI(b, c); u = MOD(tmp1, p); FREEMPI(tmp1); FREEMPI(tmp2); tmp2 = v; tmp1 = MULTI(a, d); v = MOD(tmp1, p); FREEMPI(tmp1); FREEMPI(tmp2); *fptr = ADDM(v, u, p); FREEMPI(u); FREEMPI(v); return; } void POWERXM(MPI *a, MPI *b, MPI *n, MPI **eptr, MPI **fptr, MPI *x, MPI *p) /* * *eptr+(*fptr)*sqrt(x)=(a+b*sqrt(x))^n (mod p). Used in R.C. Peralta's * probabilistic method of finding sqrt(x) (mod p). */ { MPI *x1, *x2, *x3, *x4, *x5, *x6, *z1, *z2, *tmp, *tmp1, *tmp2, *N; x1 = COPYI(a); x2 = COPYI(b); z1 = ONEI(); z2 = ZEROI(); N = COPYI(n); while (N->S) { while ((N->V[0]) % 2 == 0) { tmp = N; N = INT0_(N, (USL)2); FREEMPI(tmp); tmp1 = x1; tmp2 = x2; MULTXM(x1, x2, x1, x2, &x3, &x4, x, p); x1 = x3; x2 = x4; FREEMPI(tmp1); FREEMPI(tmp2); } tmp = N; N = SUB0_I(N, (USL)1); FREEMPI(tmp); tmp1 = z1; tmp2 = z2; MULTXM(z1, z2, x1, x2, &x5, &x6, x, p); z1 = x5; z2 = x6; FREEMPI(tmp1); FREEMPI(tmp2); } *eptr = z1; *fptr = z2; FREEMPI(x1); FREEMPI(x2); FREEMPI(N); return; } MPI *SQRTM(MPI *x, MPI *p) /* * Calculates sqrt(x) (mod p) using "A simple and fast probabilistic algorithm * for computing square roots modulo a prime number", I.E.E.E. Trans. Inform. * Theory, IT-32, 1986, 846-847, R. Peralta. * Here x is a quadratic residue mod p. x can be negative. */ { MPI *z, *u, *v, *tmp, *tmp1, *tmp2, *tmp3; unsigned int t; unsigned long r; z = INT0_(p, (USL)2); if ((p->V[0]) % 4 == 3) { tmp = ADD0_I(z, (USL)1); FREEMPI(z); tmp1 = INT0_(tmp, (USL)2); FREEMPI(tmp); tmp2 = MPOWER(x, tmp1, p); FREEMPI(tmp1); return (tmp2); } tmp = ONEI(); for ( r = 1; r < R0; r++) { tmp1 = CHANGE(r); tmp2 = MULTI(tmp1, tmp1); tmp3 = MOD0(tmp2, p); FREEMPI(tmp2); t = EQUALI(x, tmp3); FREEMPI(tmp3); if (t) { FREEMPI(tmp); FREEMPI(z); /* FREEMPI(x); deleted on 10th Dec 2000 */ return (tmp1); } POWERXM(tmp1, tmp, z, &u, &v, x, p); FREEMPI(tmp1); if (u->S == 0) { tmp2 = INVERSEM(v, p); FREEMPI(u); FREEMPI(v); FREEMPI(tmp); FREEMPI(z); break; } FREEMPI(u); FREEMPI(v); } return (tmp2); } MPI *LUCASU(MPI *N, MPI *Q, MPI *M) /* * returns U_n (mod m), where U_{k+1}=U_k-qU_{k-1}, U_0=0,U_1=1. * D=1-4q != 0. * We use the recurrence relations: * U_{k+1}=U_k-qU_{k-1}, * U_{2k}=-2qU_{k-1}U_k+U_kU_k, * U_{2k-1}=U_kU_k-qU_{k-1}U_{k-1} * See Niven, Zuckermann and Montgomery, p.202. * Also D. Bressoud, Factorization and Primality Testing, p.179-191 and * C. Pomerance, Kent State Lecture Notes, 19-22. */ { unsigned int *b, h; int i; MPI *Y, *R, *S, *T, *U, *V, *Temp0, *Temp, *Temp1, *Temp2; if (N->S == 0) return (ZEROI()); if (EQONEI(N)) return(ONEI()); h = 0; b = (USI *)mmalloc(10000 * sizeof(USI)); Y = COPYI(N); while (Y->S) { b[h] = (Y->V[0]) % 2; Temp = Y; Y = INT0_(Y, 2); FREEMPI(Temp); h++; } R = ZEROI(); S = ONEI(); FREEMPI(Y); Temp = MINUSI(Q); T = MOD(Temp, M); FREEMPI(Temp); V = ADDM(T, T, M); i = h - 1; while (1) { U = S; Temp1 = MULTM(V, R, M); Temp2 = ADDM(Temp1, S, M); S = MULTM(Temp2, S, M); FREEMPI(Temp1); FREEMPI(Temp2); Temp0 = MULTM(R, R, M); Temp1 = MULTM(Temp0, T, M); FREEMPI(Temp0); Temp2 = MULTM(U, U, M); FREEMPI(U); Temp = R; R = ADDM(Temp2, Temp1, M); FREEMPI(Temp); FREEMPI(Temp1); FREEMPI(Temp2); i--; if (i == -1) break; if (b[i]) { Temp1 = MULTM(T, R, M); FREEMPI(R); R = S; S = ADDM(S, Temp1, M); FREEMPI(Temp1); } } FREEMPI(R); FREEMPI(T); FREEMPI(V); ffree(b, 10000 * sizeof(USI)); return (S); } MPI *LUCASB(MPI *N) /* * Let N > 1 be odd. Then LUCASB(N) determines an integer D(!=-3) of the form * 4m+1, such that the Jacobi symbol j(D,N)= -1. Then with Q=(1-d)/4, the Lucas * pseudoprime test examines L=U_{(N+1)/2}mod N. If L=0, N is a Lucas probable * prime, otherwise N is composite. See "The Pseudoprimes to 25.10^9", * Mathematics of computation, 35 (1980) 1003-1026. At the end of this paper * it is conjectured that if N is a strong base 2 pseudoprime and a Lucas * probable prime, then N is in fact a prime. A $30 prize is offered for a * counterexample. * if LUCASB(N) = 1, then N is a Lucas probable prime, else N is composite. */ { unsigned int h; MPI *S, *T, *X, *Q, *L, *Temp, *Temp1; int d, t, s; X = BIG_MTHROOT(N, 2); Temp = MULTI(X, X); FREEMPI(X); if (EQUALI(Temp, N)) { /* N is a perfect square */; FREEMPI(Temp); return (ZEROI()); } FREEMPI(Temp); s = 5; t = -7; for (h = 0; 1; h++) { S = CHANGEI(s); if (JACOBIB(S, N) == -1) { FREEMPI(S); d = s; break; } FREEMPI(S); s = s + 4; T = CHANGEI(t); if (JACOBIB(T, N) == -1) { FREEMPI(T); d = t; break; } FREEMPI(T); t = t -4; } Q = CHANGEI((1-d)/4); Temp = ADD0_I(N, 1); Temp1 = INT0_(Temp, 2); FREEMPI(Temp); L = LUCASU(Temp1, Q, N); FREEMPI(Q); FREEMPI(Temp1); t = L->S; FREEMPI(L); if (t == 0)/* N is a Lucas probable prime */ return (ONEI()); else /* N is composite */ return (ZEROI()); } MPI *LUCAS(MPI *N) /* Here N is odd and > 1. * If LUCAS(N) returns 1, then N is a strong base 2 pseudoprime and a Lucas * probable prime; if LUCAS(N) returns 0, then N is composite. * See "The Pseudoprimes to 25.10^9", Mathematics of computation, 35 (1980) * 1003-1026. At the end of this paper it is conjectured that if N is a strong * base 2 pseudoprime and a Lucas probable prime, then N is in fact a prime. * A $30 prize is offered for a counterexample. */ { unsigned int l; int t; MPI *L; l = MILLER(N, 2); if (l == 0) return (ZEROI()); L = LUCASB(N); t = L->S; FREEMPI(L); if (t) return (ONEI()); else return (ZEROI()); } MPI *LEASTQNR(MPI *P) /* * Returns NP, the least quadratic non-residue (mod P) if NP < R0. * Else returns 0. */ { MPI *Q, *S, *T; unsigned int flag = 0; unsigned long i; Q = INT0_(P, (USL)2); T = MPOWER_((long)2, Q, P); S = SUBI(T, P); if (EQMINUSONEI(S)) { FREEMPI(Q); FREEMPI(S); FREEMPI(T); return (CHANGE((USL)2)); } FREEMPI(S); FREEMPI(T); for (i = 3; i < R0; i = i + 2) { T = MPOWER_((long)i, Q, P); S = SUBI(T, P); if (EQMINUSONEI(S)) { FREEMPI(S); FREEMPI(T); flag = 1; break; } FREEMPI(S); FREEMPI(T); } FREEMPI(Q); if (flag) return (CHANGE(i)); else return(ZEROI()); }