1use p3_field::{Field, PackedField, PackedValue};
2
3pub trait Butterfly<F: Field>: Copy + Send + Sync {
4 fn apply<PF: PackedField<Scalar = F>>(&self, x_1: PF, x_2: PF) -> (PF, PF);
5
6 #[inline]
7 fn apply_in_place<PF: PackedField<Scalar = F>>(&self, x_1: &mut PF, x_2: &mut PF) {
8 (*x_1, *x_2) = self.apply(*x_1, *x_2);
9 }
10
11 #[inline]
12 fn apply_to_rows(&self, row_1: &mut [F], row_2: &mut [F]) {
13 let (shorts_1, suffix_1) = F::Packing::pack_slice_with_suffix_mut(row_1);
14 let (shorts_2, suffix_2) = F::Packing::pack_slice_with_suffix_mut(row_2);
15 assert_eq!(shorts_1.len(), shorts_2.len());
16 assert_eq!(suffix_1.len(), suffix_2.len());
17 for (x_1, x_2) in shorts_1.iter_mut().zip(shorts_2) {
18 self.apply_in_place(x_1, x_2);
19 }
20 for (x_1, x_2) in suffix_1.iter_mut().zip(suffix_2) {
21 self.apply_in_place(x_1, x_2);
22 }
23 }
24}
25
26#[derive(Copy, Clone)]
27pub struct DifButterfly<F>(pub F);
28impl<F: Field> Butterfly<F> for DifButterfly<F> {
29 #[inline]
30 fn apply<PF: PackedField<Scalar = F>>(&self, x_1: PF, x_2: PF) -> (PF, PF) {
31 (x_1 + x_2, (x_1 - x_2) * self.0)
32 }
33}
34
35#[derive(Copy, Clone)]
36pub struct DitButterfly<F>(pub F);
37impl<F: Field> Butterfly<F> for DitButterfly<F> {
38 #[inline]
39 fn apply<PF: PackedField<Scalar = F>>(&self, x_1: PF, x_2: PF) -> (PF, PF) {
40 let x_2_twiddle = x_2 * self.0;
41 (x_1 + x_2_twiddle, x_1 - x_2_twiddle)
42 }
43}
44
45#[derive(Copy, Clone)]
47pub struct TwiddleFreeButterfly;
48impl<F: Field> Butterfly<F> for TwiddleFreeButterfly {
49 #[inline]
50 fn apply<PF: PackedField<Scalar = F>>(&self, x_1: PF, x_2: PF) -> (PF, PF) {
51 (x_1 + x_2, x_1 - x_2)
52 }
53}