FLINT3.7.0-dev
Algorithm

Discrete logarithm tables

Cost
After a precomputation of O(\sqrt{kn}), each of k logarithms in a group of prime order n costs O(\sqrt{n/k}) multiplications; for composite order the cost is the sum over the prime factors.

The dlog module computes discrete logarithms in a cyclic group \langle a \rangle \subseteq (\mathbb{Z}/m\mathbb{Z})^\times of order n, for word-size m. Its use case, Dirichlet characters (Dirichlet characters), asks for many logarithms to the same base, typically with m a prime power and a a primitive root. The module therefore separates a precomputation, sized for an expected number k of queries, from the queries themselves. For the general theory see [CraPom2005, §5.2–5.3]; the single-logarithm algorithm of nmod is described in Discrete logarithms modulo a prime (Pohlig–Hellman).

Baby-step giant-step with a balanced table#

Shanks' method [Sha1971] stores the baby steps (j, a^j) for 0 \le j < M, sorted by value, and for a query b computes the giant steps b a^{-iM}, i = 0, 1, \ldots, until one of them is found in the table as a^j; then \log_a b = iM + j.

Proposition 1. A query needs at most \lfloor n/M \rfloor + 1 giant steps, each one multiplication and one binary search. For k queries the total cost, M to build the table plus k n / M for the queries, is minimised by M \approx \sqrt{kn}, giving O(\sqrt{kn}) multiplications in total, or O(\sqrt{n/k}) per query after the precomputation.

Proof. Write x = \log_a b = iM + j with 0 \le j < M; then i \le (n-1)/M and b a^{-iM} = a^j is in the table. The optimum of M + kn/M is at M = \sqrt{kn}.

dlog_bsgs_size(n, k) returns (1 + \lfloor\sqrt n\rfloor)(1 + \lfloor\sqrt k\rfloor) when 2k < n, and n (a complete table, so that every query is one search) otherwise. For groups of order at most 3 no table is needed, and for moduli below 50 a table indexed by the residue replaces the sorted array.

Pohlig–Hellman decomposition#

If n = \prod_i p_i^{e_i}, the logarithm modulo p_i^{e_i} of b is the logarithm of b^{n/p_i^{e_i}} to the base a^{n/p_i^{e_i}}, of order p_i^{e_i}, and the Chinese remainder theorem combines them [PohHel1978]. Within a group of order p^e, write x = \sum_{t < e} x_t p^t; then

\bigl(b\, a^{-(x_0 + \cdots + x_{t-1} p^{t-1})}\bigr)^{p^{e-1-t}} = \bigl(a^{p^{e-1}}\bigr)^{x_t},

so each digit x_t is a logarithm in the subgroup of order p, generated by a^{p^{e-1}}. A logarithm in a group of order n thus costs O(\sum_i e_i (\log n + c(p_i))) multiplications, where c(p) is the cost of a logarithm in a group of order p; the structure is the same as for nmod_discrete_log_pohlig_hellman. In FLINT, dlog_crt_t holds one precomputation per prime power, and dlog_power_t one precomputation of the subgroup of order p, built for e k queries.

Prime power moduli and p-adic logarithms#

For m = p^e with p odd and a a primitive root modulo p^2, the group (\mathbb{Z}/p^e\mathbb{Z})^\times has order (p-1)p^{e-1}, and its p-Sylow part is the subgroup U_1 = \{x \equiv 1 \pmod p\}, cyclic of order p^{e-1} and generated by 1 + p. Logarithms there are cheap:

Lemma 2. For odd p and f \ge 1, (1 + p)^{p^{f-1}} \equiv 1 + p^f \pmod {p^{f+1}}. Consequently, if b \equiv 1 + c\, p^f \pmod{p^{f+1}} with 0 \le c < p, then b (1 + p)^{-c p^{f-1}} \equiv 1 \pmod{p^{f+1}}.

Proof. By induction on f with the binomial theorem: if x = 1 + p^f + y p^{f+1}, then x^p \equiv 1 + p^{f+1} \pmod{p^{f+2}}, the other terms being divisible by p^{2f+1} or, for the term \binom{p}{2} p^{2f}, by p^{2f+1} since p is odd.

So \log_{1+p} b is found one base-p digit at a time (dlog_1modpe_1modp), with e - 1 modular powers. The logarithm to the base a is then obtained from two smaller problems.

