#[macro_export]
macro_rules! bench_field {
($name:ident, $desc:expr, $fe_a:expr, $fe_b:expr) => {
fn bench_add<M: ::criterion::measurement::Measurement>(
group: &mut ::criterion::BenchmarkGroup<'_, M>,
) {
let x = core::hint::black_box($fe_a);
let y = core::hint::black_box($fe_b);
group.bench_function("add", |b| b.iter(|| x + y));
}
fn bench_sub<M: ::criterion::measurement::Measurement>(
group: &mut ::criterion::BenchmarkGroup<'_, M>,
) {
let x = core::hint::black_box($fe_a);
let y = core::hint::black_box($fe_b);
group.bench_function("sub", |b| b.iter(|| x - y));
}
fn bench_mul<M: ::criterion::measurement::Measurement>(
group: &mut ::criterion::BenchmarkGroup<'_, M>,
) {
let x = core::hint::black_box($fe_a);
let y = core::hint::black_box($fe_b);
group.bench_function("mul", |b| b.iter(|| x * y));
}
fn bench_neg<M: ::criterion::measurement::Measurement>(
group: &mut ::criterion::BenchmarkGroup<'_, M>,
) {
let x = core::hint::black_box($fe_a);
group.bench_function("neg", |b| b.iter(|| -x));
}
fn bench_invert<M: ::criterion::measurement::Measurement>(
group: &mut ::criterion::BenchmarkGroup<'_, M>,
) {
let x = core::hint::black_box($fe_a);
group.bench_function("invert", |b| b.iter(|| x.invert()));
}
fn bench_square<'a, M: ::criterion::measurement::Measurement>(
group: &mut ::criterion::BenchmarkGroup<'a, M>,
) {
let x = core::hint::black_box($fe_a);
group.bench_function("square", |b| b.iter(|| x.square()));
}
fn bench_sqrt<'a, M: ::criterion::measurement::Measurement>(
group: &mut ::criterion::BenchmarkGroup<'a, M>,
) {
use ::primefield::ff::Field;
let x = core::hint::black_box($fe_a);
group.bench_function("sqrt", |b| b.iter(|| x.sqrt()));
}
fn $name(c: &mut ::criterion::Criterion) {
let mut group = c.benchmark_group($desc);
bench_add(&mut group);
bench_sub(&mut group);
bench_mul(&mut group);
bench_neg(&mut group);
bench_invert(&mut group);
bench_square(&mut group);
bench_sqrt(&mut group);
group.finish();
}
};
}
#[macro_export]
macro_rules! test_primefield {
($fe:tt, $uint:ident) => {
$crate::test_primefield_constants!($fe, $uint);
$crate::test_field_identity!($fe);
$crate::test_field_invert!($fe);
$crate::test_field_sqrt!($fe);
};
}
#[macro_export]
macro_rules! test_primefield_constants {
($fe:tt, $uint:ident) => {
#[allow(unused_imports)]
use $crate::{bigint::modular::Retrieve as _, ff::PrimeField as _};
const MODULUS: $crate::bigint::Odd<$uint> = $crate::bigint::Odd::from_be_hex($fe::MODULUS);
const T: $uint = $crate::compute_t(MODULUS.as_ref());
#[test]
fn delta_constant() {
assert_eq!($fe::DELTA.pow_vartime(&T), $fe::ONE);
}
#[test]
fn multiplicative_generator_constant() {
assert_eq!(
$fe::MULTIPLICATIVE_GENERATOR
.retrieve()
.jacobi_symbol(&MODULUS),
$crate::bigint::JacobiSymbol::MinusOne
);
}
#[test]
fn root_of_unity_constant() {
assert_eq!($fe::ROOT_OF_UNITY.sqn_vartime($fe::S as usize), $fe::ONE);
assert_eq!(
$fe::MULTIPLICATIVE_GENERATOR.pow_vartime(&T),
$fe::ROOT_OF_UNITY
)
}
#[test]
fn root_of_unity_inv_constant() {
assert_eq!($fe::ROOT_OF_UNITY * $fe::ROOT_OF_UNITY_INV, $fe::ONE);
}
#[test]
fn two_inv_constant() {
assert_eq!($fe::from(2u32) * $fe::TWO_INV, $fe::ONE);
}
};
}
#[macro_export]
macro_rules! test_field_identity {
($fe:tt) => {
#[test]
fn zero_is_additive_identity() {
let zero = $fe::ZERO;
let one = $fe::ONE;
assert_eq!(zero.add(&zero), zero);
assert_eq!(one.add(&zero), one);
}
#[test]
fn one_is_multiplicative_identity() {
let one = $fe::ONE;
assert_eq!(one.multiply(&one), one);
}
};
}
#[macro_export]
macro_rules! test_field_invert {
($fe:tt) => {
#[test]
fn invert() {
let one = $fe::ONE;
assert_eq!(one.invert().unwrap(), one);
let three = one + &one + &one;
let inv_three = three.invert().unwrap();
assert_eq!(three * &inv_three, one);
let minus_three = -three;
let inv_minus_three = minus_three.invert().unwrap();
assert_eq!(inv_minus_three, -inv_three);
assert_eq!(three * &inv_minus_three, -one);
}
};
}
#[macro_export]
macro_rules! test_field_sqrt {
($fe:tt) => {
#[test]
fn sqrt() {
for &n in &[1u64, 4, 9, 16, 25, 36, 49, 64] {
let fe = $fe::from(n);
let sqrt = $crate::ff::Field::sqrt(&fe).unwrap();
assert_eq!(sqrt.square(), fe);
}
}
};
}