Reversible modular reduction — the complete single-step reduce circuit (ECDLP Phase 2, Stage S6.3a) #
Category: 1-Mathlib (CSD-free; staged as a Mathlib-upstream candidate).
S4 (ModReduce.lean) verified the comparison-as-carry-out primitive and the x ≥ N reduce value
(rippleCirc_modReduce_ge), but left the flag-controlled wrapper and the x < N branch as
documented cost, not as an exhibited circuit (ResourceBounds.modReduceToffoli is a documented
estimate, not derived from a reduce circuit). This module closes that residue: it exhibits and
proves the complete single-step modular reduction circuit, both branches, from already-verified
primitives only.
The circuit (modReduce) #
For x in register B with x < 2N (and x < 2ⁿ, N ≤ 2ⁿ):
modReduce L = rippleCirc L1 ++ [Gate.X flag] ++ cRippleCirc L2
- Step 1
rippleCirc L1(A1preset to2ⁿ − N,B, fresh carry chainC1): adds the complement constant, soB ← (x + 2ⁿ − N) mod 2ⁿ, andflag := C1 n(the carry-out) becomesdecide (N ≤ x)(rippleCirc_correct+rippleCirc_carryout). - Step 2
X flag: flips the flag todecide (x < N) = ¬ decide (N ≤ x). - Step 3
cRippleCirc L2(A2preset toN, sameB, second fresh carry chainC2,ctrl := flag, fresh ancillaanc): controlled add-back ofN, conditional onx < N(cRippleCirc_correct).
The arithmetic (verified in modReduce_correct):
x ≥ N: flag clears, no add-back; step-1 value(x + 2ⁿ − N) mod 2ⁿ = x − N = x mod N(usingN ≤ x < 2ⁿand S4'smod_eq_sub_of_le_of_lt_two_mul).x < N: flag sets; step-1 value isx + 2ⁿ − N(no wrap, sincex < N ≤ 2ⁿ), then+ N mod 2ⁿ = (x + 2ⁿ) mod 2ⁿ = x = x mod N.
What is NEW vs S4 #
S4's rippleCirc_modReduce_ge handled only the x ≥ N branch and no control — the reduce was
the bare adder, correct only when a subtract was actually needed. This module does both branches in
one reversible pass, with the comparison flag controlling the conditional add-back via S2's
cRippleCirc. So: comparison VERIFIED (S4), x ≥ N reduce VERIFIED (S4), and now the
flag-controlled wrapper + the x < N identity branch are exhibited circuits, VERIFIED (S6.3a) —
the documented residue of S4 §"Documented residue" is closed.
Honest cost #
modReduceCtrl_toffoli derives 2n + 8n = 10n Toffolis from the exhibited gate list (step-1 ripple
2n, the X flip 0, step-3 controlled ripple 8n via cRippleCirc_toffoli). This is heavier
than S4's documented estimate modReduceToffoli n = 4n: the controlled add-back is 8n (the
quantum×quantum overhead of S2, 4× the 2n of an uncontrolled add), not the ~2n an idealised
in-place subtract would suggest. That is the honest cost of a verified reduction (compare-and-
conditional-subtract, both branches, in the 2-control DSL) versus S4's documented uncontrolled-add
estimate.
Remaining residue (named, not built) #
- Cleanup / reversibility (S6.3b concern). The comparison flag
C1 nis left holdingdecide (x < N), the step-1 carry chainC1holds garbage, andC2/ancare restored clean bycRippleCircbutC1/flagare not uncomputed. The value correctness ofBholds regardless (modReduce_correct), but in-place reuse inside a multiply needs the standard recompute-and-uncompute of the flag and step-1 carries. Naming, not building, that uncompute pass here. - Full product reduction. A
2w-bit product (xup to~N²) is reduced by the multi-step / interleaved schedule that keeps the accumulator< 2Nand applies this primitive each step. This module is the single-step (x < 2N) primitive that schedule iterates; the full modular multiply is S6.3b.
A single-step modular-reduction layout on Fin m for n-bit registers. Bundles:
B— the data register (holdsx, overwritten withx mod N);A1— the step-1 constant register (preset to2ⁿ − N), with fresh carry chainC1(whose output wireC1 nis the comparison flag);A2— the step-3 constant register (preset toN), with a second fresh carry chainC2;anc— the shared clean ancilla for the controlled add-back.
The fields are pure wire geometry (pairwise disjointness + per-range bounded injectivity), mirroring
the RippleLayout/CRippleLayout discipline. The injectivity fields are bounded (< n for
registers, < n + 1 for carry chains) exactly as MulLayout/CMulLayout — an unbounded ℕ → Fin m
injectivity field is uninhabitable and would make the theorem vacuous.
Data register: holds
x, overwritten withx mod N.Step-1 constant register (preset to
2ⁿ − N).Step-1 carry chain;
C1 nis the comparison flag (the control of step 3).Step-3 constant register (preset to
N).Step-3 carry chain (distinct from
C1).- anc : Fin m
Shared clean ancilla for the controlled add-back.
Instances For
The single-step modular-reduction circuit. rippleCirc (add complement 2ⁿ − N, produce the
comparison flag) ++ [X flag] (flip flag to x < N) ++ cRippleCirc (controlled add-back of N).
Equations
Instances For
Frame: step-3 inputs survive steps 1 and 2 #
Step 1 (rippleCirc L.stepOne) touches only {A1 k, B k, C1 k} and step 2 (X (C1 n)) only
{C1 n}. The step-3 carry chain C2, constant A2, and ancilla anc are disjoint from those, so
their values pass through steps 1 + 2 unchanged.
The data-register window B is untouched by the flag flip (step 2): C1 n ≠ B j.
Steps 1 + 2 leave the step-3 carry chain C2 j at its initial value.
Steps 1 + 2 leave the step-3 constant register A2 j at its initial value.
Steps 1 + 2 leave the shared ancilla anc at its initial value.
Value correctness, both branches #
The complete single-step modular reduction — both branches, verified from the exhibited
circuit. For a disjoint-wire ModReduceLayout with the step-1 carry chain C1, the step-3 carry
chain C2, and the ancilla anc all initialised false, register A1 preset to 2ⁿ − N, register
A2 preset to N, and data B holding x with N ≤ 2ⁿ, x < 2ⁿ, x < 2N: the circuit
modReduce L leaves B holding x mod N.
Proof. Step 1 (rippleCirc_correct) writes (x + 2ⁿ − N) mod 2ⁿ to B and sets the flag
C1 n = decide (N ≤ x) (rippleCirc_carryout); step 2 flips it to decide (x < N); step 3
(cRippleCirc_correct) adds N back iff the flag is set. The two branches:
x ≥ N(flag clear): step-1 value(x + 2ⁿ − N) mod 2ⁿ = x − N(N ≤ x < 2ⁿ), andx − N = x mod N(mod_eq_sub_of_le_of_lt_two_mul); add-back skipped.x < N(flag set): step-1 valuex + 2ⁿ − N(no wrap,x < N ≤ 2ⁿ), then+ N mod 2ⁿ = (x + 2ⁿ) mod 2ⁿ = x = x mod N.
This closes S4's documented residue: comparison + conditional-subtract + both branches, derived from circuits, not documented.
The reducer output is a genuine residue in [0, N). A direct corollary of
modReduce_correct and Nat.mod_lt: the property a modular reducer must have.
Derived cost #
Derived Toffoli cost of the single-step reduce circuit: 10n Toffolis, from the exhibited gate
list. Step 1 (rippleCirc) is 2n (rippleAdder_toffoli-style, here read via the same ripple count),
the X flip is 0, and step 3 (cRippleCirc) is 8n (cRippleCirc_toffoli); composed through the
Tranche-1 additivity cost_comp_toffoli_count. This is heavier than S4's documented
modReduceToffoli n = 4n: the verified controlled add-back costs 8n (the quantum×quantum
overhead of S2, 4× an uncontrolled add), the honest price of an exhibited both-branch reduction.
Non-vacuity witness #
A concrete 2-bit reduce layout on Fin 13:
- data
B → {0,1}, step-1 constantA1 → {2,3}, step-1 carry chainC1 → {4,5,6}, - step-3 constant
A2 → {7,8}, step-3 carry chainC2 → {9,10,11}, ancilla12.
This exhibits that ModReduceLayout is inhabited (the bounded-injectivity bundle is satisfiable),
so the headlines are not vacuously quantified. The concrete computations below run the reducer on
n = 2, N = 3 at two fully-specified input states, checking x = 3 ↦ 0 (the x ≥ N subtract
branch) and x = 2 ↦ 2 (the x < N identity branch). [The spec's illustrative x = 5 ↦ 2 needs
n = 3: 5 < 2³ = 8; at n = 2, x < 2² = 4, so 5 is not representable in two wires.]
A concrete 2-bit reduce layout on Fin 13.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Interface lemmas (CONVENTIONS §9.1, F1): the wire assignments of the concrete layout, one lemma per field.
modReduceLayout2's data-register wires.
modReduceLayout2's step-1 constant-register wires.
modReduceLayout2's step-1 carry-chain wires.
modReduceLayout2's step-3 constant-register wires.
modReduceLayout2's step-3 carry-chain wires.
modReduceLayout2's ancilla wire.
The hypotheses of modReduce_correct hold at modReduceState2 b0 b1 (carries/ancilla clear,
A1 = 1, A2 = 3), for any data bits. The regValRange register-value preconditions are concrete
sums, discharged by decide.