jacobi.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <cassert> | ||
| 4 | #include <utility> | ||
| 5 | |||
| 6 | // Computes (n on m) == 1 using the binary-gcd method | ||
| 7 | // m must be positive and odd, and n must be relatively prime | ||
| 8 | ✗ | template <typename T> bool is_qr_jacobi(T n, T m) { | |
| 9 | ✗ | bool r = true; | |
| 10 | ✗ | assert(m & 1); | |
| 11 | ✗ | assert(m > 0); | |
| 12 | ✗ | if (n < 0) { | |
| 13 | ✗ | if (m & 2) r = !r; | |
| 14 | ✗ | n = -n; | |
| 15 | } | ||
| 16 | ✗ | while (m > 1) { | |
| 17 | ✗ | assert(n > 0); | |
| 18 | ✗ | int t = __builtin_ctzll(n); | |
| 19 | ✗ | n >>= t; | |
| 20 | ✗ | if ((t & 1) && (((m & 7) == 3) || ((m & 7) == 5))) { | |
| 21 | ✗ | r = !r; | |
| 22 | } | ||
| 23 | // n and m both odd | ||
| 24 | ✗ | if (n < m) { | |
| 25 | ✗ | if ((n & 2) && (m & 2)) { | |
| 26 | ✗ | r = !r; | |
| 27 | } | ||
| 28 | using std::swap; | ||
| 29 | ✗ | swap(n, m); | |
| 30 | } | ||
| 31 | ✗ | n -= m; | |
| 32 | } | ||
| 33 | ✗ | return r; | |
| 34 | } | ||
| 35 |