The Discrete Fourier Transform
The Discrete Fourier Transform
The continuous Fourier transform is beautiful; the discrete one is what runs. Sample a signal at points and Fourier analysis becomes a single matrix–vector product by a special matrix — one whose normalized form is unitary. That unitarity is not a footnote: it is the exact reason the Quantum Fourier Transform exists as a legal quantum operation, and the FFT's trick is the classical shadow of the QFT's circuit. This lesson is the hinge between Term 0 and the quantum algorithms to come.
Learning Objectives
By the end of this lesson you will be able to:
- Define the discrete Fourier transform and its inverse, and express both as matrix–vector products.
- Prove that the normalized DFT matrix is unitary, using the roots-of-unity orthogonality relation.
- Explain the periodicity of the DFT and connect it to sampling and aliasing.
- Contrast the naive DFT with the FFT and explain the divide-and-conquer idea.
- Articulate precisely how the Quantum Fourier Transform performs this same unitary on amplitudes in gates with , and locate where that is developed.
- Build the DFT matrix in NumPy, verify unitarity with
np.allclose, and check it againstnp.fft.
Intuition
You cannot store a continuous signal in a computer — you store samples . The discrete Fourier transform asks the same question as before ("what frequencies is this made of?") but now there are only frequencies to ask about, indexed . So the DFT is finite: inputs in, complex amplitudes out. Each output is the overlap of the sampled signal with a sampled pure tone — exactly the inner-product "project onto a frequency" move from lesson 2, now a finite sum.
Because it is finite and linear, the DFT is a matrix. And the magic from the roots of unity comes back: the rows of that matrix are sampled tones, and distinct tones are orthogonal (the vanishing-sum theorem from lesson 1). Orthogonal rows, after normalizing, make a unitary matrix — a rotation in that preserves length. Hold onto that word unitary: in quantum computing, unitary = "a thing a closed quantum system is allowed to do." The DFT being unitary is what lets a quantum computer perform it, and do so astonishingly fast.
There are two efficiency stories here, and they rhyme. Classically, the naive DFT costs multiply-adds, but the FFT exploits the recursive structure of the roots of unity to do it in . Quantumly, the QFT exploits the same structure to do it in gates — because the amplitudes live on only qubits. Same matrix, three speeds. By the end you should see the DFT not as a numerical recipe but as the unitary that the rest of the program keeps reaching for.
Theory
Definition
Given a vector , the discrete Fourier transform is the vector with
Writing for the primitive -th root of unity (Appendix E §6), the kernel is , so . (We follow the program convention with a minus sign in the forward DFT kernel; Appendix C §4. This makes the inverse DFT carry , matching the QFT's action in Appendix E §6.)
The inverse discrete Fourier transform (IDFT) recovers from :
Proof that this inverts the DFT. Substitute the definition of and swap the finite sums:
where the braced sum is the roots-of-unity orthogonality relation from Appendix E §6 and proved in lesson 1: . Only survives, leaving .
The DFT as a matrix
Both transforms are linear, so each is multiplication by an matrix. Define the DFT matrix with entries
so that . It is a symmetric Vandermonde-type matrix in the powers of . For , with so :
reducing each exponent mod (e.g. , ). Row samples the pure tone of frequency ; the inverse matrix is (the conjugate, up to the ), as the IDFT formula shows.
The normalized DFT matrix is unitary
The factor-of- asymmetry between forward and inverse transforms is just bookkeeping. Split the symmetrically by defining the normalized DFT matrix
Theorem. is unitary: .
Proof. Compute the entry of . The adjoint conjugates and transposes, so $(U^{\dagger}){jn} = \overline{U{nj}} = \tfrac{1}{\sqrt N},\overline{\omega^{-nj}} = \tfrac{1}{\sqrt N},\omega^{nj}\overline{\omega^{m}} = \omega^{-m}$, from lesson 1). Then
By the orthogonality relation (Appendix E §6), this equals , i.e. $U^{\dagger}U = IUU^{\dagger}U = IUU^{\dagger}=IU$ is unitary.
This is the single most important fact in the lesson. Equivalent restatements:
- The rows (and columns) of are an orthonormal basis of — the normalized sampled tones .
- preserves the inner product and the norm: and . This is the finite-dimensional Parseval/Plancherel identity — the same energy-conservation proved in lesson 2, now exact and algebraic: for the unnormalized , i.e. .
- , so the inverse transform is "the same machine run backward" — and in particular the IDFT is the adjoint, which is exactly what makes the inverse QFT just the QFT circuit reversed.
Computational cost and the FFT idea
Computing directly is inner products of length : complex multiply-adds, i.e. . The Fast Fourier Transform (Cooley–Tukey) brings this to by divide-and-conquer on the structure of the roots of unity. For even , split into even- and odd-indexed subsequences:
Now use , the primitive -th root. The even sum is a length- DFT of the even samples; the odd sum is times a length- DFT of the odd samples:
where the second line uses (since ) and the period- of . So two half-size DFTs plus "butterfly" combines give the full DFT. The recurrence solves to — the asymmetry in the cancellation (the same that made roots sum to zero) is what halves the work at every level.
Periodicity and sampling
Two periodicities are built in. First, both and are treated as periodic with period :
$X_{k+N} = \sum_n x_n,\omega^{-(k+N)n} = \sum_n x_n,\omega^{-kn},\underbrace{\omega^{-Nn}}{=1} =
X_kx{n+N} = x_n$. This is why np.fft-based convolution is circular (it wraps
around), as flagged in lesson 2.
Second, the DFT lives on sampled data. If a continuous signal is sampled at rate ( samples spaced ), the DFT bin corresponds to frequency for , and to the negative frequency for (the upper half of the spectrum is the negative frequencies, by the period- symmetry). The Nyquist–Shannon sampling theorem says a signal band-limited to is perfectly determined by its samples; frequencies above the Nyquist frequency are indistinguishable from lower ones — they alias. Aliasing is just the period- identity wearing a physical hat: two tones whose frequencies differ by a multiple of produce identical samples.
The strong link: this is (classically) what the QFT does
Everything above sets up one of the program's pivotal connections. The Quantum Fourier Transform applies the same unitary — the normalized DFT matrix — but to the amplitudes of a quantum state rather than to a stored array. With basis states on qubits, its action on a basis state is precisely the DFT kernel (Appendix E §6):
and on a general superposition it maps the amplitude vector . (The QFT conventionally uses the sign — it implements the inverse-DFT kernel, or equivalently the DFT up to the index reversal ; the unitary content is identical and the choice is just our Appendix C §4 convention.) Three things make this revolutionary, and each traces back to a fact in this lesson:
- It is allowed at all because is unitary (the theorem above). A non-unitary "transform" could not be a quantum gate.
- It is exponentially compact. The classical FFT writes down all outputs in $O(N\log N) = O(n,2^n)n=\log_2 NO(n^2)$ gates** — Hadamards and controlled-phase rotations whose phases are exactly the roots of unity from lesson 1. That is the QFT gate-count recorded in Appendix E §8.
- The inverse is free. Because , running the QFT circuit in reverse (daggering each gate) gives the inverse — no new construction needed. This is what powers Quantum Phase Estimation.
The catch, which the quantum lessons make precise, is that you cannot read out all amplitudes: the QFT does not hand you the spectrum, it rearranges amplitudes so that a subsequent measurement samples from a Fourier-transformed distribution. That is exactly enough to find hidden periods, which is why the QFT is the engine of Shor's factoring algorithm.
Forward link (do this when you reach Term 2). The QFT is built, decomposed into gates, and run on Braket in Term 2.4 · The Quantum Fourier Transform; it is then used for Phase Estimation and ultimately Shor's algorithm in Term 3.3. When you get there, the matrix you build below is the exact unitary that circuit implements. [KLM, Ch. 7] and [NC, §5.1] develop the gate decomposition.
Worked Examples
Example 1 — DFT of a length-4 signal by hand
Let . Using the matrix above ():
Interpretation: is a tone that repeats every samples — i.e. it sits at the Nyquist frequency (bin ) plus a DC component (bin ). The transform confirms energy only at (the average) and (the fastest representable oscillation), with nothing in between. Inverting: returns — try it.
Example 2 — Verifying unitarity for
Take the normalized matrix . Its first two rows are and . Check orthonormality via the Hermitian inner product (conjugate the left):
The diagonal inner products are and the off-diagonal is — the rows are orthonormal, the hallmark of a unitary matrix. The general proof (orthogonality relation) gives this for all row pairs and all .
Example 3 — A period reveals itself as a frequency spike
Let and for — a pure cosine completing exactly cycles over the window. Since , this signal is with . Its DFT is therefore nonzero only where the kernel matches: a spike of height at bin and another at bin (the alias / negative-frequency partner), with all other bins zero. The DFT has localized the periodicity of into two sharp peaks — the discrete analog of "a tone in time is a spike in frequency." This peak-at-the-period behavior is precisely what Shor's algorithm reads off the QFT (via measurement) to recover an unknown period.
Hands-on (Python)
import numpy as np
# =====================================================================
# 1. Build the (un)normalized DFT matrix and the normalized unitary one.
# =====================================================================
def dft_matrix(N, normalized=False):
"""Return the N×N DFT matrix W with W[k,n] = ω^{-kn}, ω = e^{2πi/N}.
If normalized, return U = W/√N (the unitary normalized DFT)."""
k = np.arange(N).reshape(-1, 1) # column index k
n = np.arange(N).reshape(1, -1) # row index n
W = np.exp(-2j * np.pi * k * n / N) # ω^{-kn} = e^{-2πi kn/N}
return W / np.sqrt(N) if normalized else W
N = 8
W = dft_matrix(N)
U = dft_matrix(N, normalized=True)
# Sanity: the N=4 matrix matches the hand computation in the lesson.
print("N=4 DFT matrix (rounded):")
print(np.round(dft_matrix(4), 6).real + 1j * np.round(dft_matrix(4), 6).imag)
# =====================================================================
# 2. PROVE numerically that the normalized DFT matrix is UNITARY.
# U is unitary ⇔ U† U = I ⇔ rows form an orthonormal basis.
# =====================================================================
def dag(A):
return A.conj().T # adjoint (conjugate transpose)
I = np.eye(N)
print("U† U = I :", np.allclose(dag(U) @ U, I, atol=1e-12)) # True
print("U U† = I :", np.allclose(U @ dag(U), I, atol=1e-12)) # True
print("U⁻¹ = U† :", np.allclose(np.linalg.inv(U), dag(U), atol=1e-12)) # True
# Norm preservation (finite-dimensional Parseval / Plancherel):
x = np.random.default_rng(0).standard_normal(N) + 1j * np.random.default_rng(1).standard_normal(N)
print("‖Ux‖ = ‖x‖ :", np.isclose(np.linalg.norm(U @ x), np.linalg.norm(x))) # True
# =====================================================================
# 3. Our DFT vs. np.fft. NumPy uses the UNNORMALIZED convention X = W x,
# with the SAME e^{-2πi kn/N} kernel — so it must match W @ x exactly.
# =====================================================================
x = np.array([1, 0, 1, 0], dtype=complex)
print("\nExample 1 check, x = (1,0,1,0):")
print(" W @ x =", np.round(dft_matrix(4) @ x, 10)) # [2,0,2,0]
print(" np.fft.fft =", np.round(np.fft.fft(x), 10)) # [2,0,2,0]
print(" match :", np.allclose(dft_matrix(4) @ x, np.fft.fft(x))) # True
# Inverse: IDFT recovers x. (np.fft.ifft includes the 1/N.)
X = np.fft.fft(x)
print(" IDFT recovers x:", np.allclose(np.fft.ifft(X), x)) # True
# =====================================================================
# 4. A period shows up as a frequency spike (Worked Example 3).
# =====================================================================
N = 8
n = np.arange(N)
x = np.cos(2 * np.pi * 2 * n / N) # exactly 2 cycles over the window
X = np.fft.fft(x)
print("\nSpectrum magnitudes of a 2-cycle cosine (N=8):")
print(np.round(np.abs(X), 6)) # spikes of height 4 at bins k=2 and k=6
# =====================================================================
# 5. Cost scaling: naive DFT (matrix multiply, O(N²)) vs FFT (O(N log N)).
# Both agree; the FFT is dramatically faster as N grows.
# =====================================================================
import time
for N in (256, 1024, 4096):
x = np.random.default_rng(0).standard_normal(N).astype(complex)
W = dft_matrix(N)
t0 = time.perf_counter(); Xslow = W @ x; t1 = time.perf_counter()
t2 = time.perf_counter(); Xfast = np.fft.fft(x); t3 = time.perf_counter()
assert np.allclose(Xslow, Xfast, atol=1e-8)
print(f"N={N:5d}: naive O(N²) = {1e3*(t1-t0):7.2f} ms "
f"FFT O(N log N) = {1e3*(t3-t2):7.3f} ms")What you should observe: U† U = I, U U† = I, U⁻¹ = U†, and ‖Ux‖ = ‖x‖ all print True — a
numerical proof that the normalized DFT matrix is unitary and norm-preserving. Our hand-built W @ x
matches np.fft.fft exactly (same kernel, same unnormalized convention), and the IDFT round-trips.
The 2-cycle cosine produces clean spikes at bins and . Finally the timing loop shows the
naive matrix product ballooning while the FFT stays nearly flat — the classical preview of
why the QFT's gate count is such a leap.
Exercises
1. (Easy) DFT by hand. Compute the DFT of for using the matrix , and interpret the result.
Solution
Each output is a row of dotted with , i.e. the sum of that row's entries. Row 0 sums to ; rows are , , , each summing to (the vanishing-sum theorem!). So . A constant signal is pure DC: all energy in bin , nothing elsewhere.
2. (Easy) Linearity and the inverse. Given and , what is ? And how do you recover from using the matrix ?
Solution
By linearity of matrix multiplication, . Recovery: since , we have — or directly (the IDFT). The key point is , so inverting is just applying the adjoint.
3. (Medium) Unitarity of the DFT. Write for , normalize it, and show by hand that . What familiar gate is ?
Solution
For , , so W = \begin{psmallmatrix}1&1\\1&-1\end{psmallmatrix} and U = \tfrac1{\sqrt2}\begin{psmallmatrix}1&1\\1&-1\end{psmallmatrix}. is real and symmetric, so , and U^2 = \tfrac12\begin{psmallmatrix}2&0\\0&2\end{psmallmatrix} = I. Hence : unitary. This is exactly the Hadamard gate (Appendix E §2) — the single-qubit QFT is the Hadamard, which is why the QFT on qubits begins with a Hadamard on each.
4. (Medium) Periodicity and aliasing. A continuous tone at Hz is sampled at samples/s. Which DFT bin does it land in for , and why is that not bin ""? Identify the aliased frequency.
Solution
Bin corresponds to frequency Hz for , and to Hz for . A Hz tone exceeds the Nyquist frequency Hz, so it aliases: $5,\text{Hz} \equiv 5 - f_s = 5 - 8 = -3,\text{Hz}-3k$ with , i.e. — but it is physically a Hz (equivalently Hz) component, indistinguishable from a true Hz tone given these samples. Algebraically this is — the period- identity $\omega^{-kn} = \omega^{-(k\pm N)n}$. Moral: sample faster than twice the highest frequency, or alias.
5. (Hard) FFT butterfly by hand. Using the radix-2 split , , compute the DFT of () via two length-2 DFTs and one butterfly stage. Check against the direct matrix product.
Solution
Even samples ; odd . Length-2 DFTs (the matrix \begin{psmallmatrix}1&1\\1&-1\end{psmallmatrix}): and . Twiddle factors with : , . Combine for :
So . Direct gives the same (and np.fft.fft([1,2,3,4])
confirms it). The conjugate-symmetry reflects that is real.
6. (Hard) Counting operations: DFT vs FFT vs QFT. For (), estimate the number of complex multiplications for (a) the naive DFT, (b) the FFT, and (c) the number of gates for the QFT. State the qubit count for the QFT and the moral.
Solution
(a) Naive DFT: complex multiplies. (b) FFT: $\sim \tfrac{N}{2}\log_2 N = \tfrac{2^{20}}{2}\cdot 20 = 10\cdot 2^{20}\approx 1.05\times 10^7$ — about fewer than naive. (c) QFT: with qubits, the standard decomposition uses Hadamard + controlled-phase gates (, Appendix E §8), plus swaps. Moral: the FFT is an enormous classical win, but it still writes down all outputs; the QFT manipulates the same amplitudes living on just qubits with a few hundred gates — though you cannot read all amplitudes out, only sample. That exponential compactness, harnessed by phase estimation, is the source of Shor's speedup. See Term 2.4.
Checkpoint
1. Write the DFT and its inverse, and identify the kernel.
(forward), and (inverse), with kernel and .
2. Why is the normalized DFT matrix $U = W/\sqrt N$ unitary?
by the roots-of-unity orthogonality relation. So (and, being square, ): its rows are orthonormal sampled tones.
3. What is the inverse of a unitary, and why does that matter for the QFT?
. For the QFT this means the inverse transform is just the circuit run in reverse with each gate daggered — no separate construction — which is what makes Quantum Phase Estimation practical.
4. State the cost of the naive DFT vs. the FFT, and the idea behind the speedup.
Naive DFT is ; the FFT is . The speedup comes from radix-2 divide-and-conquer: , , recursively splitting into half-size DFTs (), using .
5. What does periodicity of the DFT imply about convolution and sampling?
The DFT treats data as period-, so FFT-based convolution is circular (wrap-around; zero-pad for linear convolution). For sampled signals, frequencies above Nyquist alias onto lower bins — the period- identity in physical disguise.
6. In one sentence: how does the QFT relate to the DFT, and where is it built?
The QFT applies the same unitary (the normalized DFT matrix) to the amplitudes of an -qubit state () using only gates; it is constructed in Term 2.4 · The Quantum Fourier Transform.
Further Reading
- [NC, §5.1] — the Quantum Fourier Transform and its gate decomposition; the DFT background it rests on.
- [KLM, Ch. 6–7] — DFT → FFT → QFT, developed in the order this course follows.
- [Aar] — intuition for why the QFT's compactness does not let you read out the spectrum, only sample it.
- Appendix E §6, §8 — orthogonality relation, QFT kernel, and the gate count.
← Prev: Fourier Series & Transforms · Up: Term 0 · Next: Models of Computation →