FM post-processing: untwist, lift to signed coefficients and carry into M-bit digits
ProvedNLogN.fmPost_runsLet , , and with ; write and . Let be a list of canonical residues mod . Assume DX holds (first entry on top) over , and the rulers on DL, on W2, on HB, on RM, on RQ, on RN, on RF. Let
where maps to (untwisting, division by via , and lifting to the symmetric range), and propagates carries, producing digits and final carry . Then fmPost runs from to the state where DX is , the digits are pushed on DG in reverse order (last on top) and is pushed on CY, with cost at most
Applied to the inverse FFT output, the lifted coefficients are exactly the negacyclic convolution of the input pieces (ss_lift); this step turns them into base- digits for recombination.
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.fmPost_runs (s : IState NS) (n M Q k : ℕ) (D : List ℤ)
(RX LL L2 LH LM LQ LN LF : List Item)
(hn : 1 ≤ n) (hM1 : 1 ≤ M) (hM : M ≤ n) (hKQ : 2 ^ k * Q = n) (hk : k + 1 ≤ n)
(hDl : D.length = 2 ^ k) (hD : Canon (2 ^ n + 1) D)
(hX : s.G DX = ints D ++ RX) (hDL : s.G DL = .int (2 ^ k) :: LL)
(h2 : s.G W2 = .int (2 ^ (n - k)) :: L2) (hH : s.G HB = .int (2 ^ (n - 1)) :: LH)
(hRM : s.G RM = .int (2 ^ M) :: LM) (hRQ : s.G RQ = .int (2 ^ Q) :: LQ)
(hN : s.G RN = .int (2 ^ n) :: LN) (hF : s.G RF = .int (2 ^ n + 1) :: LF) :
IRuns I iprog fmPost s
(((s.upd DX RX).upd DG ((ints (carZ M (liftL n k Q (2 ^ k) D) 0).1).reverse ++ s.G DG)).upd
CY (.int (carZ M (liftL n k Q (2 ^ k) D) 0).2 :: s.G CY))
(2 ^ k * (60000 * (n + 3) + 30) + 2000 * (n + 3)) := by sorry