── Root table #
theorem
ensure_roots_base_case
(n : ℕ)
(hN : 0 < n)
(v : Vector UInt32 n)
(K j f : ℕ)
(hlen_K : 2 ^ (K + 1) ≤ n)
(hj : j < 2 ^ K)
(hK63 : K < 63)
(h_half : ((2 ^ (K + 1)).toUInt64 / 2).toNat < n)
(hlt : 2 ^ K + j < n)
:
have wm := toMont (powModU64 primRoot ((mod64 - 1) / (2 ^ (K + 1)).toUInt64) mod64).toUInt32;
have vr :=
rootsInner wm ((2 ^ (K + 1)).toUInt64 / 2).toNat (((2 ^ (K + 1)).toUInt64 / 2).toNat - 1) 0
(v.set ((2 ^ (K + 1)).toUInt64 / 2).toNat montR1 h_half);
have res := ensureRoots.outer n vr (2 ^ (K + 2)).toUInt64 hN f;
res[2 ^ K + j].toNat = (primRoot.toNat ^ ((mod64.toNat - 1) / 2 ^ (K + 1)) % mod64.toNat) ^ j * montR1.toNat % mod64.toNat
The s = K base step of ensure_roots_outer_inv: after one outer-loop iteration at level K, followed by any number of further iterations, position 2^K+j holds (w^j · montR1) % mod64.