Skip to content

Commit

Permalink
Add quartic extension baby bear u32 (#956)
Browse files Browse the repository at this point in the history
* add quartic extension for baby bear u32. Add comments in mu and r2 generator function

* add bench for Fp4E using u32

* fix typo and restore all benches

* fix clippy

* cargo check

* fix tests

* fix clippy

* fix crate import

* fix documentation

* use num instead of capacity in loop

---------

Co-authored-by: Nicole <nicole@Nicoles-MacBook-Air.local>
Co-authored-by: jotabulacios <jbulacios@fi.uba.ar>
Co-authored-by: Diego K <43053772+diegokingston@users.noreply.github.com>
Co-authored-by: jotabulacios <45471455+jotabulacios@users.noreply.github.com>
  • Loading branch information
5 people authored Feb 3, 2025
1 parent f2f40d3 commit d78d18a
Show file tree
Hide file tree
Showing 5 changed files with 947 additions and 17 deletions.
21 changes: 18 additions & 3 deletions math/benches/criterion_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ mod fields;
use fields::mersenne31::{mersenne31_extension_ops_benchmarks, mersenne31_ops_benchmarks};
use fields::mersenne31_montgomery::mersenne31_mont_ops_benchmarks;
use fields::{
baby_bear::{babybear_ops_benchmarks, babybear_ops_benchmarks_f64, babybear_p3_ops_benchmarks},
baby_bear::{
babybear_extension_ops_benchmarks_p3, babybear_p3_ops_benchmarks,
babybear_u32_extension_ops_benchmarks, babybear_u32_ops_benchmarks,
babybear_u64_extension_ops_benchmarks, babybear_u64_ops_benchmarks,
},
stark252::starkfield_ops_benchmarks,
u64_goldilocks::u64_goldilocks_ops_benchmarks,
u64_goldilocks_montgomery::u64_goldilocks_montgomery_ops_benchmarks,
Expand All @@ -14,7 +18,18 @@ use fields::{
criterion_group!(
name = field_benches;
config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None)));
targets =babybear_ops_benchmarks,babybear_ops_benchmarks_f64, babybear_p3_ops_benchmarks,mersenne31_extension_ops_benchmarks,mersenne31_ops_benchmarks,
starkfield_ops_benchmarks,u64_goldilocks_ops_benchmarks,u64_goldilocks_montgomery_ops_benchmarks,mersenne31_mont_ops_benchmarks

targets = babybear_u32_ops_benchmarks,
babybear_u32_extension_ops_benchmarks,
babybear_u64_ops_benchmarks,
babybear_u64_extension_ops_benchmarks,
babybear_p3_ops_benchmarks,
babybear_extension_ops_benchmarks_p3,
mersenne31_ops_benchmarks,
mersenne31_extension_ops_benchmarks,
mersenne31_mont_ops_benchmarks,
starkfield_ops_benchmarks,
u64_goldilocks_ops_benchmarks,
u64_goldilocks_montgomery_ops_benchmarks,
);
criterion_main!(field_benches);
267 changes: 255 additions & 12 deletions math/benches/fields/baby_bear.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use criterion::Criterion;
use std::hint::black_box;

