Algorithm Search⌘K

Proofs: Multidimensional FFT

These are the human proofs of Multidimensional FFT, at full length.

MULTIDIM-FFT computes the d-dimensional DFT with N lg N additions and (N/2) lg N multiplications full

This proof shows: correctness, complexity.

Statement. Let RR be a commutative ring, d≥1d \ge 1, and n1,…,ndn_1, \ldots, n_d powers of two with product NN. For each axis aa let ωa∈R\omega_a \in R satisfy ωana=1\omega_a^{n_a} = 1 and, when na≥2n_a \ge 2, ωana/2=−1\omega_a^{n_a/2} = -1 (over C\mathbb{C} with ωa=e−2πi/na\omega_a = e^{-2\pi i/n_a} both hold). For every array xx stored in row-major order, MULTIDIM-FFT ends with the array

Xk1,…,kd=∑j1=0n1−1⋯∑jd=0nd−1xj1,…,jd ω1j1k1⋯ωdjdkdX_{k_1, \ldots, k_d} = \sum_{j_1 = 0}^{n_1 - 1} \cdots \sum_{j_d = 0}^{n_d - 1} x_{j_1, \ldots, j_d}\, \omega_1^{j_1 k_1} \cdots \omega_d^{j_d k_d}

in the same layout. Lines L5 to L8 do exactly Nlg⁡NN \lg N additions and subtractions and N2lg⁡N\frac{N}{2} \lg N multiplications in RR, the tables of line L4 do at most ∑ana/2\sum_a n_a/2 more, and the extra space is Θ(m)\Theta(m) with m=max⁡anam = \max_a n_a.

Lemma 1 (the lines partition the array). Fix an axis aa and write σ=σa=na+1⋯nd\sigma = \sigma_a = n_{a+1} \cdots n_d. Every position tt with 0≤t<N0 \le t < N has a unique expression t=q⋅naσ+iσ+rt = q \cdot n_a \sigma + i \sigma + r with 0≤q<N/(naσ)0 \le q < N / (n_a \sigma), 0≤i<na0 \le i < n_a and 0≤r<σ0 \le r < \sigma: this is division of tt by naσn_a \sigma with remainder, followed by division of the remainder by σ\sigma. So the lines {s+iσ:0≤i<na}\{s + i\sigma : 0 \le i < n_a\} for the starts s=q⋅naσ+rs = q \cdot n_a \sigma + r of line L5 are disjoint and cover all NN positions. In row-major order the position tt holds the entry with indices (j1,…,jd)(j_1, \ldots, j_d) where t=∑bjbσbt = \sum_b j_b \sigma_b; the mixed-radix digits of tt are exactly these indices, so on one line the indices jbj_b with b≠ab \ne a are fixed (they are the digits of qq and rr) and ja=ij_a = i runs over 0,…,na−10, \ldots, n_a - 1. □\square

Lemma 2 (one line). Let n=2tn = 2^t and ω∈R\omega \in R with ωn=1\omega^n = 1 and ωn/2=−1\omega^{n/2} = -1 when n≥2n \ge 2. The call FFT(ℓ,W)(\ell, W) of line L7, with W[k]=ωkW[k] = \omega^k, replaces ℓ\ell by Lk=∑iℓiωikL_k = \sum_{i} \ell_i \omega^{ik}, with nlg⁡nn \lg n additions and subtractions and n2lg⁡n\frac{n}{2} \lg n multiplications. Proof. By induction on tt. For t=0t = 0 there is nothing to do and L0=ℓ0L_0 = \ell_0. For t≥1t \ge 1 write EkE_k and OkO_k for the DFTs, with root ω2\omega^2, of the even and odd entries; ω2\omega^2 satisfies the hypothesis for n/2n/2, since (ω2)n/4=ωn/2=−1(\omega^2)^{n/4} = \omega^{n/2} = -1 when n≥4n \ge 4. Splitting the sum by the parity of ii gives Lk=Ek+ωkOkL_k = E_k + \omega^k O_k for 0≤k<n/20 \le k < n/2, and since EE and OO have period n/2n/2 and ωk+n/2=−ωk\omega^{k + n/2} = -\omega^k, also Lk+n/2=Ek−ωkOkL_{k + n/2} = E_k - \omega^k O_k. The iterative radix-2 code computes exactly these butterflies after the bit-reversal permutation, stage by stage; this is the standard decimation-in-time FFT, proved in full on the page of the iterative FFT. Each of the lg⁡n\lg n stages does n/2n/2 butterflies of one multiplication, one addition and one subtraction, which gives the counts. □\square

