Skip to content

Commit ed1f377

Browse files
committed
use msm_naive or msm_pippenger based on the msm size
1 parent 4ea9991 commit ed1f377

File tree

2 files changed

+10
-11
lines changed

2 files changed

+10
-11
lines changed

benches/msm.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn bench_msm_curve25519_dalek(c: &mut Criterion) {
1212
let mut group = c.benchmark_group("MSM curve25519-dalek RistrettoPoint");
1313
let mut rng = thread_rng();
1414

15-
for size in [16, 64, 256, 1024].iter() {
15+
for size in [1, 2, 4, 8, 16, 64, 256, 1024].iter() {
1616
let scalars: Vec<Scalar> = (0..*size).map(|_| Scalar::random(&mut rng)).collect();
1717
let bases: Vec<RistrettoPoint> = (0..*size)
1818
.map(|_| RistrettoPoint::random(&mut rng))
@@ -31,7 +31,7 @@ fn bench_msm_k256(c: &mut Criterion) {
3131
let mut group = c.benchmark_group("MSM k256 ProjectivePoint");
3232
let mut rng = thread_rng();
3333

34-
for size in [16, 64, 256, 1024].iter() {
34+
for size in [1, 2, 4, 8, 16, 64, 256, 1024].iter() {
3535
let scalars: Vec<Scalar> = (0..*size).map(|_| Scalar::random(&mut rng)).collect();
3636
let bases: Vec<ProjectivePoint> = (0..*size)
3737
.map(|_| ProjectivePoint::random(&mut rng))
@@ -50,7 +50,7 @@ fn bench_msm_p256(c: &mut Criterion) {
5050
let mut group = c.benchmark_group("MSM p256 ProjectivePoint");
5151
let mut rng = thread_rng();
5252

53-
for size in [16, 64, 256, 1024].iter() {
53+
for size in [1, 2, 4, 8, 16, 64, 256, 1024].iter() {
5454
let scalars: Vec<Scalar> = (0..*size).map(|_| Scalar::random(&mut rng)).collect();
5555
let bases: Vec<ProjectivePoint> = (0..*size)
5656
.map(|_| ProjectivePoint::random(&mut rng))

src/group/msm.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ impl<G: PrimeGroup> VariableMultiScalarMul for G {
6464
fn msm(scalars: &[Self::Scalar], bases: &[Self::Point]) -> Self {
6565
assert_eq!(scalars.len(), bases.len());
6666

67-
if scalars.is_empty() {
68-
return Self::identity();
69-
}
70-
71-
// NOTE: We use the naive implementation here as it is signficantly faster in practice for
72-
// curve25519-dalek, which implements SIMD for scalar multiplication.
67+
// NOTE: Based on the msm benchmark in this repo, msm_pippenger provides improvements over
68+
// msm_naive past a small constant size, but is significantly slower for very small MSMs.
7369
// TODO: Support specialized MSM selection based on the group.
74-
msm_naive(bases, scalars)
70+
match scalars.len() {
71+
0 => Self::identity(),
72+
1..16 => msm_naive(bases, scalars),
73+
16.. => msm_pippenger(bases, scalars),
74+
}
7575
}
7676
}
7777

@@ -82,7 +82,6 @@ fn msm_naive<G: PrimeGroup>(bases: &[G], scalars: &[G::Scalar]) -> G {
8282

8383
/// An MSM implementation that employ's Pippenger's algorithm and works for all groups that
8484
/// implement `PrimeGroup`.
85-
#[expect(dead_code)]
8685
fn msm_pippenger<G: PrimeGroup>(bases: &[G], scalars: &[G::Scalar]) -> G {
8786
let c = ln_without_floats(scalars.len());
8887
let num_bits = <G::Scalar as PrimeField>::NUM_BITS as usize;

0 commit comments

Comments
 (0)