use lambdaworks_math::field::fields::fft_friendly::{
quartic_babybear::Degree4BabyBearExtensionField,
quartic_babybear_u32::Degree4BabyBearU32ExtensionField,
};
use lambdaworks_math::field::{
element::FieldElement,
fields::{
Expand All @@ -10,6 +14,7 @@ use lambdaworks_math::field::{
};

use p3_baby_bear::BabyBear;
use p3_field::extension::BinomialExtensionField;
use p3_field::{Field, FieldAlgebra};

use rand::random;
Expand All @@ -18,26 +23,85 @@ use rand::Rng;
pub type U32Babybear31PrimeField = U32MontgomeryBackendPrimeField<2013265921>;
pub type F = FieldElement<U32Babybear31PrimeField>;
pub type F64 = FieldElement<Babybear31PrimeField>;
pub type Fp4Eu32 = FieldElement<Degree4BabyBearU32ExtensionField>;
pub type Fp4E = FieldElement<Degree4BabyBearExtensionField>;
type EF4 = BinomialExtensionField<BabyBear, 4>;

pub fn rand_field_elements(num: usize) -> Vec<(F, F)> {
pub fn rand_field_elements_u32(num: usize) -> Vec<(F, F)> {
let mut result = Vec::with_capacity(num);
for _ in 0..result.capacity() {
for _ in 0..num {
result.push((F::from(random::<u64>()), F::from(random::<u64>())));
}
result
}

pub fn rand_field_elements_u64(num: usize) -> Vec<(F64, F64)> {
let mut result = Vec::with_capacity(num);
for _ in 0..num {
result.push((F64::from(random::<u64>()), F64::from(random::<u64>())));
}
result
}

pub fn rand_babybear_u64_fp4_elements(num: usize) -> Vec<(Fp4E, Fp4E)> {
let mut result = Vec::with_capacity(num);
for _ in 0..num {
result.push((
Fp4E::new([
F64::from(random::<u64>()),
F64::from(random::<u64>()),
F64::from(random::<u64>()),
F64::from(random::<u64>()),
]),
Fp4E::new([
F64::from(random::<u64>()),
F64::from(random::<u64>()),
F64::from(random::<u64>()),
F64::from(random::<u64>()),
]),
));
}
result
}
pub fn rand_babybear_u32_fp4_elements(num: usize) -> Vec<(Fp4Eu32, Fp4Eu32)> {
let mut result = Vec::with_capacity(num);
for _ in 0..num {
result.push((
Fp4Eu32::new([
F::from(random::<u64>()),
F::from(random::<u64>()),
F::from(random::<u64>()),
F::from(random::<u64>()),
]),
Fp4Eu32::new([
F::from(random::<u64>()),
F::from(random::<u64>()),
F::from(random::<u64>()),
F::from(random::<u64>()),
]),
));
}
result
}

fn rand_babybear_elements_p3(num: usize) -> Vec<(BabyBear, BabyBear)> {
let mut rng = rand::thread_rng();
(0..num)
.map(|_| (rng.gen::<BabyBear>(), rng.gen::<BabyBear>()))
.collect()
}

pub fn babybear_ops_benchmarks(c: &mut Criterion) {
fn rand_babybear_fp4_elements_p3(num: usize) -> Vec<(EF4, EF4)> {
let mut rng = rand::thread_rng();
(0..num)
.map(|_| (rng.gen::<EF4>(), rng.gen::<EF4>()))
.collect()
}

pub fn babybear_u32_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(F, F)>> = [1000000]
.into_iter()
.map(rand_field_elements)
.map(rand_field_elements_u32)
.collect::<Vec<_>>();
let mut group = c.benchmark_group("BabyBear operations using Lambdaworks u32");

Expand Down Expand Up @@ -92,14 +156,7 @@ pub fn babybear_ops_benchmarks(c: &mut Criterion) {
}
}

pub fn rand_field_elements_u64(num: usize) -> Vec<(F64, F64)> {
let mut result = Vec::with_capacity(num);
for _ in 0..result.capacity() {
result.push((F64::from(random::<u64>()), F64::from(random::<u64>())));
}
result
}
pub fn babybear_ops_benchmarks_f64(c: &mut Criterion) {
pub fn babybear_u64_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(F64, F64)>> = [1000000]
.into_iter()
.map(rand_field_elements_u64)
Expand Down Expand Up @@ -156,6 +213,130 @@ pub fn babybear_ops_benchmarks_f64(c: &mut Criterion) {
});
}
}
pub fn babybear_u32_extension_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(Fp4Eu32, Fp4Eu32)>> = [1000000]
.into_iter()
.map(rand_babybear_u32_fp4_elements)
.collect::<Vec<_>>();

let mut group = c.benchmark_group("BabyBear u32 Fp4 operations");

for i in input.clone().into_iter() {
group.bench_with_input(format!("Addition of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) + black_box(y));
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(
format!("Multiplication of Fp4 {:?}", &i.len()),
&i,
|bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) * black_box(y));
}
});
},
);
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Square of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).square());
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Inverse of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) / black_box(y));
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Division of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).inv().unwrap());
}
});
});
}
}
pub fn babybear_u64_extension_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(Fp4E, Fp4E)>> = [1000000]
.into_iter()
.map(rand_babybear_u64_fp4_elements)
.collect::<Vec<_>>();

let mut group = c.benchmark_group("BabyBear u64 Fp4 operations");

for i in input.clone().into_iter() {
group.bench_with_input(format!("Addition of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) + black_box(y));
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(
format!("Multiplication of Fp4 {:?}", &i.len()),
&i,
|bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) * black_box(y));
}
});
},
);
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Square of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).square());
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Inverse of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) / black_box(y));
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Division of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).inv().unwrap());
}
});
});
}
}

pub fn babybear_p3_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(BabyBear, BabyBear)>> = [1000000]
Expand Down Expand Up @@ -214,3 +395,65 @@ pub fn babybear_p3_ops_benchmarks(c: &mut Criterion) {
});
}
}

pub fn babybear_extension_ops_benchmarks_p3(c: &mut Criterion) {
let input_sizes = [1000000];
let input: Vec<Vec<(EF4, EF4)>> = input_sizes
.into_iter()
.map(rand_babybear_fp4_elements_p3)
.collect::<Vec<_>>();

let mut group = c.benchmark_group("BabyBear Fp4 operations using Plonky3");

for i in input.clone().into_iter() {
group.bench_with_input(format!("Addition of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(*x) + black_box(*y));
}
});
});
}
for i in input.clone().into_iter() {
group.bench_with_input(
format!("Multiplication of Fp4 {:?}", &i.len()),
&i,
|bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(*x) * black_box(*y));
}
});
},
);
}
for i in input.clone().into_iter() {
group.bench_with_input(format!("Square of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).square());
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Inverse of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).inverse());
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Division of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(*x) / black_box(*y));
}
});
});
}
}
7 changes: 5 additions & 2 deletions math/src/field/fields/fft_friendly/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/// Implemenation of the Babybear Prime Field p = 2^31 - 2^27 + 1
pub mod babybear;
/// Implemenation of the quadratic extension of the babybear field
/// Implementation of the quadratic extension of the babybear field
pub mod quadratic_babybear;
/// Implemenation of the quadric extension of the babybear field
/// Implementation of the extension of degree 4 of the babybear field using u64.
pub mod quartic_babybear;
/// Implementation of the prime field used in [Stark101](https://starkware.co/stark-101/) tutorial, p = 3 * 2^30 + 1
pub mod stark_101_prime_field;
Expand All @@ -15,3 +15,6 @@ pub mod u64_mersenne_montgomery_field;

/// Inmplementation of the Babybear Prime Field p = 2^31 - 2^27 + 1 using u32
pub mod babybear_u32;

/// Implementation of the extension of degree 4 of the babybear field using u32.
pub mod quartic_babybear_u32;
Loading

0 comments on commit d78d18a

Please # to comment.