2
0

jacobi.c 1.6 KB

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