Suppose you have an odd prime *p* and an integer *a*, with *a* not a multiple of *p*. Does *a* have a square root mod *p*? That is, does there exist an integer *x* such that *x*² is congruent to *a* mod *p*? Half the time the answer is yes, and half the time it’s no. (We will remove the restriction that *p* is prime near the end of the post.)

In principle it’s easy to tell whether *a* has a square root: square all the integers from 1 to *p*-1 and see whether one of them is congruent to *a*. For example, let *p* = 7. Square the numbers 1 through 6 and take the remainders by 7. You get 1, 4, 2, 2, 4, 1. So the numbers 1, 2, and 4 have square roots mod 7, and the numbers 3, 5, and 6 do not. In application, *p* might be very large, and so such brute force isn’t practical.

## Legendre symbols

Before we go any further it will help to introduce some notation. The **Legendre symbol**

looks like a fraction, but it’s not. As we’ll see, it behaves something like a fraction, which was the motivation for the notation. But the symbol is defined to be 0 if *a* is a multiple of *p*, 1 if *a* has a square root mod *p*, and -1 otherwise.

One key fact is for any numbers *m* and *n* that are not multiples of *p*,

So Legendre symbols multiply like fractions on top but not on bottom. This tells us that we can tell whether *a* has a square root mod *p* by factoring *a* and determining whether each of its factors has a square root. For example, suppose we want to know whether 108 has a square root modulo some prime *p*. Since 108 = 2² 3³ the question boils down to whether 3 has a square root mod *p*, because obviously 2² 3² has a square root, namely 2×3 = 6.

## Quadratic reciprocity

The most important result we need is Gauss’ quadratic reciprocity theorem, what he called his **golden theorem**. Gauss published six proofs of this theorem, and left two more proofs unpublished.

One thing you can do with a fraction is take its reciprocal, and the quadratic reciprocity theorem takes the “reciprocal” of the Legendre symbol. The quadratic reciprocity theorem says that if *p* and *q* are odd primes, then

## Algorithm for computing Legendre symbols

Suppose *p* < *q*. The quadratic reciprocity theorem says we can reduce the problem of determining whether *p* has a square root mod *q* to the opposite problem, determining whether *q* has a square root mod *p*. Why is that progress? Because we can reduce *q* mod *p*, and so now we’re dealing with smaller numbers. For example, quadratic reciprocity tells us that 7 has a square root mod 61 if and only if 61 has a square root mod 7. But 61 is congruent to 5 mod 7, so we’ve reduced the question to whether 5 has a square root mod 7, and we know from above that it does not.

You can repeatedly apply the techniques of factoring the top of the Legendre symbol and applying quadratic reciprocity to steadily decrease the size of the numbers you’re dealing with until you get either a 1 or a 2 on top. (Why not apply quadratic reciprocity one more time when you get a 2 on top? Because the theorem applies to *odd* primes.)

If you get a 1 on top, the answer is obvious: 1 has a square root, namely itself, modulo anything. If you get a 2 on top, you need the result

## Jacobi symbols

You might think you could compute the Legendre symbol in Mathematica with a function called `LegendreSymbol`

, but there’s no such function. Instead, you call `JacobiSymbol`

. The **Jacobi symbol** is a generalization of the Legendre symbol, using the same notation but allowing the “denominator” to be any odd positive number. As before the symbol is defined to be 1 if the top has a square root modulo the bottom, and -1 otherwise.

If *m* has prime factors *p*_{i} with exponents *e*_{i}, then the Jacobi symbol can be computed by

Technically the symbol on the left is a Jacobi symbol and the symbols on the right are Legendre symbols. But the distinction doesn’t matter because when *m* is an odd prime, the Jacobi symbol equals the Legendre symbol.

In Python, you can compute Legendre symbols with `sympy.ntheory.legendre_symbol`

and Jacobi symbols with `sympy.ntheory.jacobi_symbol`

.

## Finding square roots

So far we’ve described how to determine whether a number has a square root mod *m* where *m* is odd. Once you know a square root exists, how do you find it?

These notes show how to solve quadratic congruences, whether *m* is odd or not.

I was thinking about these topics recently and was looking at the Wikipedia page for Tonelli’s algorithm. Usually I find Wikipedia good for math, but I found this article rambling and incomprehensible. There was a reference to Dickson’s classic tome, so I looked there. Dickson presents the algorithm in a dozen lines of text and it’s clear as a bell! He also presents extensions by Tonelli. There is an explicit formula for the square root mod p^k given the root mod p. There is an adaptation of the algorithm that computes the square root mod p^k directly. As I recall, there is even an algorithm that yields, given p, an algebraic expression in m that gives the square root of m mod p! Tonelli was ahead of his time.