Recursive inverse Fermat-ring FFT (decimation in time) is correct within its cost
ProvedNLogN.dit_runsLet pT be a procedure index whose body is ditBody pT and let ; write . For every , every state , every list of integers and every , assume
- , and either or (so is a -th root of unity mod , as );
- every entry of is a canonical residue, ;
- stack
DXholds the items of (first entry on top) followed by ;DLhas on top,DEhas on top,RNhas andRFhas on top.
Then calling pT runs from to the state in which DX holds followed by , all other stacks unchanged:
Here ditZ is the reference recursive decimation-in-time transform: it transforms the two halves recursively with and combines them with butterflies whose twiddle factors are powers of , realised as shifts followed by reduction mod .
This is the inverse transform of the Schönhage–Strassen algorithm; with and it is applied once per recursion level, at cost .
Formalization Note. States are IState NS records with item stacks G : Fin NS → List Item (head = top), input pointer ip and output out; s.upd X L replaces stack X by L; ints A is the list of integer items of A. The named stacks (ARG, PRM, RN, RF, DX, DL, …) are fixed indices in Fin 32. IRuns I iprog p s s' c means that p executes from s to exactly s' with some cost , so costs are upper bounds; the program text iprog and input I are arbitrary unless constrained.
-- Schönhage–Strassen multitape-TM development (NLogN), generated by skeleton subtraction.
import Definitions.Def_IntMul_SS_Defs2
set_option autoImplicit false
set_option relaxedAutoImplicit false
set_option maxHeartbeats 1000000
open NLogN
open IntMul
variable {P : ℕ} {I : List Sym} {iprog : Fin P → IStmt NS P}
theorem NLogN.dit_runs (pT : Fin P) (hP : iprog pT = ditBody pT) (n : ℕ) (hn : 1 ≤ n) :
∀ j (s : IState NS) (B : List ℤ) (R LL LE LN LF : List Item) (E : ℕ),
B.length = 2 ^ j → (j = 0 ∨ 2 ^ j * E = 2 * n) → Canon (2 ^ n + 1) B →
s.G DX = ints B ++ R → s.G DL = .int (2 ^ j) :: LL → s.G DE = .int (2 ^ E) :: LE →
s.G RN = .int (2 ^ n) :: LN → s.G RF = .int (2 ^ n + 1) :: LF →
IRuns I iprog (.call pT) s (s.upd DX (ints (ditZ (2 ^ n + 1) n E j B) ++ R))
(ditCost n j) := by sorry