Square roots modulo a prime
- Cost
- modular multiplications if . Otherwise, with and odd, multiplications for Tonelli–Shanks, or multiplications and a few Jacobi symbols for Müller's method.
Given a prime and , we want with . Half of the nonzero residues are squares. For a square, the two roots are and , and nmod_sqrt returns the one in . The choice of method depends on and on the 2-adic valuation of . Standard references are [Coh1996] and [CraPom2005].
Overview#
nmod_sqrt(res, a, mod) proceeds as follows.
- If , return . If is even, return failure.
- If (
NMOD_SQRT_SMALL_CUTOFF), search with updated incrementally (_nmod_sqrt_small). This is exact for any odd . - Otherwise choose the arithmetic: half-word lazy Montgomery arithmetic if , full-word lazy Montgomery arithmetic if , and plain Montgomery arithmetic otherwise. All remaining steps work in Montgomery form, and the three versions are compiled separately so that each is fully inlined.
Compute a candidate root :
- : Algorithm 1;
- : Algorithm 2;
- : Algorithm 5 if , where is the bit length of , and if it finds a suitable parameter; otherwise Algorithm 3 for and Algorithm 4 for .
- Return if , and failure otherwise.
No Jacobi symbol of is computed in advance. For prime , every method below returns a correct root when is a square, so the final check is a complete test of whether is a square. For composite , the check guarantees that a returned root is genuine, but a failure proves nothing.
The branches in the inner loops are replaced by masks and selections, since their conditions depend on random data and would be mispredicted. For the same reason, exponentiation multiplies by 1 instead of skipping a multiplication when an exponent bit is 0.
The case #
Input: prime and .
Output: a candidate root .
- Return .
If is a square, Euler's criterion gives , so .
The case #
Here is a square and is not. Atkin's method [Atk1992] uses a square root of built from .
Input: prime and .
Output: a candidate root .
- and .
- .
- Return .
Theorem 1. If is a nonzero square modulo the prime , then Algorithm 2 returns a square root of .
Proof. We have , so , because 2 is a nonsquare and is a square. Hence and
Tonelli–Shanks#
For write with odd, so . The method of Tonelli [Ton1891] and Shanks [Sha1973] works in the subgroup of order of , which is cyclic.
Nonresidue. It needs some that is not a square. FLINT takes the least odd prime with Jacobi symbol , and otherwise the least odd with . Only odd primes need to be tried among the small values, because the least nonresidue is prime and 2 is a square for . By quadratic reciprocity , and is read from a bitmask indexed by , computed with two multiplications instead of a division: with , the high word of satisfies , so , and since is a square, . The search gives up, which makes nmod_sqrt fail, if is found to be a perfect square or no nonresidue is found below ; neither happens for prime .
Setup. With and , both computed by one exponentiation loop that interleaves the two independent squaring chains, set
Then , and has order exactly since . If is a square, then . It remains to find with ; then is even when is a square, and is a root.
Input: as above, with and of order .
Output: a root of , or failure.
- .
While :
- Find the least with and , by repeated squaring. If there is none, return failure.
- , , , , .
- Return .
Theorem 2. If is a nonzero square modulo the prime , then Algorithm 3 terminates and returns a square root of . If is not a square, it returns failure.
Proof. The loop maintains , of order exactly , and . This holds initially. In step 2.1, and , so exists and has order exactly . Then has order , so has order . In a cyclic group, the elements of order exactly all satisfy , so . The updates give , and the invariant holds with . Since decreases strictly, the loop terminates, and on exit and . If is not a square, then , so no exists in the first round.
Each round costs up to dependent squarings, so the total is multiplications in one long dependency chain. This is cheap for small , which is the common case: asymptotically, half of the primes have . FLINT uses it for .
Bitwise variant#
For larger the latency of the dependent squarings dominates. The second form finds the bits of from the bottom, as in Pohlig–Hellman (see Discrete logarithms modulo a prime (Pohlig–Hellman)), using products that do not depend on each other.
Input: as above.
Output: a root of , or failure.
- For : and .
- If , return failure.
- For : if , set for , and .
- Return .
Theorem 3. If is a nonzero square modulo the prime , then Algorithm 4 returns a square root of . If is not a square, it returns failure.
Proof. Let with , which exists because lies in the cyclic group generated by . Let be the part of below bit . We claim that before iteration of step 3, for , and .
Since and divides , we get , so the test in step 3 reads off bit . Setting the bit multiplies by , hence each by , and by . Only with are used later. Step 2 is the case : , which is 1 if and only if is a square, and then . At the end and .
Step 1 is two independent chains of squarings, and step 3 performs at most multiplications. The work is still , but the multiplications of each iteration are independent, so their cost is bounded by multiplication throughput instead of latency.
Müller's method#
The cost of Tonelli–Shanks grows with . The Cipolla–Lehmer method works in instead, with a cost that does not depend on . Müller [Mue2004] gave a version for that needs a single Lucas sequence. For , let , and , so that where are the roots of .
Theorem 4 (Müller). Let be prime, let be a nonzero square, and let with . With ,
Proof. Let , and let be a square root of in ; it is not in . Put and . Then , and , so is a root of . The Frobenius map fixes and sends to , so and . Hence satisfies and . Now
Input: prime and .
Output: a candidate root , or no answer.
- For , let and test whether ; stop at the first success. If none succeeds, give no answer.
- .
- Compute with the ladder or over the bits of , using and .
- Return .
Choosing makes the division by in step 4 a sequence of halvings, each a shift and a conditional addition of . The Jacobi symbols in step 1 are computed for () and for (), because and 4 is a square; they satisfy and . Each candidate fails with probability about , so giving no answer after 33 candidates is very unlikely; nmod_sqrt then falls back to Tonelli–Shanks.
Each step of the ladder costs one squaring and one independent multiplication, so the latency is about that of one exponentiation. The fixed cost of the Jacobi symbols makes the method pay off only for large . FLINT uses it when , where is the bit length of . Since , this happens only for , and for 64-bit it requires .
Use in FLINT#
nmod_sqrtimplements all the methods above.n_sqrtmodis a wrapper that skipsnmod_initfor .- Other callers include
nmod_poly_sqrt(for the constant term), the square root method ofgr_ctx_init_nmodcontexts, andflint_mpn_sqrtmod_preinvfor one-word moduli. For multi-word moduli,flint_mpn_sqrtmod_preinvhas its own implementation of Müller's method.
Referenced from#
References#
- [Coh1996] Cohen, Henri : A course in computational algebraic number theory, Springer, 1996
- [CraPom2005] R. Crandall and C. Pomerance, Prime Numbers: A Computational Perspective, second edition, Springer (2005).
- [Atk1992] A. O. L. Atkin, "Probabilistic primality testing", summary by F. Morain, in Algorithms Seminar 1991–1992, INRIA Research Report 1779 (1992), 159–163
- [Ton1891] A. Tonelli, "Bemerkung über die Auflösung quadratischer Congruenzen", Nachrichten von der Königlichen Gesellschaft der Wissenschaften und der Georg-Augusts-Universität zu Göttingen (1891), 344–346
- [Sha1973] D. Shanks, "Five number-theoretic algorithms", Proceedings of the Second Manitoba Conference on Numerical Mathematics, Congressus Numerantium 7 (1973), 51–70
- [Mue2004] S. Müller, "On the computation of square roots in finite fields", Designs, Codes and Cryptography 31 (2004), 301–312, https://doi.org/10.1023/B:DESI.0000015890.44831.e2
The FLINT team, “Square roots modulo a prime,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/number-theory/sqrt-mod-p.html (generated 2026-11-02).
@misc{flint-doc-algorithms-number-theory-sqrt-mod-p,
author = {{The FLINT team}},
title = {{Square roots modulo a prime}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/number-theory/sqrt-mod-p.html},
note = {Generated 2026-11-02}
}