Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: FieldMerkleTree tree with arbitrary hasher #22

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions baby-bear/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ rand_chacha = "0.3.1"
serde_json = "1.0.113"

[[bench]]
name = "inverse"
harness = false

[[bench]]
name = "root_7"
name = "bench_field"
harness = false

[[bench]]
Expand Down
37 changes: 37 additions & 0 deletions baby-bear/benches/bench_field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use p3_baby_bear::BabyBear;
use p3_field::AbstractField;
use p3_field_testing::bench_func::{
benchmark_add_latency, benchmark_add_throughput, benchmark_inv, benchmark_iter_sum,
benchmark_sub_latency, benchmark_sub_throughput,
};

type F = BabyBear;

fn bench_field(c: &mut Criterion) {
let name = "BabyBear";
const REPS: usize = 1000;
benchmark_inv::<F>(c, name);
benchmark_iter_sum::<F, 4, REPS>(c, name);
benchmark_iter_sum::<F, 8, REPS>(c, name);
benchmark_iter_sum::<F, 12, REPS>(c, name);

// Note that each round of throughput has 10 operations
// So we should have 10 * more repitions for latency tests.
const L_REPS: usize = 10 * REPS;
benchmark_add_latency::<F, L_REPS>(c, name);
benchmark_add_throughput::<F, REPS>(c, name);
benchmark_sub_latency::<F, L_REPS>(c, name);
benchmark_sub_throughput::<F, REPS>(c, name);

c.bench_function("7th_root", |b| {
b.iter_batched(
rand::random::<F>,
|x| x.exp_u64(1725656503),
BatchSize::SmallInput,
)
});
}

criterion_group!(baby_bear_arithmetic, bench_field);
criterion_main!(baby_bear_arithmetic);
18 changes: 0 additions & 18 deletions baby-bear/benches/inverse.rs

This file was deleted.

18 changes: 0 additions & 18 deletions baby-bear/benches/root_7.rs

This file was deleted.

11 changes: 7 additions & 4 deletions baby-bear/src/aarch64_neon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::iter::{Product, Sum};
use core::mem::transmute;
use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};

use p3_field::{AbstractField, Field, PackedField};
use p3_field::{AbstractField, Field, PackedField, PackedValue};
use rand::distributions::{Distribution, Standard};
use rand::Rng;

Expand Down Expand Up @@ -582,9 +582,8 @@ fn interleave2(v0: uint32x4_t, v1: uint32x4_t) -> (uint32x4_t, uint32x4_t) {
}
}

