These are the human proofs of Goertzel algorithm, at full length.
GOERTZEL returns X_k with n + 1 multiplications and 2n + 1 additions, and its rounding error is at most (13u + η + μ)(n + 2) M ‖x‖_1 to first order full
This proof shows: correctness, complexity.
Statement. Let R be a commutative ring, n≥1, ω∈R with ωn=1, k an integer, z=ω−k and c=z+z−1. For every x∈Rn, GOERTZEL returns Xk=∑j=0n−1xjωjk, using exactly n+1 multiplications and 2n+1 additions and subtractions in R, besides computing z and c. Over C with ω=e−2πi/n, in floating-point arithmetic with unit roundoff u, if the constants are computed with ∣c^−c∣≤η and ∣z^−z∣≤μ, then to first order in u (dropping terms of order u2, uη and uμ)
The sequence. Let s−2=s−1=0 and sj=xj+csj−1−sj−2 for 0≤j<n. By induction on the loop at line L4, after the iteration for j the variables hold s1=sj and s2=sj−1: before the loop they hold s−1 and s−2 (line L3), and lines L5 and L6 compute sj from them and shift. So line L7 returns zsn−1−sn−2.
Lemma 1 (Horner). For j≥0 let yj=∑i=0jxizj−i. Then yj=sj−z−1sj−1. Proof. For j=0: y0=x0=s0−z−1s−1. If it holds for j, then yj+1=zyj+xj+1=zsj−sj−1+xj+1, using zz−1=1, while sj+1−z−1sj=xj+1+(c−z−1)sj−sj−1=xj+1+zsj−sj−1, using c−z−1=z. □
Correctness. Since ωn=1, zn=ω−kn=1, so ωjk=z−j=zn−j=z⋅zn−1−j. Hence Xk=z∑jxjzn−1−j=zyn−1=zsn−1−sn−2 by Lemma 1, which is the value returned. Over C, z=e2πik/n and c=2cos(2πk/n) is real.
Operation count. Each of the n iterations of line L5 does one multiplication c⋅s1, one addition and one subtraction; line L6 only moves values. Line L7 does one multiplication and one subtraction. The total is n+1 multiplications and 2n+1 additions and subtractions, for every input. The space is the three variables s,s1,s2 and the two constants, Θ(1).
Lemma 2 (the propagation factors). Let U−1=0, U0=1 and Um=cUm−1−Um−2 for m≥1. Then (a) zUm−Um−1=zm+1 for m≥0; (b) sj=∑i=0jUj−ixi; (c) over C with c=2cosθ, ∣Um∣≤min(m+1,1/∣sinθ∣). Proof. (a) For m=0 it reads z=z. For m≥1, zUm−Um−1=(zc−1)Um−1−zUm−2, and zc−1=z2, so this is z(zUm−1−Um−2)=z⋅zm by induction. (b) Both sides satisfy the recurrence tj=xj+ctj−1−tj−2 with t−1=t−2=0, by linearity. (c) Um is the Chebyshev polynomial of the second kind at cosθ, and Um(cosθ)=sin((m+1)θ)/sinθ when sinθ=0 (this satisfies the same recurrence, by sin((m+1)θ)+sin((m−1)θ)=2cosθsin(mθ)), which gives the bound 1/∣sinθ∣. Also Um=∑r=0mei(m−2r)θ (both sides are 1 and 2cosθ for m=0,1 and satisfy the recurrence, since multiplying the sum for m−1 by eiθ+e−iθ gives the sums for m and m−2), so ∣Um∣≤m+1. □
By (b) and (c), with θ=2πk/n and j≤n−1, ∣sj∣≤M∥x∥1.
The rounding errors of the loop. We use the standard model fl(a∘b)=(a∘b)(1+δ), ∣δ∣≤u, for real operations. Since c^ is real, each operation of line L5 acts on the real and imaginary parts separately. For one real component, s^=fl(fl(x+fl(c^s^1))−s^2) equals x+c^s^1−s^2+e with ∣e∣≤3u(∣x∣+∣c^s^1∣+∣s^2∣) to first order. Adding the bounds of the two components and using ∣ar∣+∣ai∣≤2∣a∣ gives, for the complex values,
to first order, where fj also absorbs (c^−c)s^j−1 and we used ∣c^∣≤2+η. The differences dj=s^j−sj satisfy dj=cdj−1−dj−2+fj with d−1=d−2=0, so by Lemma 2(b), dj=∑i≤jUj−ifi. Then by Lemma 2(a),
and since ∣z∣=1 its modulus is at most ∑i∣fi∣≤32u∥x∥1+(92u+η)nM∥x∥1, using ∣sj∣≤M∥x∥1.
The rounding errors of line L7. For a complex product, fl(ab)=ab(1+δ) with ∣δ∣≤2γ2=22u to first order (Higham, Lemma 3.5), and a complex subtraction has relative error at most u. So X^k=(z^s^n−1(1+δ1)−s^n−2)(1+δ2), and X^k−(zs^n−1−s^n−2) has modulus at most μ∣sn−1∣+22u∣sn−1∣+u∣Xk∣ to first order, which is at most (μ+22u)M∥x∥1+u∥x∥1.
The bound. Adding the two parts,
∣X^k−Xk∣≤[(92u+η)nM+(32+1)u+(22u+μ)M]∥x∥1.
Now 92<13, and since M≥1, (32+1)u+(22u+μ)M≤(8.1u+μ)M≤2(13u+μ)M. So the right side is at most (13u+η+μ)(n+2)M∥x∥1. ■
Remark. The implementation computes z^ by cmath.exp and c^=2Rez^, so η≤2μ; the tests assume μ≤2u for the library exponential, hence η+μ≤6u, and use the constant 20≥13+7.