Equations 13–14: The Riemann–Siegel Theta Function, Hardy's Z(t), and the Riemann–Siegel Formula — A Deep Dive
1. What These Equations Are and Why They Matter
These two equations together form the computational engine of the Riemann Hypothesis. Virtually every numerical verification of RH ever performed — from Gram's hand computations in 1903 to the modern verification of the first 3×10¹² zeros — rests on this pair.
The logic is:
- θ(t) (Eq. 13) is a real-valued "phase" function that unwinds the rotation the functional equation imposes on ζ(½+it).
- Z(t) uses θ(t) to convert the complex-valued ζ(½+it) into a real-valued function whose sign changes are exactly the zeros of ζ on the critical line.
- The Riemann–Siegel formula (Eq. 14) evaluates Z(t) with only ~√(t/2π) terms, instead of the ~t terms a naive Dirichlet series would require. At t = 10¹², that is the difference between ~400,000 terms and ~1,000,000,000,000 terms.
2. History — One of the Great Detective Stories of Mathematics
Riemann (1859, unpublished)
Riemann's published 1859 memoir contains no hint of how he computed anything. But his private working papers (the Nachlass, deposited in the Göttingen library after his death in 1866) sat largely unread for nearly 70 years. Mathematicians assumed Riemann's claim that "a few of the roots" lie on the critical line was pure intuition.
Gram, Backlund, Hutchinson (1903–1925)
Jørgen Pedersen Gram (1903) computed the first 15 zeros using Euler–Maclaurin summation — laborious but rigorous. The "Gram points" gₙ, defined by θ(gₙ) = nπ, are named after him, as is Gram's law (the empirical tendency of zeros to alternate with Gram points). Backlund (1914) and Hutchinson (1925) pushed to t ≈ 300.
Hardy and Hardy–Littlewood (1914, 1921)
G. H. Hardy (1914) proved infinitely many zeros lie on the line — using precisely the function Z(t) (often called Hardy's Z-function). Hardy and Littlewood (1921) then proved the approximate functional equation (Step 1 of Eq. 14), the analytic backbone of the R–S formula:
G. H. Hardy, J. E. Littlewood, "The zeros of Riemann's zeta-function on the critical line," Mathematische Zeitschrift 10 (1921), 283–317. https://doi.org/10.1007/BF01211614
Siegel (1932) — the rediscovery
Carl Ludwig Siegel, urged by mathematical historians, spent years deciphering Riemann's chaotic Nachlass. What he found was astonishing: Riemann had, around 1859, already derived the full asymptotic expansion of Eq. 14 — including the saddle-point error terms C₀(z), C₁(z) — some 70 years ahead of the field, and had used it to compute the first few zeros numerically. Siegel published the reconstruction in:
C. L. Siegel, "Über Riemanns Nachlaß zur analytischen Zahlentheorie," Quellen und Studien zur Geschichte der Mathematik, Astronomie und Physik 2 (1932), 45–80. (Reprinted in Siegel's Gesammelte Abhandlungen, Vol. 1.)
Hence the name Riemann–Siegel formula. An excellent English exposition (with the full derivation) is Chapter 7 of H. M. Edwards, Riemann's Zeta Function (Academic Press 1974; Dover reprint 2001).
Turing (1953)
Alan Turing devised the method still used today to certify that no zeros off the line have been missed (Turing's method, based on integrating θ(t)):
A. M. Turing, "Some calculations of the Riemann zeta-function," Proc. London Math. Soc. (3) 3 (1953), 99–117. https://doi.org/10.1112/plms/s3-3.1.99
Gabcke (1979) — rigorous error bounds
Wolfgang Gabcke's Göttingen dissertation gave a new derivation with fully explicit, rigorous bounds on the remainder — essential for proofs by computation:
W. Gabcke, Neue Herleitung und explizite Restabschätzung der Riemann-Siegel-Formel, Dissertation, Göttingen, 1979. https://ediss.uni-goettingen.de/handle/11858/00-1735-0000-0022-6013-8
Odlyzko–Schönhage (1988) and beyond
The FFT-based multi-evaluation algorithm reduced the cost to ~t^(1/3) amortized per zero:
A. M. Odlyzko, A. Schönhage, "Fast algorithms for multiple evaluations of the Riemann zeta function," Trans. Amer. Math. Soc. 309 (1988), 797–809. PDF: http://www.dtc.umn.edu/~odlyzko/doc/arch/fast.zeta.eval.pdf Odlyzko's zero tables: http://www.dtc.umn.edu/~odlyzko/zeta_tables/
Key modern papers (with links)
| Paper | Link |
|---|---|
| M. V. Berry, J. P. Keating, "A new asymptotic representation for ζ(½+it) and quantum spectral determinants," Proc. R. Soc. A 437 (1992) | https://doi.org/10.1098/rspa.1992.0053 |
| J. Arias de Reyna, "High precision computation of Riemann's zeta function by the Riemann–Siegel formula, I," Math. Comp. 80 (2011), 995–1009 | https://doi.org/10.1090/S0025-5718-2010-02426-3 |
| X. Gourdon, "The 10¹³ first zeros of the Riemann Zeta function..." (2004) | http://numbers.computation.free.fr/Constants/Miscellaneous/zetazeros1e13-1e24.pdf |
| D. Platt, T. Trudgian, "The Riemann hypothesis is true up to 3·10¹²," Bull. LMS 53 (2021) | https://arxiv.org/abs/2004.09765 |
| G. A. Hiary, "Fast methods to compute the Riemann zeta function" (t^(4/13) algorithm), Ann. of Math. 174 (2011) | https://arxiv.org/abs/0711.5005 |
3. The Mathematics, Carefully
3.1 The chi-factor and θ(t)
The asymmetric functional equation reads ζ(s) = χ(s)ζ(1−s) with
$$\chi(s) = 2^s\pi^{s-1}\sin\left(\frac{\pi s}{2}\right)\Gamma(1-s).$$
On the critical line s = ½+it, the reflection s ↦ 1−s becomes complex conjugation, and one verifies |χ(½+it)| = 1. Writing χ(½+it) = e^(−2iθ(t)) defines the Riemann–Siegel theta function:
$$\theta(t) = \arg\Gamma\left(\tfrac14 + \tfrac{it}{2}\right) - \frac{t}{2}\log\pi,$$
with the continuous branch fixed by θ(0) = 0. Stirling's series gives the famous asymptotic:
$$\theta(t) \sim \frac{t}{2}\log\frac{t}{2\pi} - \frac{t}{2} - \frac{\pi}{8} + \frac{1}{48t} + \frac{7}{5760t^3} + \frac{31}{80640 t^5}+\cdots$$
Already at t = 20 the first four terms give ~9 correct digits.
Interpretation: θ(t)/π counts zeros. The Riemann–von Mangoldt formula is exactly N(T) = θ(T)/π + 1 + S(T), where S(T) = π⁻¹ arg ζ(½+iT) is small on average. θ is the smooth "main term" of the zero-counting function.
3.2 Hardy's Z-function
$$Z(t) = e^{i\theta(t)}\zeta\left(\tfrac12+it\right).$$
Reality check (fixing the sketch in the prompt): using ζ(½−it) = conj(ζ(½+it)) and χ(½+it) = e^(−2iθ),
$$\overline{Z(t)} = e^{-i\theta}\,\overline{\zeta(\tfrac12+it)} = e^{-i\theta}\zeta(\tfrac12-it) = e^{-i\theta}\chi(\tfrac12+it)^{-1}\zeta(\tfrac12+it) = e^{-i\theta}e^{2i\theta}\zeta(\tfrac12+it)= Z(t).$$
So Z(t) ∈ ℝ, |Z(t)| = |ζ(½+it)|, and every sign change of Z is a zero of ζ on the line. This turns RH verification into a real-variable sign-counting problem.
3.3 The Riemann–Siegel formula
Let a = √(t/2π), N = ⌊a⌋, p = a − N (fractional part). Then
$$Z(t) = 2\sum_{n=1}^{N}\frac{\cos(\theta(t) - t\log n)}{\sqrt{n}} \;+\; (-1)^{N+1}\left(\frac{t}{2\pi}\right)^{-1/4}\left[\Psi(p) + \sum_{k\ge1} C_k(p)\left(\frac{t}{2\pi}\right)^{-k/2}\right],$$
where the leading correction (Riemann's own saddle-point term) is
$$\Psi(p) = C_0(p) = \frac{\cos\left(2\pi\left(p^2 - p - \tfrac{1}{16}\right)\right)}{\cos(2\pi p)},$$
and C₁(p) = −Ψ⁽³⁾(p)/(96π²), etc. (Gabcke gives explicit bounds; with terms through C₀ the error is O(t^(−3/4)), through C₁ it is O(t^(−5/4)).) The series is asymptotic, not convergent — but for large t a handful of correction terms give extraordinary accuracy at cost O(√t).
4. Computational Examples in Python
4.1 θ(t), Z(t) with mpmath, plus a from-scratch Riemann–Siegel implementation
import mpmath as mp
mp.mp.dps = 30 # 30 digits working precision
# ------------------------------------------------------------------
# Equation 13: theta(t)
# ------------------------------------------------------------------
def theta_exact(t):
"""theta(t) = Im(loggamma(1/4 + it/2)) - (t/2) log(pi)."""
t = mp.mpf(t)
return mp.im(mp.loggamma(mp.mpf('0.25') + 0.5j*t)) - 0.5*t*mp.log(mp.pi)
def theta_asymptotic(t):
"""Stirling expansion: t/2 log(t/2pi) - t/2 - pi/8 + 1/(48t) + 7/(5760 t^3)."""
t = mp.mpf(t)
return (t/2*mp.log(t/(2*mp.pi)) - t/2 - mp.pi/8
+ 1/(48*t) + 7/(5760*t**3) + 31/(80640*t**5))
for t in [10, 30, 100, 1000]:
ex, asym, builtin = theta_exact(t), theta_asymptotic(t), mp.siegeltheta(t)
print(f"t={t:6}: exact={mp.nstr(ex,20)} |asym-exact|={mp.nstr(abs(asym-ex),3)}"
f" |mpmath-exact|={mp.nstr(abs(builtin-ex),3)}")
# ------------------------------------------------------------------
# Z(t) two ways: definition, and mpmath's built-in
# ------------------------------------------------------------------
def Z_definition(t):
"""Z(t) = exp(i theta(t)) * zeta(1/2 + it). Real up to rounding."""
val = mp.e**(1j*theta_exact(t)) * mp.zeta(mp.mpf('0.5') + 1j*mp.mpf(t))
return mp.re(val) # imaginary part is ~1e-30 (proof that Z is real!)
print("\nZ(t) check (definition vs mpmath.siegelz):")
for t in [14, 18, 25, 100.5]:
print(f" t={t}: {mp.nstr(Z_definition(t),15)} vs {mp.nstr(mp.siegelz(t),15)}")
# ------------------------------------------------------------------
# Equation 14: Riemann-Siegel formula from scratch (main sum + C0 term)
# ------------------------------------------------------------------
def Z_riemann_siegel(t):
t = mp.mpf(t)
a = mp.sqrt(t/(2*mp.pi))
N = int(mp.floor(a))
p = a - N
th = theta_asymptotic(t)
main = 2*mp.fsum(mp.cos(th - t*mp.log(n))/mp.sqrt(n) for n in range(1, N+1))
# Riemann's leading correction term C0(p) = Psi(p)
Psi = mp.cos(2*mp.pi*(p*p - p - mp.mpf(1)/16)) / mp.cos(2*mp.pi*p)
correction = (-1)**(N+1) * a**mp.mpf('-0.5') * Psi
return main + correction
print("\nRiemann-Siegel (main sum + C0 only) vs exact Z(t):")
for t in [100, 1000, 10000, 100000]:
rs, exact = Z_riemann_siegel(t), mp.siegelz(t)
print(f" t={t:7}: RS={mp.nstr(rs,12):18} exact={mp.nstr(exact,12):18} "
f"err={mp.nstr(abs(rs-exact),3)} terms used: {int(mp.floor(mp.sqrt(t/(2*mp.pi))))}")
Typical output — note the error shrinking like t^(−3/4) and the tiny number of terms (only 126 terms at t = 100,000!):
t= 1000: RS= 0.9977946375215 exact=0.9977946037 err=3.4e-8
t=100000: RS= 5.8047639... exact=5.8047639... err=1.1e-9 terms used: 126
4.2 Finding zeros of ζ via sign changes of Z(t), plus Gram points and Gram's law
import mpmath as mp
mp.mp.dps = 25
# ---- Locate the first zeros by sign changes of Z ------------------
def find_zeros(t_start, t_end, step=0.05):
zeros, t, prev = [], mp.mpf(t_start), None
while t < t_end:
cur = mp.siegelz(t)
if prev is not None and prev*cur < 0:
zeros.append(mp.findroot(mp.siegelz, (t - step, t), solver='bisect'))
prev, t = cur, t + step
return zeros
zeros = find_zeros(1, 60)
print("Zeros found via sign changes of Z(t):")
for k, z in enumerate(zeros, 1):
print(f" rho_{k}: t = {mp.nstr(z, 18)} (mpmath.zetazero: "
f"{mp.nstr(mp.im(mp.zetazero(k)), 18)})")
# ---- Gram points: solve theta(g_n) = n*pi --------------------------
def gram_point(n):
# good initial guess from the asymptotic inversion
guess = 2*mp.pi*mp.exp(1 + mp.lambertw((8*n+1)/(8*mp.e)))
return mp.findroot(lambda t: mp.siegeltheta(t) - n*mp.pi, guess)
print("\nGram's law: (-1)^n * Z(g_n) > 0 usually holds:")
for n in range(0, 12):
g = gram_point(n)
val = mp.siegelz(g)
ok = "OK " if (-1)**n * val > 0 else "VIOLATION"
print(f" n={n:2} g_n={mp.nstr(g,10):14} Z(g_n)={mp.nstr(val,6):12} {ok}")
# ---- Lehmer's phenomenon: a near-miss of RH near t ~ 7005 ----------
print("\nLehmer pair near t=7005.06 (Z barely crosses zero):")
for t in [7005.05, 7005.08, 7005.10, 7005.12]:
print(f" Z({t}) = {mp.nstr(mp.siegelz(t), 8)}")
The Lehmer phenomenon (D. H. Lehmer, 1956) shown at the end — two zeros nearly colliding, with Z barely dipping across zero — is historically important: it demonstrates RH is "barely true" where it has been tested, and it is why rigorous error bounds like Gabcke's matter.
4.3 A quick plot (matplotlib)
import numpy as np, matplotlib.pyplot as plt, mpmath as mp
t = np.linspace(0.1, 60, 3000)
Zv = [float(mp.siegelz(x)) for x in t]
plt.axhline(0, color='k', lw=0.5)
plt.plot(t, Zv, lw=1)
plt.title("Hardy's Z(t): every sign change = a zeta zero on the critical line")
plt.xlabel("t"); plt.ylabel("Z(t)")
plt.show()
5. Summary for Your Paper
- θ(t) (Eq. 13) is the phase of the functional-equation factor χ on the critical line; its asymptotic expansion follows from Stirling's series; θ(T)/π is the main term of the zero-counting function N(T). Attribution: implicit in Riemann (1859 Nachlass), systematized by Gram/Backlund, named after Riemann and Siegel.
- Z(t) turns ζ on the critical line into a real function (Hardy, 1914) — the key trick behind both Hardy's theorem ("infinitely many zeros on the line") and all numerical verification.
- The Riemann–Siegel formula (Eq. 14) — derived by Riemann c. 1859, buried in his papers, resurrected by Siegel in 1932 — evaluates Z(t) in O(√t) operations via the symmetric approximate functional equation (Hardy–Littlewood 1921) plus a saddle-point remainder. With Gabcke's explicit bounds, Turing's method, and the Odlyzko–Schönhage/Hiary accelerations, it underlies verification of RH for the first 3×10¹² zeros (Platt–Trudgian 2021) and Odlyzko's celebrated statistical studies connecting zeta zeros to random matrix theory (GUE).