unsafe impl PackedField for PackedBabyBearNeon {
type Scalar = BabyBear;

unsafe impl PackedValue for PackedBabyBearNeon {
type Value = BabyBear;
const WIDTH: usize = WIDTH;

#[inline]
Expand Down Expand Up @@ -623,6 +622,10 @@ unsafe impl PackedField for PackedBabyBearNeon {
fn as_slice_mut(&mut self) -> &mut [BabyBear] {
&mut self.0[..]
}
}

unsafe impl PackedField for PackedBabyBearNeon {
type Scalar = BabyBear;

#[inline]
fn interleave(&self, other: Self, block_len: usize) -> (Self, Self) {
Expand Down
4 changes: 3 additions & 1 deletion baby-bear/src/baby_bear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};

use p3_field::{
exp_1725656503, exp_u64_by_squaring, AbstractField, Field, PrimeField, PrimeField32,
exp_1725656503, exp_u64_by_squaring, AbstractField, Field, Packable, PrimeField, PrimeField32,
PrimeField64, TwoAdicField,
};
use rand::distributions::{Distribution, Standard};
Expand Down Expand Up @@ -107,6 +107,8 @@ const MONTY_ONE: u32 = to_monty(1);
const MONTY_TWO: u32 = to_monty(2);
const MONTY_NEG_ONE: u32 = to_monty(P - 1);

impl Packable for BabyBear {}

impl AbstractField for BabyBear {
type F = Self;

Expand Down
4 changes: 3 additions & 1 deletion baby-bear/src/x86_64_avx2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ mod tests {
#[test]
fn test_neg_own_inverse() {
let vec = packed_from_random(0xee4df174b850a35f);
let res = --vec;
let res = -(-vec);
assert_eq!(res, vec);
}

Expand Down Expand Up @@ -1144,6 +1144,7 @@ mod tests {
let vec = PackedBabyBearAVX2(arr);
let vec_res = -vec;

#[allow(clippy::needless_range_loop)]
for i in 0..WIDTH {
assert_eq!(vec_res.0[i], -arr[i]);
}
Expand All @@ -1156,6 +1157,7 @@ mod tests {
let vec = PackedBabyBearAVX2(arr);
let vec_res = -vec;

#[allow(clippy::needless_range_loop)]
for i in 0..WIDTH {
assert_eq!(vec_res.0[i], -arr[i]);
}
Expand Down
15 changes: 14 additions & 1 deletion challenger/src/duplex_challenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use alloc::vec;
use alloc::vec::Vec;

use p3_field::{ExtensionField, Field, PrimeField64};
use p3_symmetric::CryptographicPermutation;
use p3_symmetric::{CryptographicPermutation, Hash};

use crate::{CanObserve, CanSample, CanSampleBits, FieldChallenger};

Expand Down Expand Up @@ -87,6 +87,19 @@ where
}
}

impl<F, P, const N: usize, const WIDTH: usize> CanObserve<Hash<F, F, N>>
for DuplexChallenger<F, P, WIDTH>
where
F: Copy,
P: CryptographicPermutation<[F; WIDTH]>,
{
fn observe(&mut self, values: Hash<F, F, N>) {
for value in values {
self.observe(value);
}
}
}

impl<F, EF, P, const WIDTH: usize> CanSample<EF> for DuplexChallenger<F, P, WIDTH>
where
F: Field,
Expand Down
45 changes: 22 additions & 23 deletions challenger/src/hash_challenger.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
use alloc::vec;
use alloc::vec::Vec;

use p3_field::Field;
use p3_symmetric::CryptographicHasher;

use crate::{CanObserve, CanSample};

#[derive(Clone)]
pub struct HashChallenger<F, H, const OUT_LEN: usize>
pub struct HashChallenger<T, H, const OUT_LEN: usize>
where
F: Field,
H: CryptographicHasher<F, [F; OUT_LEN]>,
T: Clone,
H: CryptographicHasher<T, [T; OUT_LEN]>,
{
input_buffer: Vec<F>,
output_buffer: Vec<F>,
input_buffer: Vec<T>,
output_buffer: Vec<T>,
hasher: H,
}

impl<F, H, const OUT_LEN: usize> HashChallenger<F, H, OUT_LEN>
impl<T, H, const OUT_LEN: usize> HashChallenger<T, H, OUT_LEN>
where
F: Field,
H: CryptographicHasher<F, [F; OUT_LEN]>,
T: Clone,
H: CryptographicHasher<T, [T; OUT_LEN]>,
{
pub fn new(initial_state: Vec<F>, hasher: H) -> Self {
pub fn new(initial_state: Vec<T>, hasher: H) -> Self {
Self {
input_buffer: initial_state,
output_buffer: vec![],
Expand All @@ -41,38 +40,38 @@ where
}
}

impl<F, H, const OUT_LEN: usize> CanObserve<F> for HashChallenger<F, H, OUT_LEN>
impl<T, H, const OUT_LEN: usize> CanObserve<T> for HashChallenger<T, H, OUT_LEN>
where
F: Field,
H: CryptographicHasher<F, [F; OUT_LEN]>,
T: Clone,
H: CryptographicHasher<T, [T; OUT_LEN]>,
{
fn observe(&mut self, value: F) {
fn observe(&mut self, value: T) {
// Any buffered output is now invalid.
self.output_buffer.clear();

self.input_buffer.push(value);
}
}

impl<F, H, const N: usize, const OUT_LEN: usize> CanObserve<[F; N]>
for HashChallenger<F, H, OUT_LEN>
impl<T, H, const N: usize, const OUT_LEN: usize> CanObserve<[T; N]>
for HashChallenger<T, H, OUT_LEN>
where
F: Field,
H: CryptographicHasher<F, [F; OUT_LEN]>,
T: Clone,
H: CryptographicHasher<T, [T; OUT_LEN]>,
{
fn observe(&mut self, values: [F; N]) {
fn observe(&mut self, values: [T; N]) {
for value in values {
self.observe(value);
}
}
}

impl<F, H, const OUT_LEN: usize> CanSample<F> for HashChallenger<F, H, OUT_LEN>
impl<T, H, const OUT_LEN: usize> CanSample<T> for HashChallenger<T, H, OUT_LEN>
where
F: Field,
H: CryptographicHasher<F, [F; OUT_LEN]>,
T: Clone,
H: CryptographicHasher<T, [T; OUT_LEN]>,
{
fn sample(&mut self) -> F {
fn sample(&mut self) -> T {
if self.output_buffer.is_empty() {
self.flush();
}
Expand Down
2 changes: 2 additions & 0 deletions challenger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern crate alloc;
mod duplex_challenger;
mod grinding_challenger;
mod hash_challenger;
mod serializing_challenger;

use alloc::vec::Vec;
use core::array;
Expand All @@ -15,6 +16,7 @@ pub use duplex_challenger::*;
pub use grinding_challenger::*;
pub use hash_challenger::*;
use p3_field::{AbstractExtensionField, Field};
pub use serializing_challenger::*;

pub trait CanObserve<T> {
fn observe(&mut self, value: T);
Expand Down
Loading
Loading