is a quadratic residue modulo an odd prime if is solvable. Euler’s criterion: ( residue, non-residue, if ); exactly nonzero residues exist. Roots come from Tonelli–Shanks or Cipolla, lift to by Hensel, combine over composite moduli by CRT. Related Diophantine equations: (Cornacchia), sums of two squares.

TaskMethodCost
is a residue mod prime Euler’s criterion / Jacobi symbol
Jacobi for odd reciprocity, like Euclid
Tonelli–Shanks () or Cipolla ()—
Hensel lifting
roots mod each prime power + CRT ( combinations)—
Cornacchia (Euclid on )
, count factor; factoring
int jacobi(ll a, ll n) {                                   // n odd > 0; Legendre symbol when n is prime
    a %= n; if (a < 0) a += n; int t = 1;
    while (a) {
        while (a % 2 == 0) { a /= 2; if (n % 8 == 3 || n % 8 == 5) t = -t; }
        swap(a, n); if (a % 4 == 3 && n % 4 == 3) t = -t;
        a %= n;
    }
    return n == 1 ? t : 0;
}
ll sqrtMod(ll a, ll p) {                                   // Tonelli-Shanks: some x with x^2 = a (mod p), -1 if none; p prime
    a %= p; if (a < 0) a += p;
    if (a == 0 || p == 2) return a;
    if (power(a, (p - 1) / 2, p) != 1) return -1;
    if (p % 4 == 3) return power(a, (p + 1) / 4, p);
    ll q = p - 1; int s = 0; while (q % 2 == 0) q /= 2, s++;
    ll z = 2; while (power(z, (p - 1) / 2, p) != p - 1) z++;
    ll c = power(z, q, p), x = power(a, (q + 1) / 2, p), t = power(a, q, p); int m = s;
    while (t != 1) {
        int i = 0; ll tt = t; while (tt != 1) tt = (i128)tt * tt % p, i++;
        ll b = c; for (int j = 0; j < m - i - 1; j++) b = (i128)b * b % p;
        x = (i128)x * b % p; c = (i128)b * b % p; t = (i128)t * c % p; m = i;
    }
    return x;
}
ll cipolla(ll a, ll p) {                                   // same contract, O(log p) multiplications in F_{p^2}
    a %= p; if (a < 0) a += p;
    if (a == 0 || p == 2) return a;
    if (power(a, (p - 1) / 2, p) != 1) return -1;
    ll r = 0, w = 0; mt19937_64 rng(7);
    do { r = rng() % p; w = ((i128)r * r - a + p) % p; } while (power(w, (p - 1) / 2, p) != p - 1);
    auto mul = [&](pair<ll, ll> x, pair<ll, ll> y) { return pair<ll, ll>{(ll)(((i128)x.first * y.first + (i128)x.second * y.second % p * w) % p), (ll)(((i128)x.first * y.second + (i128)x.second * y.first) % p)}; };
    pair<ll, ll> res{1, 0}, b{r, 1};
    for (ll e = (p + 1) / 2; e; e >>= 1, b = mul(b, b)) if (e & 1) res = mul(res, b);
    return res.first;                                      // (r + sqrt(w))^{(p+1)/2} lies in F_p
}
ll sqrtModPrimePower(ll a, ll p, int k) {                  // odd p, gcd(a, p) = 1: x^2 = a (mod p^k), -1 if none
    ll x = sqrtMod(a % p, p); if (x < 0) return -1;
    ll pk = p;
    for (int i = 1; i < k; i++) {                          // x <- x - (x^2 - a) / (2x) mod p^{i+1}
        pk *= p; ll am = ((a % pk) + pk) % pk;
        ll f = ((i128)x * x - am) % pk; if (f < 0) f += pk;
        x = (x - (i128)f * invMod(2 * x % pk, pk)) % pk; if (x < 0) x += pk;
    }
    return x;
}
pair<ll, ll> cornacchia(ll d, ll p) {                      // x^2 + d y^2 = p, p prime, 0 < d < p; {-1, -1} if none
    ll r = sqrtMod(p - d % p, p); if (r < 0) return {-1, -1};
    if (2 * r < p) r = p - r;                              // take the root > p / 2
    ll a = p, b = r, lim = (ll)sqrtl(p); while (lim * lim > p) lim--;
    while (b > lim) { ll t = a % b; a = b; b = t; }
    ll rest = p - b * b; if (rest % d) return {-1, -1};
    ll y = (ll)sqrtl(rest / d); while (y * y > rest / d) y--; while ((y + 1) * (y + 1) <= rest / d) y++;
    if (y * y * d != rest) return {-1, -1};
    return {b, y};
}

Sums of two squares in full (all representations of , and ), from the library:

pair<i64, i64> primeTwoSquares(i64 p) {
    if (p == 2) return {1, 1};
    auto mulmod = [&](i64 a, i64 b) { return (i64)((i128)a * b % p); };
    auto pw = [&](i64 b, i64 e) {
        i64 r = 1;
        for (b %= p; e; e >>= 1, b = mulmod(b, b)) {
            if (e & 1) r = mulmod(r, b);
        }
        return r;
    };
    i64 x = 0;
    for (i64 c = 2;; c++) {
        if (pw(c, (p - 1) / 2) == p - 1) {
            x = pw(c, (p - 1) / 4);
            break;
        }
    }
    i64 a = p, b = x;
    i64 lim = sqrtl((long double)p);
    while (b > lim) {
        i64 t = a % b;
        a = b, b = t;
    }
    i64 c = (i64)sqrtl((long double)(p - b * b));
    while (c * c > p - b * b) c--;
    while ((c + 1) * (c + 1) <= p - b * b) c++;
    return {b, c};
}
 
vector<pair<i64, i64>> twoSquares(i64 n) {
    vector<pair<i64, i64>> res;
    if (n < 0) return res;
    for (i64 x = 0; x * x <= n; x++) {
        i64 rest = n - x * x;
        i64 y = sqrtl((long double)rest);
        while (y * y > rest) y--;
        while ((y + 1) * (y + 1) <= rest) y++;
        if (y * y == rest) res.push_back({x, y});
    }
    return res;
}
 
i64 r2(i64 n) {
    if (n == 0) return 1;
    i64 d1 = 0, d3 = 0;
    auto count = [&](i64 e) {
        if (e % 4 == 1) d1++;
        else if (e % 4 == 3) d3++;
    };
    for (i64 d = 1; d * d <= n; d++) {
        if (n % d) continue;
        count(d);
        if (d != n / d) count(n / d);
    }
    return 4 * (d1 - d3);
}
FactStatement
Euler’s criterion
, as residues is a QR iff ; iff
quadratic reciprocity
number of roots of (odd )0 or 2; modulo : product over prime powers ( has up to 4)
sum of two squares is one iff every prime has even exponent;
Fermatprime iff or