blob: 24b73137a31e9ffe7a25108248528189be2c38b2 [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001/*
2 * Compute the Jacobi symbol (small prime case only).
3 *
4 * Copyright (c) 1995 Colin Plumb. All rights reserved.
5 * For licensing and other legal details, see the file legal.c.
6 */
7#include "bn.h"
8#include "jacobi.h"
9
10/*
11 * For a small (usually prime, but not necessarily) prime p,
12 * compute Jacobi(p,bn), which is -1, 0 or +1, using the following rules:
13 * Jacobi(x, y) = Jacobi(x mod y, y)
14 * Jacobi(0, y) = 0
15 * Jacobi(1, y) = 1
16 * Jacobi(2, y) = 0 if y is even, +1 if y is +/-1 mod 8, -1 if y = +/-3 mod 8
17 * Jacobi(x1*x2, y) = Jacobi(x1, y) * Jacobi(x2, y) (used with x1 = 2 & x1 = 4)
18 * If x and y are both odd, then
19 * Jacobi(x, y) = Jacobi(y, x) * (-1 if x = y = 3 mod 4, +1 otherwise)
20 */
21int
22bnJacobiQ(unsigned p, struct BigNum const *bn)
23{
24 int j = 1;
25 unsigned u = bnLSWord(bn);
26
27 if (!(u & 1))
28 return 0; /* Don't *do* that */
29
30 /* First, get rid of factors of 2 in p */
31 while ((p & 3) == 0)
32 p >>= 2;
33 if ((p & 1) == 0) {
34 p >>= 1;
35 if ((u ^ u>>1) & 2)
36 j = -j; /* 3 (011) or 5 (101) mod 8 */
37 }
38 if (p == 1)
39 return j;
40 /* Then, apply quadratic reciprocity */
41 if (p & u & 2) /* p = u = 3 (mod 4? */
42 j = -j;
43 /* And reduce u mod p */
44 u = bnModQ(bn, p);
45
46 /* Now compute Jacobi(u,p), u < p */
47 while (u) {
48 while ((u & 3) == 0)
49 u >>= 2;
50 if ((u & 1) == 0) {
51 u >>= 1;
52 if ((p ^ p>>1) & 2)
53 j = -j; /* 3 (011) or 5 (101) mod 8 */
54 }
55 if (u == 1)
56 return j;
57 /* Now both u and p are odd, so use quadratic reciprocity */
58 if (u < p) {
59 unsigned t = u; u = p; p = t;
60 if (u & p & 2) /* u = p = 3 (mod 4? */
61 j = -j;
62 }
63 /* Now u >= p, so it can be reduced */
64 u %= p;
65 }
66 return 0;
67}