Proposition 3. Let L = \log_a b modulo (p-1)p^{e-1}, x = \log_{a \bmod p}(b \bmod p) modulo p - 1, and y = \log_{a^{p-1}} (b^{p-1}) modulo p^{e-1}. Then L \equiv x \pmod {p-1}, L \equiv y \pmod {p^{e-1}}, and

L = y + p^{e-1} \bigl((x - y) \bmod (p - 1)\bigr).

Proof. The first congruence is reduction modulo p, the second follows from b^{p-1} = (a^{p-1})^L with a^{p-1} of order p^{e-1}. Since p^{e-1} \equiv 1 \pmod{p-1}, the right-hand side is congruent to x modulo p - 1 and to y modulo p^{e-1}, and it lies in [0, (p-1)p^{e-1}).

The logarithm y is \log_{1+p}(b^{p-1}) divided by \log_{1+p}(a^{p-1}) modulo p^{e-1}, which is precomputed (dlog_1modpe_init). For m = 2^e the subgroup of elements \equiv 1 \pmod 4 is generated by 5, and \log_5 is found one bit at a time in the same way (dlog_mod2e_1mod4). The cost of a logarithm modulo p^e is therefore a logarithm modulo p, in a group of order p - 1, plus O(e) modular powers.

Choosing the method#

dlog_precomp_modpe_init, dlog_precomp_n_init, dlog_precomp_pe_init and dlog_precomp_p_init choose the method from what is known about the group, recursively:

SituationMethod
modulus p^e < 50complete table
modulus p^e, e \ge 2logarithm modulo p and p-adic logarithm
order n \le 3direct comparison
order n an odd prime < 50, or other n < 50complete table (residue-indexed if the modulus is < 50, else sorted)
order n an odd prime \ge 50baby-step giant-step with dlog_bsgs_size(n, k) baby steps
order n composite, 50 \le n < 500baby-step giant-step
order n \ge 500 compositePohlig–Hellman over the prime powers
order p^e, e \ge 2, p^e \ge 50digits in the subgroup of order p

Each method returns an estimate of the cost of one logarithm in multiplications (cost), which the sieve below uses to decide whether to look for relations.

Pollard's rho method [Pol1978], which needs O(\sqrt n) time and no memory, is available as dlog_rho but is not used by these precomputations.

The logarithms of all small integers#

To evaluate a Dirichlet character at 0, 1, \ldots, N - 1, one needs \log_a k for all k < N. Two methods are used.

Enumeration (dlog_vec_loop). Running through a^0, a^1, \ldots, a^{n-1} and recording the exponent of every power below N costs n multiplications. It is the method of choice when N is comparable with n (FLINT uses it when 6n < N).

Sieving (dlog_vec_sieve). Logarithms are additive, \log_a(jk) = \log_a j + \log_a k, so it suffices to compute \log_a p for the primes p < N and to fill in the other entries in increasing order, v[pk] = v[k] + v[p]. A prime p costs one precomputed logarithm. For larger primes, a relation with smaller numbers may be cheaper: with c = a^X for a fixed X, compute for i = 1, 2, \ldots a partial extended Euclidean algorithm on (m, p c^i \bmod m), stopped when the remainder r and the cofactor u are both about \sqrt m, so that

u \cdot p\, c^i \equiv \pm r \pmod m.

If r and u factor into primes below p, whose logarithms are already known, then \log_a p = \log_a r - \log_a u - iX \pm \log_a(-1). The probability that two numbers of size \sqrt m are p-smooth is about \rho(s)^2 with s = \log \sqrt m / \log p, which FLINT estimates crudely by s^{-s} with s = \log m/\log p; it searches for relations only when this predicts fewer multiplications than a precomputed logarithm. This is a small instance of the index calculus method [CraPom2005, §6.4], without the linear algebra.

Use in FLINT#

Referenced from#

References#

  • [CraPom2005] R. Crandall and C. Pomerance, Prime Numbers: A Computational Perspective, second edition, Springer (2005).
  • [Sha1971] D. Shanks, "Class number, a theory of factorization, and genera", Proc. Symp. Pure Math. 20, American Mathematical Society (1971), 415–440
  • [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
  • [Pol1978] J. M. Pollard, "Monte Carlo methods for index computation (mod p)", Mathematics of Computation 32 (1978), 918–924. https://doi.org/10.1090/S0025-5718-1978-0491431-9
Cite this page

The FLINT team, “Discrete logarithm tables,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/number-theory/discrete-log-tables.html (generated 2026-10-20).