perf(Mux): shared selector decomposition and ±Y symmetry optimization in emulated MSM#1704
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR optimizes selector multiplexing and its use in emulated field arithmetic and GLV-based scalar multiplication to reduce redundant constraints and improve performance.
Changes:
- Add unchecked selector mux variants to reuse already-constrained selector bits.
- Optimize
selector.Muxandemulated.Field.Muxto avoid repeated binary decomposition work. - Exploit ±Y symmetry in GLV tables to replace 16-to-1 Y selection with 8-to-1 + conditional negation.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
std/selector/mux.go |
Adds BinaryMuxUnchecked / GeneralMuxUnchecked wrappers to skip redundant boolean assertions. |
std/selector/multiplexer.go |
Adds constant-selector fast path, n=2 specialization, and an “unchecked” recursive path for non-power-of-2 muxes. |
std/math/emulated/field_ops.go |
Reuses a single selector bit decomposition across all limbs and uses unchecked mux variants. |
std/algebra/emulated/sw_emulated/point.go |
Adds muxY8Signed and switches GLV loops to 8-to-1 Y mux + conditional negation. |
std/algebra/emulated/sw_bls12381/g2.go |
Adds muxE2Y8Signed for the same 8-to-1 + sign optimization in G2 GLV scalar mul. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ivokub
requested changes
Feb 17, 2026
Collaborator
ivokub
left a comment
There was a problem hiding this comment.
In general looks good. I can have a check if we can use MarkBoolean more efficiently to avoid redundant binary assertions.
ivokub
approved these changes
Feb 18, 2026
Collaborator
ivokub
left a comment
There was a problem hiding this comment.
Thanks for the fixes! Looks good now!
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.
Description
Optimizes the
Mux(multiplexer) function in the selector package and its usage across emulated field arithmetic and elliptic curve scalar multiplication.The optimizations consist of three key improvements:
1. Share binary decomposition across emulated field limbs
Previously,
emulated.Muxdecomposed the selector into bits independently for each limb (e.g., 6 limbs × 4 bits = 24 redundant boolean assertions for a 16-to-1 Mux). Now we decompose once and reuse across all limbs.BinaryMuxUncheckedandGeneralMuxUncheckedvariants that skip boolean assertions when bits are already constrained (e.g., frombits.ToBinary).Also:
inputs[sel]directly whenselis compile-time constantapi.Selectdirectly for 2-to-1 MuxFiles:
std/math/emulated/field_ops.go,std/selector/mux.goandstd/selector/multiplexer.go.2. Exploit ±Y symmetry in MSM
In GLV-based scalar multiplication, the 16 precomputed points satisfy
Y[i] = -Y[15-i]. This allows replacing a 16-to-1 Mux with an 8-to-1 Mux + conditional negation, saving constraints.Added
muxY8Signedhelper that selects from 8 Y-values and conditionally negates based on the MSB.Files:
std/algebra/emulated/sw_emulated/point.go,std/algebra/emulated/sw_bls12381/g2.goType of change
How has this been tested?
std/selectortests passstd/math/emulatedtests passstd/algebra/emulated/sw_emulatedtests passstd/algebra/emulated/sw_bls12381tests passstd/evmprecompilestests passHow has this been benchmarked?
SCS constraint count comparison:
Single Scalar Multiplication
EVM Precompiles
Checklist:
golangci-lintdoes not output errors locallyNote
Medium Risk
Touches low-level constraint-building and mux selection logic used broadly across circuits; while changes are performance-oriented, mistakes could cause unsound or failing constraints across many call sites.
Overview
Speeds up constraint generation for multiplexers and emulated scalar multiplication by reducing redundant selector constraints and leveraging GLV point symmetry.
selector.Muxnow short-circuits constant selectors, usesapi.Selectfor 2-way muxes, and replaces the previous bounded-compare check with a builder-levelMustBeLessOrEqCston the already-decomposed selector bits.emulated.Field.Muxis reworked to decomposeselinto bits once, reuse them across all limbs viaselector.BinaryMux, and pad/check bounds only for non-power-of-two input counts.Emulated GLV scalar-mul paths in
sw_emulated/point.goand BLS12-381G2replace 16-to-1 Y-coordinate muxing with an 8-to-1 mux plus conditional negation (muxY8Signed/muxE2Y8Signed), reflecting theY[i] = -Y[15-i]symmetry. Constraint builders (r1cs/scs) also skip adding trivially satisfiedMustBeLessOrEqCstconstraints when the compared bit is a constant zero;latest_stats.csvis updated accordingly.Written by Cursor Bugbot for commit de2cef3. This will update automatically on new commits. Configure here.