// jacobi(). // General includes. #include "cl_sysdep.h" // Specification. #include "cln/numtheory.h" // Implementation. #include "cln/integer.h" #include "cl_I.h" #include "cln/abort.h" #include "cl_xmacros.h" namespace cln { int jacobi (const cl_I& a, const cl_I& b) { // Check b > 0, b odd. if (!(b > 0)) cl_abort(); if (!oddp(b)) cl_abort(); { Mutable(cl_I,a); Mutable(cl_I,b); // Ensure 0 <= a < b. a = mod(a,b); // If a and b are fixnums, choose faster routine. if (fixnump(b)) return jacobi(FN_to_L(a),FN_to_L(b)); var int v = 1; for (;;) { // (a/b) * v is invariant. if (b == 1) // b=1 implies (a/b) = 1. return v; if (a == 0) // b>1 and a=0 imply (a/b) = 0. return 0; if (a > (b >> 1)) { // a > b/2, so (a/b) = (-1/b) * ((b-a)/b), // and (-1/b) = -1 if b==3 mod 4. a = b-a; if (FN_to_L(logand(b,3)) == 3) v = -v; continue; } if ((a & 1) == 0) { // b>1 and a=2a', so (a/b) = (2/b) * (a'/b), // and (2/b) = -1 if b==3,5 mod 8. a = a>>1; switch (FN_to_L(logand(b,7))) { case 3: case 5: v = -v; break; } continue; } // a and b odd, 0 < a < b/2 < b, so apply quadratic reciprocity // law (a/b) = (-1)^((a-1)/2)((b-1)/2) * (b/a). if (FN_to_L(logand(logand(a,b),3)) == 3) v = -v; swap(cl_I, a,b); // Now a > 2*b, set a := a mod b. if ((a >> 3) >= b) a = mod(a,b); else { a = a-b; do { a = a-b; } while (a >= b); } } }} } // namespace cln