Skip to content

Batched group law + MontgomeryField: match/beat smalljac (and fix #2's numbers) - #3

Merged
salindne merged 2 commits into
mainfrom
batched-group-law
Jun 18, 2026
Merged

Batched group law + MontgomeryField: match/beat smalljac (and fix #2's numbers)#3
salindne merged 2 commits into
mainfrom
batched-group-law

Conversation

@salindne

@salindne salindne commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Builds on #2 (merged). The "chase smalljac" follow-up. Three commits.

1. Batched group law — Montgomery's trick (feat)

field::batch_invert + a two-phase split of the generic deg-2 add/double (deg2_add_pre/post, deg2_dbl_pre/post) + add_batch/double_batch, amortizing one inversion across a batch. Mirrors smalljac's ctx + ff_parallel_invert. Test asserts batched == scalar, element-for-element, on 1000 inputs.

2. Correct the smalljac comparison merged in #2 ⚠️

PR #2's harness left f[4] ≠ 0, so hecurve_g2_compose silently used smalljac's slow generic Cantor path — those numbers (now on main) were wrong. Fixed f[4]=0 (the depressed quintic this crate's not_char2 uses), added a batched harness + raw field-op timing.

3. MontgomeryField<P> — closes the gap (feat)

A second Field backend: Montgomery REDC multiply (no division) + binary-GCD inversion. Drops into the same generic formulas. Verified identical to PrimeField (10k random ops at 56-bit; exhaustive inversion over F₆₅₅₂₁).

Result — 56-bit prime, same machine (ns/op)

operation PrimeField MontgomeryField smalljac
add, scalar 673 163 190
double, scalar 691 168 210
add, batched (N=1024) 348 40 48
double, batched (N=1024) 384 46 54

With MontgomeryField the genus-2 group law is ~4× faster than PrimeField and competitive with / faster than smalljac in every mode. This pins the earlier gap entirely on the field layer (the formulas + batched driver were already sound; op counts match the literature): inversion 529 → 109 ns (smalljac 157), multiply 8.2 → ~0.9 ns. Batching is orthogonal and helps both backends.

Checks

cargo fmt --check, cargo +stable clippy --all-targets -- -D warnings, cargo test --release (230 + doctest), cargo bench --no-run, cargo doc -D warnings all green locally.

Harness + arm64 build notes in benches/smalljac-compare/ (smalljac/ff_poly not vendored — GPL).

salindne added 2 commits June 18, 2026 16:03
Add field::batch_invert (simultaneous inversion: one field inversion + ~3(n-1)
mults for a whole slice) and, for g2::ramified::not_char2, a two-phase split of
the generic degree-2 add/double (deg2_add_pre/post, deg2_dbl_pre/post) plus
add_batch/double_batch drivers that amortize the single inversion across a batch
via batch_invert. This mirrors smalljac's hecurve_ctx_t + ff_parallel_invert
path and is the throughput-oriented group law used by generic-group order
algorithms.

A test asserts the batched results are identical, element for element, to the
scalar add/double on 1000 random inputs. Benches report amortized ns/op at a
56-bit and 16-bit prime; field-op benches gain a 56-bit instantiation.
The comparison harness left f[4] != 0, which makes hecurve_g2_compose silently
fall back to smalljac's slow generic Cantor path (~5-8x slower) instead of its
fast explicit formula — so the earlier scalar numbers measured Cantor, not the
group law. Fix f[4]=0 (matching this crate's not_char2 curve form), add a
batched mode (ctx + ff_parallel_invert) and raw field-op timing.

Corrected, same-machine results (ns/op): at a 56-bit prime smalljac add is
~190 (scalar) / ~48 (batched) vs this crate's ~673 / ~348. smalljac is faster
in every cell; the gap is the field-arithmetic layer (Montgomery vs u128
mul+mod and extended-Euclidean inversion: M 4.5 vs 8.2 ns, I 157 vs 529 ns),
not the genus-2 formulas (op counts match). README comparison section rewritten
accordingly.
@salindne
salindne merged commit e4a118a into main Jun 18, 2026
4 checks passed
@salindne salindne changed the title Batched group law + correct the smalljac comparison (f4=0) Batched group law + MontgomeryField: match/beat smalljac (and fix #2's numbers) Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant