Batched group law + MontgomeryField: match/beat smalljac (and fix #2's numbers) - #3
Merged
Conversation
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.
This was referenced Jun 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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'sctx+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, sohecurve_g2_composesilently used smalljac's slow generic Cantor path — those numbers (now onmain) were wrong. Fixedf[4]=0(the depressed quintic this crate'snot_char2uses), added a batched harness + raw field-op timing.3.
MontgomeryField<P>— closes the gap (feat)A second
Fieldbackend: Montgomery REDC multiply (no division) + binary-GCD inversion. Drops into the same generic formulas. Verified identical toPrimeField(10k random ops at 56-bit; exhaustive inversion over F₆₅₅₂₁).Result — 56-bit prime, same machine (ns/op)
PrimeFieldMontgomeryFieldWith
MontgomeryFieldthe genus-2 group law is ~4× faster thanPrimeFieldand 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 warningsall green locally.Harness + arm64 build notes in
benches/smalljac-compare/(smalljac/ff_poly not vendored — GPL).