Annotation of OpenXM/src/kan96xx/gmp-2.0.2/mpz/legendre.c, Revision 1.1.1.1
1.1 maekawa 1: /* mpz_legendre (op1, op2).
2: Contributed by Bennet Yee (bsy) at Carnegie-Mellon University
3:
4: Copyright (C) 1992, 1996 Free Software Foundation, Inc.
5:
6: This file is part of the GNU MP Library.
7:
8: The GNU MP Library is free software; you can redistribute it and/or modify
9: it under the terms of the GNU Library General Public License as published by
10: the Free Software Foundation; either version 2 of the License, or (at your
11: option) any later version.
12:
13: The GNU MP Library is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
16: License for more details.
17:
18: You should have received a copy of the GNU Library General Public License
19: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21: MA 02111-1307, USA. */
22:
23: #include "gmp.h"
24:
25: #if defined (DEBUG)
26: #include <stdio.h>
27: #endif
28:
29: /* Precondition: both p and q are positive */
30:
31: int
32: #if __STDC__
33: mpz_legendre (mpz_srcptr pi, mpz_srcptr qi)
34: #else
35: mpz_legendre (pi, qi)
36: mpz_srcptr pi, qi;
37: #endif
38: {
39: mpz_t p, q, qdiv2;
40: #ifdef Q_MINUS_1
41: mpz_t q_minus_1;
42: #endif
43: mpz_ptr mtmp;
44: register mpz_ptr pptr, qptr;
45: register int retval = 1;
46: register unsigned long int s;
47:
48: pptr = p;
49: mpz_init_set (pptr, pi);
50: qptr = q;
51: mpz_init_set (qptr, qi);
52:
53: #ifdef Q_MINUS_1
54: mpz_init (q_minus_1);
55: #endif
56: mpz_init (qdiv2);
57:
58: tail_recurse2:
59: #ifdef DEBUG
60: printf ("tail_recurse2: p=");
61: mpz_out_str (stdout, 10, pptr);
62: printf ("\nq=");
63: mpz_out_str (stdout, 10, qptr);
64: putchar ('\n');
65: #endif
66: s = mpz_scan1 (qptr, 0);
67: if (s) mpz_tdiv_q_2exp (qptr, qptr, s); /* J(a,2) = 1 */
68: #ifdef DEBUG
69: printf ("2 factor decomposition: p=");
70: mpz_out_str (stdout, 10, pptr);
71: printf ("\nq=");
72: mpz_out_str (stdout, 10, qptr);
73: putchar ('\n');
74: #endif
75: /* postcondition q odd */
76: if (!mpz_cmp_ui (qptr, 1L)) /* J(a,1) = 1 */
77: goto done;
78: mpz_mod (pptr, pptr, qptr); /* J(a,q) = J(b,q) when a == b mod q */
79: #ifdef DEBUG
80: printf ("mod out by q: p=");
81: mpz_out_str (stdout, 10, pptr);
82: printf ("\nq=");
83: mpz_out_str (stdout, 10, qptr);
84: putchar ('\n');
85: #endif
86: /* quick calculation to get approximate size first */
87: /* precondition: p < q */
88: if ((mpz_sizeinbase (pptr, 2) + 1 >= mpz_sizeinbase (qptr,2))
89: && (mpz_tdiv_q_2exp (qdiv2, qptr, 1L), mpz_cmp (pptr, qdiv2) > 0))
90: {
91: /* p > q/2 */
92: mpz_sub (pptr, qptr, pptr);
93: /* J(-1,q) = (-1)^((q-1)/2), q odd */
94: if (mpz_get_ui (qptr) & 2)
95: retval = -retval;
96: }
97: /* p < q/2 */
98: #ifdef Q_MINUS_1
99: mpz_sub_ui (q_minus_q, qptr, 1L);
100: #endif
101: tail_recurse: /* we use tail_recurse only if q has not changed */
102: #ifdef DEBUG
103: printf ("tail_recurse1: p=");
104: mpz_out_str (stdout, 10, pptr);
105: printf ("\nq=");
106: mpz_out_str (stdout, 10, qptr);
107: putchar ('\n');
108: #endif
109: /*
110: * J(0,q) = 0
111: * this occurs only if gcd(p,q) != 1 which is never true for
112: * Legendre function.
113: */
114: if (!mpz_cmp_ui (pptr, 0L))
115: {
116: retval = 0;
117: goto done;
118: }
119:
120: if (!mpz_cmp_ui (pptr, 1L))
121: {
122: /* J(1,q) = 1 */
123: /* retval *= 1; */
124: goto done;
125: }
126: #ifdef Q_MINUS_1
127: if (!mpz_cmp (pptr, q_minus_1))
128: {
129: /* J(-1,q) = (-1)^((q-1)/2) */
130: if (mpz_get_ui (qptr) & 2)
131: retval = -retval;
132: /* else retval *= 1; */
133: goto done;
134: }
135: #endif
136: /*
137: * we do not handle J(xy,q) except for x==2
138: * since we do not want to factor
139: */
140: if ((s = mpz_scan1 (pptr, 0)) != 0)
141: {
142: /*
143: * J(2,q) = (-1)^((q^2-1)/8)
144: *
145: * Note that q odd guarantees that q^2-1 is divisible by 8:
146: * Let a: q=2a+1. q^2 = 4a^2+4a+1, (q^2-1)/8 = a(a+1)/2, qed
147: *
148: * Now, note that this means that the low two bits of _a_
149: * (or the low bits of q shifted over by 1 determines
150: * the factor).
151: */
152: mpz_tdiv_q_2exp (pptr, pptr, s);
153:
154: /* even powers of 2 gives J(2,q)^{2n} = 1 */
155: if (s & 1)
156: {
157: s = mpz_get_ui (qptr) >> 1;
158: s = s * (s + 1);
159: if (s & 2)
160: retval = -retval;
161: }
162: goto tail_recurse;
163: }
164: /*
165: * we know p is odd since we have cast out 2s
166: * precondition that q is odd guarantees both odd.
167: *
168: * quadratic reciprocity
169: * J(p,q) = (-1)^((p-1)(q-1)/4) * J(q,p)
170: */
171: if ((s = mpz_scan1 (pptr, 1)) <= 2 && (s + mpz_scan1 (qptr, 1)) <= 2)
172: retval = -retval;
173:
174: mtmp = pptr; pptr = qptr; qptr = mtmp;
175: goto tail_recurse2;
176: done:
177: mpz_clear (p);
178: mpz_clear (q);
179: mpz_clear (qdiv2);
180: #ifdef Q_MINUS_1
181: mpz_clear (q_minus_1);
182: #endif
183: return retval;
184: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>