You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
1.4 KiB

25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
  1. // jacobi().
  2. // General includes.
  3. #include "cl_sysdep.h"
  4. // Specification.
  5. #include "cln/numtheory.h"
  6. // Implementation.
  7. #include "cln/integer.h"
  8. #include "cl_I.h"
  9. #include "cln/abort.h"
  10. #include "cl_xmacros.h"
  11. namespace cln {
  12. int jacobi (const cl_I& a, const cl_I& b)
  13. {
  14. // Check b > 0, b odd.
  15. if (!(b > 0))
  16. cl_abort();
  17. if (!oddp(b))
  18. cl_abort();
  19. { Mutable(cl_I,a);
  20. Mutable(cl_I,b);
  21. // Ensure 0 <= a < b.
  22. a = mod(a,b);
  23. // If a and b are fixnums, choose faster routine.
  24. if (fixnump(b))
  25. return jacobi(FN_to_V(a),FN_to_V(b));
  26. var int v = 1;
  27. for (;;) {
  28. // (a/b) * v is invariant.
  29. if (b == 1)
  30. // b=1 implies (a/b) = 1.
  31. return v;
  32. if (a == 0)
  33. // b>1 and a=0 imply (a/b) = 0.
  34. return 0;
  35. if (a > (b >> 1)) {
  36. // a > b/2, so (a/b) = (-1/b) * ((b-a)/b),
  37. // and (-1/b) = -1 if b==3 mod 4.
  38. a = b-a;
  39. if (FN_to_V(logand(b,3)) == 3)
  40. v = -v;
  41. continue;
  42. }
  43. if ((a & 1) == 0) {
  44. // b>1 and a=2a', so (a/b) = (2/b) * (a'/b),
  45. // and (2/b) = -1 if b==3,5 mod 8.
  46. a = a>>1;
  47. switch (FN_to_V(logand(b,7))) {
  48. case 3: case 5: v = -v; break;
  49. }
  50. continue;
  51. }
  52. // a and b odd, 0 < a < b/2 < b, so apply quadratic reciprocity
  53. // law (a/b) = (-1)^((a-1)/2)((b-1)/2) * (b/a).
  54. if (FN_to_V(logand(logand(a,b),3)) == 3)
  55. v = -v;
  56. swap(cl_I, a,b);
  57. // Now a > 2*b, set a := a mod b.
  58. if ((a >> 3) >= b)
  59. a = mod(a,b);
  60. else
  61. { a = a-b; do { a = a-b; } while (a >= b); }
  62. }
  63. }}
  64. } // namespace cln