Discrete logarithms modulo a prime (Pohlig–Hellman)
- Cost
- For , one call costs multiplications modulo , where is about for up to about and between and for larger .
Let be prime and let be a primitive root modulo , so that every is for a unique , the discrete logarithm of . For a general no fast algorithm is known. When the group order factors into small primes, the method of Pohlig and Hellman [PohHel1978] reduces the problem to logarithms in groups of prime order, which are solved by Shanks' baby-step giant-step method [Sha1971]. See also [CraPom2005].
FLINT implements this method in the nmod_discrete_log_pohlig_hellman functions.
Reduction to prime-power order#
Write with distinct primes , and let . The element has order exactly , and . So is the logarithm of to the base , a problem in a group of order . The determine by the Chinese remainder theorem:
where the idempotent satisfies and for .
Digits in a prime-power group#
Fix and write , , and with . The element has order .
Input: with , the elements and .
Output: .
- , .
For :
- .
- Find with .
- , , .
- Return .
Theorem 1. In Algorithm 1, step 2.2 always has a solution, it is the digit of , and the algorithm returns .
Proof. We show that at the start of iteration , and with . This holds for . Since divides , write . Then
because has order . As has order , the solution of step 2.2 is unique in and equals . Step 2.3 multiplies by , giving , and replaces by .
Logarithms of prime order#
Step 2.2 is a discrete logarithm in the group of order generated by . FLINT uses a baby-step giant-step search with a precomputed table of bounded size.
For no search is needed: , and if , if .
For odd , choose a stride and let . The table holds the pairs for , sorted by the first entry. Any can be written with and , so if and only if .
Input: in the group generated by , the sorted table, and .
Output: with .
For :
- If for some table entry (found by binary search), return .
- .
- Fail.
The search returns the correct digit. Let be the true logarithm of the input . For , the current value is with . Since for every table entry, it matches an entry exactly when . The first such is , with .
The table costs entries and the search at most multiplications and binary searches. Balancing the two gives . FLINT starts from and doubles until . So the table has at most 100 entries, and the search costs multiplications for up to about , but between and for larger . This keeps the precomputation small and favours primes for which is smooth, which is how the functions are used in FLINT.
Precomputation#
nmod_discrete_log_pohlig_hellman_precompute_prime performs the parts that depend only on :
- Factor with
n_factor. - For each , compute , and .
- Take as the least with for all , that is, the least primitive root. If is prime, one exists. If none is found below , an exception is thrown.
- For each , compute , , , the stride and the sorted table.
It returns an estimate of the number of multiplications of one run: for each , the cost of the exponentiation , plus for each of the digits the cost of the exponentiation in step 2.1 of Algorithm 1, for the search and for the power of .
The full algorithm#
Input: the precomputed data for , and .
Output: with .
- For each : compute and by Algorithm 1, using Algorithm 2 for each digit.
- Return .
The sum in step 2 is accumulated in three words and reduced once at the end. If a search in Algorithm 2 fails, or when , an exception is thrown. For an odd prime this happens only for , which has no logarithm.
Theorem 2. For prime and , Algorithm 3 returns the discrete logarithm of to the base .
Proof. By Theorem 1, step 1 computes , where the search of Algorithm 2 succeeds because lies in the group generated by . By the properties of the idempotents, for every , so it is congruent to modulo .
Cost. Each digit needs an exponentiation by , a search and an exponentiation of , so the total is multiplications, plus one exponentiation for each . When all are small, this is .
Use in FLINT#
- The sparse interpolation in the multivariate gcd code of
fmpz_mpoly_factorevaluates at powers of a primitive root and recovers exponents withnmod_discrete_log_pohlig_hellman_run. It chooses primes withfmpz_next_smooth_prime, for which currently has no prime factor above 23, so the searches are short. fmpz_mod_discrete_log_pohlig_hellman_runinfmpz_modis the same method for multiprecision primes.n_discrete_log_bsgsinulong_extrasis a plain baby-step giant-step search, without the reduction to prime order.- The
dlogmodule, used for Dirichlet characters, precomputes tables for many logarithms to the same base modulo a prime power (Discrete logarithm tables).
Referenced from#
- Discrete logarithm tables (algorithm)
- Square roots modulo a prime (algorithm)
- dlog.h (module)
- Discrete logarithms modulo a multiprecision prime
- fmpz_mod.h (module)
- Computing discrete logarithms
- nmod.h (module)
References#
- [PohHel1978] S. C. Pohlig and M. E. Hellman, "An improved algorithm for computing logarithms over GF(p) and its cryptographic significance", IEEE Transactions on Information Theory 24 (1978), 106–110, https://doi.org/10.1109/TIT.1978.1055817
- [Sha1971] D. Shanks, "Class number, a theory of factorization, and genera", Proc. Symp. Pure Math. 20, American Mathematical Society (1971), 415–440
- [CraPom2005] R. Crandall and C. Pomerance, Prime Numbers: A Computational Perspective, second edition, Springer (2005).
The FLINT team, “Discrete logarithms modulo a prime (Pohlig–Hellman),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/number-theory/discrete-log.html (generated 2026-11-02).
@misc{flint-doc-algorithms-number-theory-discrete-log,
author = {{The FLINT team}},
title = {{Discrete logarithms modulo a prime (Pohlig–Hellman)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/algorithms/number-theory/discrete-log.html},
note = {Generated 2026-11-02}
}