FLINT3.7.0-dev
Algorithm

Zech logarithms

Cost
O(1)O(1) word operations for every field operation; O(q)O(q) field operations and 2q+p2q + p words of memory to build the tables.

The multiplicative group Fq×\mathbb{F}_q^\times of a finite field is cyclic of order q−1q - 1. If gg is a generator, every nonzero element is a=gka = g^k for a unique k∈[0,q−2]k \in [0, q - 2], its discrete logarithm, and multiplication, division and powering of elements become addition, subtraction and multiplication of logarithms modulo q−1q - 1. Addition needs a table: Jacobi introduced, and Zech tabulated, the function ZZ with

1+gk=gZ(k),1 + g^k = g^{Z(k)},

now called the Zech (or Jacobi) logarithm [LN1997] [Hub1990]. The representation is attractive whenever a table of size qq is affordable; fq_default uses it for q<216q < 2^{16}, and the module fq_zech allows q<2FLINT_BITSq < 2^{\mathtt{FLINT\_BITS}}.

Arithmetic with logarithms#

In fq_zech an element is stored as one word: its logarithm kk, or q−1q - 1 for zero (playing the role of log⁡0=∞\log 0 = \infty). Then, with all logarithms taken modulo q−1q - 1 and the special value for zero handled separately,

  • gkgl=gk+lg^k g^l = g^{k + l}, (gk)−1=g−k(g^k)^{-1} = g^{-k}, (gk)e=gke(g^k)^e = g^{ke};
  • the Frobenius map is σe(gk)=gkpe\sigma^e(g^k) = g^{k p^e} and the pp-th root is gkpd−1g^{k p^{d-1}};
  • −1=g(q−1)/2-1 = g^{(q-1)/2} for odd pp (the unique element of order 2), and −1=1=g0-1 = 1 = g^0 for p=2p = 2, so negation adds (q−1)/2(q - 1)/2 or nothing;
  • for odd pp, gkg^k is a square if and only if kk is even, since the squares form the subgroup of index 2; its square roots are ±gk/2\pm g^{k/2}. For p=2p = 2 every element is a square, and the square root of gkg^k is gk/2g^{k/2} or g(k+q−1)/2g^{(k + q - 1)/2} (q−1q - 1 is odd);
  • for i≥ji \ge j, gi+gj=gj(1+gi−j)=gj+Z(i−j)g^i + g^j = g^j (1 + g^{i - j}) = g^{j + Z(i - j)}, where Z(i−j)Z(i - j) is "infinite" (the sum is zero) when gi−j=−1g^{i-j} = -1; subtraction is addition of gj+(q−1)/2g^{j + (q-1)/2}.

So every operation except table construction costs a few word operations and one memory access. When the table does not fit in the cache, the memory access dominates: for q≈106q \approx 10^6 the polynomial representation fq_nmod is already faster (see Arithmetic in finite fields).

Building the tables#

Let ff be the defining polynomial and gg the class of xx in Fp[x]/(f)\mathbb{F}_p[x]/(f). To index elements by integers, write an element in the polynomial representation as ∑j<dcjgj\sum_{j < d} c_j g^j with cj∈[0,p)c_j \in [0, p) and map it to the integer ν(a)=∑jcjpj∈[0,q)\nu(a) = \sum_j c_j p^j \in [0, q), its coefficients read as digits in base pp. This is a bijection between Fq\mathbb{F}_q and [0,q)[0, q), with ν(0)=0\nu(0) = 0 and ν(1)=1\nu(1) = 1.

Algorithm 1: Zech tables

Input: a monic irreducible ff of degree dd over Fp\mathbb{F}_p.