Invariant. Write X(a)X^{(a)} for the array after the passes 1,…,a1, \ldots, a of the loop at line L2. We prove by induction on aa that

Xk1,…,ka,ja+1,…,jd(a)=∑j1,…,jaxj1,…,jd ω1j1k1⋯ωajaka.(1)X^{(a)}_{k_1, \ldots, k_a, j_{a+1}, \ldots, j_d} = \sum_{j_1, \ldots, j_a} x_{j_1, \ldots, j_d}\, \omega_1^{j_1 k_1} \cdots \omega_a^{j_a k_a}. \tag{1}

Base. For a=0a = 0 the empty sum and product leave X(0)=xX^{(0)} = x, which is the array before the loop.

Step. Suppose (1) holds for a−1a - 1. In pass aa, line L5 visits each start once, line L6 copies the line into the buffer, line L7 transforms it, and line L8 writes it back to the same positions. By Lemma 1 the lines are disjoint, so the write of one line never changes an entry read by another line in the same pass, and every entry belongs to exactly one line. Fix the indices b≠ab \ne a; on that line the entry with ja=ij_a = i is X(a−1)X^{(a-1)} at (k1,…,ka−1,i,ja+1,…,jd)(k_1, \ldots, k_{a-1}, i, j_{a+1}, \ldots, j_d). By Lemma 2 the entry written back at ja=kaj_a = k_a is

∑i=0na−1Xk1,…,ka−1,i,ja+1,…,jd(a−1) ωaika=∑i∑j1,…,ja−1xj1,…,ja−1,i,ja+1,…,jd ω1j1k1⋯ωa−1ja−1ka−1 ωaika,\sum_{i=0}^{n_a - 1} X^{(a-1)}_{k_1, \ldots, k_{a-1}, i, j_{a+1}, \ldots, j_d}\, \omega_a^{i k_a} = \sum_{i} \sum_{j_1, \ldots, j_{a-1}} x_{j_1, \ldots, j_{a-1}, i, j_{a+1}, \ldots, j_d}\, \omega_1^{j_1 k_1} \cdots \omega_{a-1}^{j_{a-1} k_{a-1}}\, \omega_a^{i k_a},

using (1) for a−1a - 1. Renaming ii as jaj_a and using that finite sums in a commutative ring can be reordered, this is the right side of (1) for aa.

End. For a=da = d, (1) is the definition of XX, which proves correctness.

Operation count. In pass aa there are N/naN / n_a lines by Lemma 1, each costing nalg⁡nan_a \lg n_a additions and na2lg⁡na\frac{n_a}{2} \lg n_a multiplications by Lemma 2, so the pass costs Nlg⁡naN \lg n_a additions and N2lg⁡na\frac{N}{2} \lg n_a multiplications. Since N=∏anaN = \prod_a n_a, we have ∑alg⁡na=lg⁡N\sum_a \lg n_a = \lg N, and summing over aa gives Nlg⁡NN \lg N additions and N2lg⁡N\frac{N}{2} \lg N multiplications. Line L4 builds na/2n_a / 2 table entries; taken as successive powers, each costs at most one multiplication, so the tables add at most ∑ana/2≤dm/2\sum_a n_a / 2 \le d m / 2 multiplications. (The Python code instead evaluates each entry directly, by modular powering or from its exact angle over C\mathbb{C}, which is more accurate in floating point and does not change the asymptotic cost.) Lines L6 and L8 move NN entries per pass and do no ring operations.

Space. Apart from the array, the pass for axis aa holds the buffer ℓ\ell of nan_a entries, the table WW of na/2n_a / 2 entries and O(1)O(1) indices, and both are released before the next pass. The extra space is therefore at most 32m+O(1)\frac{3}{2} m + O(1) entries, and at least mm for the buffer of the longest axis, so it is Θ(m)\Theta(m). ■\blacksquare

Back to Multidimensional FFT