2018-03-26 00:10:30 +00:00
|
|
|
#![allow(non_snake_case)]
|
|
|
|
|
|
2026-01-25 00:29:05 +00:00
|
|
|
use getrandom::SysRng;
|
|
|
|
|
use rand_core::{Rng, UnwrapErr};
|
2018-03-26 00:10:30 +00:00
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
use criterion::{
|
2025-07-07 15:52:25 +00:00
|
|
|
BatchSize, BenchmarkGroup, BenchmarkId, Criterion, criterion_main, measurement::Measurement,
|
2023-01-31 08:37:03 +00:00
|
|
|
};
|
2025-07-05 20:01:26 +00:00
|
|
|
#[cfg(feature = "digest")]
|
|
|
|
|
use sha2::Sha512;
|
2018-03-26 00:10:30 +00:00
|
|
|
|
|
|
|
|
use curve25519_dalek::constants;
|
|
|
|
|
use curve25519_dalek::scalar::Scalar;
|
|
|
|
|
|
2018-04-04 17:16:32 +00:00
|
|
|
static BATCH_SIZES: [usize; 5] = [1, 2, 4, 8, 16];
|
2018-03-26 00:10:30 +00:00
|
|
|
static MULTISCALAR_SIZES: [usize; 13] = [1, 2, 4, 8, 16, 32, 64, 128, 256, 384, 512, 768, 1024];
|
|
|
|
|
|
|
|
|
|
mod edwards_benches {
|
|
|
|
|
use super::*;
|
2019-10-05 19:02:08 +00:00
|
|
|
|
2018-05-02 21:54:46 +00:00
|
|
|
use curve25519_dalek::edwards::EdwardsPoint;
|
2018-03-26 00:10:30 +00:00
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn compress<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2018-03-26 00:10:30 +00:00
|
|
|
let B = &constants::ED25519_BASEPOINT_POINT;
|
2019-01-24 21:29:28 +00:00
|
|
|
c.bench_function("EdwardsPoint compression", move |b| b.iter(|| B.compress()));
|
2018-03-26 00:10:30 +00:00
|
|
|
}
|
|
|
|
|
|
2025-05-28 04:09:49 +00:00
|
|
|
#[cfg(feature = "alloc")]
|
|
|
|
|
fn compress_batch<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
|
|
|
|
for batch_size in BATCH_SIZES {
|
|
|
|
|
c.bench_with_input(
|
|
|
|
|
BenchmarkId::new("Batch EdwardsPoint compression", batch_size),
|
|
|
|
|
&batch_size,
|
|
|
|
|
|b, &size| {
|
2026-01-25 00:29:05 +00:00
|
|
|
let mut rng = UnwrapErr(SysRng);
|
2025-05-28 04:09:49 +00:00
|
|
|
let points: Vec<EdwardsPoint> =
|
|
|
|
|
(0..size).map(|_| EdwardsPoint::random(&mut rng)).collect();
|
2025-12-19 23:04:32 +00:00
|
|
|
b.iter(|| EdwardsPoint::compress_batch_alloc(&points));
|
2025-05-28 04:09:49 +00:00
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn decompress<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2018-03-26 00:10:30 +00:00
|
|
|
let B_comp = &constants::ED25519_BASEPOINT_COMPRESSED;
|
|
|
|
|
c.bench_function("EdwardsPoint decompression", move |b| {
|
|
|
|
|
b.iter(|| B_comp.decompress().unwrap())
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn consttime_fixed_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2018-07-17 17:53:02 +00:00
|
|
|
let s = Scalar::from(897987897u64).invert();
|
2018-03-26 00:10:30 +00:00
|
|
|
c.bench_function("Constant-time fixed-base scalar mul", move |b| {
|
2023-01-20 17:55:32 +00:00
|
|
|
b.iter(|| EdwardsPoint::mul_base(&s))
|
2018-03-26 00:10:30 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn consttime_variable_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2018-03-26 00:10:30 +00:00
|
|
|
let B = &constants::ED25519_BASEPOINT_POINT;
|
2018-07-17 17:53:02 +00:00
|
|
|
let s = Scalar::from(897987897u64).invert();
|
2018-03-26 00:10:30 +00:00
|
|
|
c.bench_function("Constant-time variable-base scalar mul", move |b| {
|
2019-10-05 19:02:08 +00:00
|
|
|
b.iter(|| B * s)
|
2018-03-26 00:10:30 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn vartime_double_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2018-03-26 00:10:30 +00:00
|
|
|
c.bench_function("Variable-time aA+bB, A variable, B fixed", |bench| {
|
2026-01-25 00:29:05 +00:00
|
|
|
let mut rng = UnwrapErr(SysRng);
|
2023-01-20 17:55:32 +00:00
|
|
|
let A = EdwardsPoint::mul_base(&Scalar::random(&mut rng));
|
2019-02-14 15:59:45 +00:00
|
|
|
bench.iter_batched(
|
|
|
|
|
|| (Scalar::random(&mut rng), Scalar::random(&mut rng)),
|
|
|
|
|
|(a, b)| EdwardsPoint::vartime_double_scalar_mul_basepoint(&a, &A, &b),
|
|
|
|
|
BatchSize::SmallInput,
|
|
|
|
|
);
|
2018-03-26 00:10:30 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-26 18:51:39 +00:00
|
|
|
#[cfg(feature = "digest")]
|
|
|
|
|
fn encode_to_curve<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2026-01-25 00:29:05 +00:00
|
|
|
let mut rng = UnwrapErr(SysRng);
|
2025-08-26 18:51:39 +00:00
|
|
|
|
|
|
|
|
let mut msg = [0u8; 32];
|
|
|
|
|
let mut domain_sep = [0u8; 32];
|
|
|
|
|
rng.fill_bytes(&mut msg);
|
|
|
|
|
rng.fill_bytes(&mut domain_sep);
|
|
|
|
|
|
|
|
|
|
c.bench_function(
|
|
|
|
|
"Elligator2 encode to curve (SHA-512, input size 32 bytes)",
|
|
|
|
|
|b| b.iter(|| EdwardsPoint::encode_to_curve::<Sha512>(&[&msg], &[&domain_sep])),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-05 20:01:26 +00:00
|
|
|
#[cfg(feature = "digest")]
|
|
|
|
|
fn hash_to_curve<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2026-01-25 00:29:05 +00:00
|
|
|
let mut rng = UnwrapErr(SysRng);
|
2025-07-05 20:01:26 +00:00
|
|
|
|
|
|
|
|
let mut msg = [0u8; 32];
|
|
|
|
|
let mut domain_sep = [0u8; 32];
|
|
|
|
|
rng.fill_bytes(&mut msg);
|
|
|
|
|
rng.fill_bytes(&mut domain_sep);
|
|
|
|
|
|
|
|
|
|
c.bench_function(
|
|
|
|
|
"Elligator2 hash to curve (SHA-512, input size 32 bytes)",
|
|
|
|
|
|b| b.iter(|| EdwardsPoint::hash_to_curve::<Sha512>(&[&msg], &[&domain_sep])),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
pub(crate) fn edwards_benches() {
|
|
|
|
|
let mut c = Criterion::default();
|
|
|
|
|
let mut g = c.benchmark_group("edwards benches");
|
|
|
|
|
|
|
|
|
|
compress(&mut g);
|
|
|
|
|
decompress(&mut g);
|
2025-05-28 04:09:49 +00:00
|
|
|
#[cfg(feature = "alloc")]
|
|
|
|
|
compress_batch(&mut g);
|
2023-01-31 08:37:03 +00:00
|
|
|
consttime_fixed_base_scalar_mul(&mut g);
|
|
|
|
|
consttime_variable_base_scalar_mul(&mut g);
|
|
|
|
|
vartime_double_base_scalar_mul(&mut g);
|
2025-08-26 18:51:39 +00:00
|
|
|
encode_to_curve(&mut g);
|
2025-07-05 20:01:26 +00:00
|
|
|
hash_to_curve(&mut g);
|
2019-01-24 21:29:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mod multiscalar_benches {
|
|
|
|
|
use super::*;
|
2019-10-05 19:02:08 +00:00
|
|
|
|
2019-01-24 21:29:28 +00:00
|
|
|
use curve25519_dalek::edwards::EdwardsPoint;
|
2019-02-14 15:59:45 +00:00
|
|
|
use curve25519_dalek::edwards::VartimeEdwardsPrecomputation;
|
2019-01-24 21:29:28 +00:00
|
|
|
use curve25519_dalek::traits::MultiscalarMul;
|
|
|
|
|
use curve25519_dalek::traits::VartimeMultiscalarMul;
|
2019-02-14 15:59:45 +00:00
|
|
|
use curve25519_dalek::traits::VartimePrecomputedMultiscalarMul;
|
|
|
|
|
|
|
|
|
|
fn construct_scalars(n: usize) -> Vec<Scalar> {
|
2026-01-25 00:29:05 +00:00
|
|
|
let mut rng = UnwrapErr(SysRng);
|
2019-02-14 15:59:45 +00:00
|
|
|
(0..n).map(|_| Scalar::random(&mut rng)).collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn construct_points(n: usize) -> Vec<EdwardsPoint> {
|
2026-01-25 00:29:05 +00:00
|
|
|
let mut rng = UnwrapErr(SysRng);
|
2019-02-14 15:59:45 +00:00
|
|
|
(0..n)
|
2023-01-20 17:55:32 +00:00
|
|
|
.map(|_| EdwardsPoint::mul_base(&Scalar::random(&mut rng)))
|
2019-02-14 15:59:45 +00:00
|
|
|
.collect()
|
|
|
|
|
}
|
2019-01-24 21:29:28 +00:00
|
|
|
|
2021-03-26 16:18:18 +00:00
|
|
|
fn consttime_multiscalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
|
|
|
|
for multiscalar_size in &MULTISCALAR_SIZES {
|
|
|
|
|
c.bench_with_input(
|
|
|
|
|
BenchmarkId::new(
|
|
|
|
|
"Constant-time variable-base multiscalar multiplication",
|
|
|
|
|
*multiscalar_size,
|
|
|
|
|
),
|
|
|
|
|
&multiscalar_size,
|
|
|
|
|
|b, &&size| {
|
|
|
|
|
let points = construct_points(size);
|
|
|
|
|
// This is supposed to be constant-time, but we might as well
|
|
|
|
|
// rerandomize the scalars for every call just in case.
|
|
|
|
|
b.iter_batched(
|
|
|
|
|
|| construct_scalars(size),
|
|
|
|
|
|scalars| EdwardsPoint::multiscalar_mul(&scalars, &points),
|
|
|
|
|
BatchSize::SmallInput,
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
2018-03-26 00:10:30 +00:00
|
|
|
}
|
|
|
|
|
|
2021-03-26 16:18:18 +00:00
|
|
|
fn vartime_multiscalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
|
|
|
|
for multiscalar_size in &MULTISCALAR_SIZES {
|
|
|
|
|
c.bench_with_input(
|
|
|
|
|
BenchmarkId::new(
|
|
|
|
|
"Variable-time variable-base multiscalar multiplication",
|
|
|
|
|
*multiscalar_size,
|
|
|
|
|
),
|
|
|
|
|
&multiscalar_size,
|
|
|
|
|
|b, &&size| {
|
|
|
|
|
let points = construct_points(size);
|
|
|
|
|
// Rerandomize the scalars for every call to prevent
|
|
|
|
|
// false timings from better caching (e.g., the CPU
|
|
|
|
|
// cache lifts exactly the right table entries for the
|
|
|
|
|
// benchmark into the highest cache levels).
|
|
|
|
|
b.iter_batched(
|
|
|
|
|
|| construct_scalars(size),
|
|
|
|
|
|scalars| EdwardsPoint::vartime_multiscalar_mul(&scalars, &points),
|
|
|
|
|
BatchSize::SmallInput,
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
2018-03-26 00:10:30 +00:00
|
|
|
}
|
|
|
|
|
|
2021-03-26 16:18:18 +00:00
|
|
|
fn vartime_precomputed_pure_static<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
|
|
|
|
for multiscalar_size in &MULTISCALAR_SIZES {
|
|
|
|
|
c.bench_with_input(
|
|
|
|
|
BenchmarkId::new(
|
|
|
|
|
"Variable-time fixed-base multiscalar multiplication",
|
2022-12-04 08:40:51 +00:00
|
|
|
multiscalar_size,
|
2021-03-26 16:18:18 +00:00
|
|
|
),
|
|
|
|
|
&multiscalar_size,
|
|
|
|
|
move |b, &&total_size| {
|
|
|
|
|
let static_size = total_size;
|
|
|
|
|
|
|
|
|
|
let static_points = construct_points(static_size);
|
2023-08-27 18:47:12 +00:00
|
|
|
let precomp = VartimeEdwardsPrecomputation::new(static_points);
|
2021-03-26 16:18:18 +00:00
|
|
|
// Rerandomize the scalars for every call to prevent
|
|
|
|
|
// false timings from better caching (e.g., the CPU
|
|
|
|
|
// cache lifts exactly the right table entries for the
|
|
|
|
|
// benchmark into the highest cache levels).
|
|
|
|
|
b.iter_batched(
|
|
|
|
|
|| construct_scalars(static_size),
|
2023-08-27 18:47:12 +00:00
|
|
|
|scalars| precomp.vartime_multiscalar_mul(scalars),
|
2021-03-26 16:18:18 +00:00
|
|
|
BatchSize::SmallInput,
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-02-14 15:16:20 +00:00
|
|
|
}
|
|
|
|
|
|
2021-03-26 16:18:18 +00:00
|
|
|
fn vartime_precomputed_helper<M: Measurement>(
|
|
|
|
|
c: &mut BenchmarkGroup<M>,
|
|
|
|
|
dynamic_fraction: f64,
|
|
|
|
|
) {
|
|
|
|
|
for multiscalar_size in &MULTISCALAR_SIZES {
|
2021-08-17 00:14:00 +00:00
|
|
|
let bench_id = BenchmarkId::new(
|
|
|
|
|
"Variable-time mixed-base",
|
2022-10-28 21:00:24 +00:00
|
|
|
format!(
|
|
|
|
|
"(size: {:?}), ({:.0}pct dyn)",
|
|
|
|
|
multiscalar_size,
|
|
|
|
|
100.0 * dynamic_fraction
|
|
|
|
|
),
|
2021-08-17 00:14:00 +00:00
|
|
|
);
|
|
|
|
|
|
2022-10-28 21:00:24 +00:00
|
|
|
c.bench_with_input(bench_id, &multiscalar_size, move |b, &&total_size| {
|
|
|
|
|
let dynamic_size = ((total_size as f64) * dynamic_fraction) as usize;
|
|
|
|
|
let static_size = total_size - dynamic_size;
|
|
|
|
|
|
|
|
|
|
let static_points = construct_points(static_size);
|
|
|
|
|
let dynamic_points = construct_points(dynamic_size);
|
2023-08-27 18:47:12 +00:00
|
|
|
let precomp = VartimeEdwardsPrecomputation::new(static_points);
|
2022-10-28 21:00:24 +00:00
|
|
|
// Rerandomize the scalars for every call to prevent
|
|
|
|
|
// false timings from better caching (e.g., the CPU
|
|
|
|
|
// cache lifts exactly the right table entries for the
|
|
|
|
|
// benchmark into the highest cache levels). Timings
|
|
|
|
|
// should be independent of points so we don't
|
|
|
|
|
// randomize them.
|
|
|
|
|
b.iter_batched(
|
|
|
|
|
|| {
|
|
|
|
|
(
|
|
|
|
|
construct_scalars(static_size),
|
|
|
|
|
construct_scalars(dynamic_size),
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
|(static_scalars, dynamic_scalars)| {
|
|
|
|
|
precomp.vartime_mixed_multiscalar_mul(
|
|
|
|
|
&static_scalars,
|
|
|
|
|
&dynamic_scalars,
|
|
|
|
|
&dynamic_points,
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
BatchSize::SmallInput,
|
|
|
|
|
);
|
|
|
|
|
});
|
2021-03-26 16:18:18 +00:00
|
|
|
}
|
2019-01-24 21:29:28 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
pub(crate) fn multiscalar_benches() {
|
|
|
|
|
let mut c = Criterion::default();
|
|
|
|
|
let mut g = c.benchmark_group("multiscalar benches");
|
2019-01-24 21:29:28 +00:00
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
consttime_multiscalar_mul(&mut g);
|
|
|
|
|
vartime_multiscalar_mul(&mut g);
|
|
|
|
|
vartime_precomputed_pure_static(&mut g);
|
2019-01-24 21:29:28 +00:00
|
|
|
|
2021-03-26 16:18:18 +00:00
|
|
|
let dynamic_fracs = [0.0, 0.2, 0.5];
|
2021-08-17 00:14:00 +00:00
|
|
|
|
2021-03-26 16:18:18 +00:00
|
|
|
for frac in dynamic_fracs.iter() {
|
2023-01-31 08:37:03 +00:00
|
|
|
vartime_precomputed_helper(&mut g, *frac);
|
2021-03-26 16:18:18 +00:00
|
|
|
}
|
2018-03-26 00:10:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mod ristretto_benches {
|
|
|
|
|
use super::*;
|
|
|
|
|
use curve25519_dalek::ristretto::RistrettoPoint;
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn compress<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2018-03-26 00:10:30 +00:00
|
|
|
c.bench_function("RistrettoPoint compression", |b| {
|
|
|
|
|
let B = &constants::RISTRETTO_BASEPOINT_POINT;
|
|
|
|
|
b.iter(|| B.compress())
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn decompress<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2018-03-26 00:10:30 +00:00
|
|
|
c.bench_function("RistrettoPoint decompression", |b| {
|
|
|
|
|
let B_comp = &constants::RISTRETTO_BASEPOINT_COMPRESSED;
|
|
|
|
|
b.iter(|| B_comp.decompress().unwrap())
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-26 16:18:18 +00:00
|
|
|
fn double_and_compress_batch<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
|
|
|
|
for batch_size in &BATCH_SIZES {
|
|
|
|
|
c.bench_with_input(
|
|
|
|
|
BenchmarkId::new("Batch Ristretto double-and-encode", *batch_size),
|
|
|
|
|
&batch_size,
|
|
|
|
|
|b, &&size| {
|
2025-12-27 16:53:24 +00:00
|
|
|
let mut rng = SysRng;
|
2021-03-26 16:18:18 +00:00
|
|
|
let points: Vec<RistrettoPoint> = (0..size)
|
2025-07-07 19:36:11 +00:00
|
|
|
.map(|_| RistrettoPoint::try_from_rng(&mut rng).unwrap())
|
2021-03-26 16:18:18 +00:00
|
|
|
.collect();
|
|
|
|
|
b.iter(|| RistrettoPoint::double_and_compress_batch(&points));
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
pub(crate) fn ristretto_benches() {
|
|
|
|
|
let mut c = Criterion::default();
|
|
|
|
|
let mut g = c.benchmark_group("ristretto benches");
|
2018-03-26 00:10:30 +00:00
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
compress(&mut g);
|
|
|
|
|
decompress(&mut g);
|
|
|
|
|
double_and_compress_batch(&mut g);
|
2018-03-26 00:10:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mod montgomery_benches {
|
|
|
|
|
use super::*;
|
2023-01-31 08:37:03 +00:00
|
|
|
use curve25519_dalek::montgomery::MontgomeryPoint;
|
2018-03-26 00:10:30 +00:00
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn montgomery_ladder<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2018-03-26 00:10:30 +00:00
|
|
|
c.bench_function("Montgomery pseudomultiplication", |b| {
|
|
|
|
|
let B = constants::X25519_BASEPOINT;
|
2018-07-17 17:53:02 +00:00
|
|
|
let s = Scalar::from(897987897u64).invert();
|
2018-03-26 00:10:30 +00:00
|
|
|
b.iter(|| B * s);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
fn consttime_fixed_base_scalar_mul<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
|
|
|
|
let s = Scalar::from(897987897u64).invert();
|
|
|
|
|
c.bench_function("Constant-time fixed-base scalar mul", move |b| {
|
|
|
|
|
b.iter(|| MontgomeryPoint::mul_base(&s))
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn montgomery_benches() {
|
|
|
|
|
let mut c = Criterion::default();
|
|
|
|
|
let mut g = c.benchmark_group("montgomery benches");
|
|
|
|
|
|
|
|
|
|
montgomery_ladder(&mut g);
|
|
|
|
|
consttime_fixed_base_scalar_mul(&mut g);
|
2018-03-26 00:10:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mod scalar_benches {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
2023-03-28 22:12:24 +00:00
|
|
|
fn scalar_arith<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
2026-01-25 00:29:05 +00:00
|
|
|
let mut rng = UnwrapErr(SysRng);
|
2023-03-28 22:12:24 +00:00
|
|
|
|
2018-03-26 00:10:30 +00:00
|
|
|
c.bench_function("Scalar inversion", |b| {
|
2018-07-17 17:53:02 +00:00
|
|
|
let s = Scalar::from(897987897u64).invert();
|
2018-03-26 00:10:30 +00:00
|
|
|
b.iter(|| s.invert());
|
|
|
|
|
});
|
2023-03-28 22:12:24 +00:00
|
|
|
c.bench_function("Scalar addition", |b| {
|
|
|
|
|
b.iter_batched(
|
|
|
|
|
|| (Scalar::random(&mut rng), Scalar::random(&mut rng)),
|
|
|
|
|
|(a, b)| a + b,
|
|
|
|
|
BatchSize::SmallInput,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
c.bench_function("Scalar subtraction", |b| {
|
|
|
|
|
b.iter_batched(
|
|
|
|
|
|| (Scalar::random(&mut rng), Scalar::random(&mut rng)),
|
|
|
|
|
|(a, b)| a - b,
|
|
|
|
|
BatchSize::SmallInput,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
c.bench_function("Scalar multiplication", |b| {
|
|
|
|
|
b.iter_batched(
|
|
|
|
|
|| (Scalar::random(&mut rng), Scalar::random(&mut rng)),
|
|
|
|
|
|(a, b)| a * b,
|
|
|
|
|
BatchSize::SmallInput,
|
|
|
|
|
);
|
|
|
|
|
});
|
2018-03-26 00:10:30 +00:00
|
|
|
}
|
|
|
|
|
|
2021-03-26 16:18:18 +00:00
|
|
|
fn batch_scalar_inversion<M: Measurement>(c: &mut BenchmarkGroup<M>) {
|
|
|
|
|
for batch_size in &BATCH_SIZES {
|
|
|
|
|
c.bench_with_input(
|
|
|
|
|
BenchmarkId::new("Batch scalar inversion", *batch_size),
|
|
|
|
|
&batch_size,
|
|
|
|
|
|b, &&size| {
|
2026-01-25 00:29:05 +00:00
|
|
|
let mut rng = UnwrapErr(SysRng);
|
2021-03-26 16:18:18 +00:00
|
|
|
let scalars: Vec<Scalar> =
|
|
|
|
|
(0..size).map(|_| Scalar::random(&mut rng)).collect();
|
|
|
|
|
b.iter(|| {
|
|
|
|
|
let mut s = scalars.clone();
|
2025-08-26 18:54:09 +00:00
|
|
|
Scalar::invert_batch_alloc(&mut s);
|
2021-03-26 16:18:18 +00:00
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-31 08:37:03 +00:00
|
|
|
pub(crate) fn scalar_benches() {
|
|
|
|
|
let mut c = Criterion::default();
|
|
|
|
|
let mut g = c.benchmark_group("scalar benches");
|
2018-03-26 00:10:30 +00:00
|
|
|
|
2023-03-28 22:12:24 +00:00
|
|
|
scalar_arith(&mut g);
|
2023-01-31 08:37:03 +00:00
|
|
|
batch_scalar_inversion(&mut g);
|
2018-03-26 00:10:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
criterion_main!(
|
|
|
|
|
scalar_benches::scalar_benches,
|
|
|
|
|
montgomery_benches::montgomery_benches,
|
|
|
|
|
ristretto_benches::ristretto_benches,
|
|
|
|
|
edwards_benches::edwards_benches,
|
2019-01-24 21:29:28 +00:00
|
|
|
multiscalar_benches::multiscalar_benches,
|
2018-03-26 00:10:30 +00:00
|
|
|
);
|