Output: the tables E[k]=ν(gk)E[k] = \nu(g^k) and Z(k)Z(k) for 0≤k<q−10 \le k < q - 1, and L[c]=log⁡cL[c] = \log c for c∈Fp×c \in \mathbb{F}_p^\times; or failure if gg is not primitive.

  1. Set T[n]←∞T[n] \gets \infty for 0≤n<q0 \le n < q, and r←1r \gets 1.
  2. For k=0,1,…,q−2k = 0, 1, \ldots, q - 2: let n=ν(r)n = \nu(r); if T[n]≠∞T[n] \ne \infty, fail. Set T[n]←kT[n] \gets k and E[k]←nE[k] \gets n; if rr is a constant cc, set L[c]←kL[c] \gets k. Set r←rgr \gets r g.
  3. For each n∈[0,q)n \in [0, q): let n′=n+1−pn' = n + 1 - p if n≡p−1(modp)n \equiv p - 1 \pmod p and n′=n+1n' = n + 1 otherwise; set Z(T[n])←T[n′]Z(T[n]) \gets T[n'] (with T[0]=∞T[0] = \infty for the element 0).

Theorem 1. Algorithm 1 fails if and only if gg is not a primitive element of Fq\mathbb{F}_q. Otherwise it computes the tables correctly, with q−1q - 1 multiplications in Fq\mathbb{F}_q and O(q)O(q) further word operations.

Proof. The loop in step 2 visits 1,g,g2,…,gq−21, g, g^2, \ldots, g^{q-2}. These are pairwise distinct if and only if the order of gg is at least q−1q - 1, that is, if gg is primitive; since ν\nu is injective and gk≠0g^k \ne 0, a repeated value of ν\nu occurs exactly when two of the powers coincide. If gg is primitive, every nonzero element is reached once, so T[ν(a)]=log⁡aT[\nu(a)] = \log a for every a≠0a \ne 0, and EE and LL are the stated tables. In step 3, n′n' is ν(a+1)\nu(a + 1) for the element aa with ν(a)=n\nu(a) = n: adding 1 increases the constant coefficient c0=n mod pc_0 = n \bmod p by one, except that p−1p - 1 wraps to 0, which subtracts p−1p - 1 from nn. Hence for a=gka = g^k, T[n′]=log⁡(1+gk)=Z(k)T[n'] = \log(1 + g^k) = Z(k), with the value ∞\infty when 1+gk=01 + g^k = 0.

The tables take qq words for ZZ, qq for EE and pp for LL; the temporary table TT takes another qq words. Because the construction fails for a non-primitive ff, it doubles as a primitivity test: fq_zech_ctx_init_fq_nmod_ctx_check returns 0 in that case. Conway polynomials are primitive by definition, and other fq_zech contexts are created with random primitive polynomials (Defining polynomials).

Conversions, norm and trace#

The table EE gives the polynomial representation of gkg^k directly: its coefficients are the base-pp digits of E[k]E[k], which is how fq_zech_get_fq_nmod and the polynomial multiplication of fq_zech_poly convert elements. Conversely, ∑jcjgj\sum_j c_j g^j is computed as a sum of the terms gL[cj]+jg^{L[c_j] + j} with d−1d - 1 Zech additions.

The norm of gg is N(g)=∏i<dgpi=g(q−1)/(p−1)N(g) = \prod_{i < d} g^{p^i} = g^{(q-1)/(p-1)}, and it is (−1)df(0)(-1)^d f(0) for the monic minimal polynomial ff of gg; it is a generator of Fp×\mathbb{F}_p^\times, since g(q−1)/(p−1)g^{(q-1)/(p-1)} has order p−1p - 1. The context stores it (prime_root), and then:

  • N(gk)=N(g)kN(g^k) = N(g)^k, one exponentiation modulo pp (fq_zech_norm);
  • the elements of Fp×\mathbb{F}_p^\times are the powers gm(q−1)/(p−1)=N(g)mg^{m(q-1)/(p-1)} = N(g)^m, so an element of the prime field with logarithm ll corresponds to the integer N(g)l(p−1)/(q−1) mod pN(g)^{l (p-1)/(q-1)} \bmod p; fq_zech_trace sums the dd conjugates gkpig^{k p^i} with Zech additions and converts the result in this way.

Use in FLINT#

Referenced from#

References#

  • [LN1997] R. Lidl and H. Niederreiter. Finite Fields. Second edition, Encyclopedia of Mathematics and its Applications 20, Cambridge University Press, 1997.
  • [Hub1990] K. Huber. Some comments on Zech's logarithms. IEEE Transactions on Information Theory 36:4 (1990), 946–950.
Cite this page

The FLINT team, “Zech logarithms,” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/algorithms/finite-fields/zech-logarithms.html (generated 2026-11-02).