binius_field/arch/portable/byte_sliced/
multiply.rs1use crate::{
3 tower_levels::{TowerLevel, TowerLevelWithArithOps},
4 underlier::WithUnderlier,
5 AESTowerField8b, PackedField,
6};
7
8#[inline(always)]
9pub fn mul<P: PackedField<Scalar = AESTowerField8b>, Level: TowerLevel>(
10 field_element_a: &Level::Data<P>,
11 field_element_b: &Level::Data<P>,
12 destination: &mut Level::Data<P>,
13) {
14 let base_alpha = P::broadcast(AESTowerField8b::from_underlier(0xd3));
15 mul_main::<true, P, Level>(field_element_a, field_element_b, destination, base_alpha);
16}
17
18#[inline(always)]
19pub fn mul_alpha<
20 const WRITING_TO_ZEROS: bool,
21 P: PackedField<Scalar = AESTowerField8b>,
22 Level: TowerLevel,
23>(
24 field_element: &Level::Data<P>,
25 destination: &mut Level::Data<P>,
26 base_alpha: P,
27) {
28 if Level::WIDTH == 1 {
29 if WRITING_TO_ZEROS {
30 destination.as_mut()[0] = field_element[0] * base_alpha;
31 } else {
32 destination.as_mut()[0] += field_element[0] * base_alpha;
33 }
34 return;
35 }
36
37 let (a0, a1) = Level::split(field_element);
38
39 let (result0, result1) = Level::split_mut(destination);
40
41 if WRITING_TO_ZEROS {
42 Level::Base::copy_into(a0, result1);
44
45 Level::Base::copy_into(a1, result0);
47 } else {
48 Level::Base::add_into(a0, result1);
50
51 Level::Base::add_into(a1, result0);
53 }
54 mul_alpha::<false, P, Level::Base>(a1, result1, base_alpha);
56}
57
58#[inline(always)]
59pub fn mul_main<
60 const WRITING_TO_ZEROS: bool,
61 P: PackedField<Scalar = AESTowerField8b>,
62 Level: TowerLevel,
63>(
64 field_element_a: &Level::Data<P>,
65 field_element_b: &Level::Data<P>,
66 destination: &mut Level::Data<P>,
67 base_alpha: P,
68) {
69 if Level::WIDTH == 1 {
70 if WRITING_TO_ZEROS {
71 destination.as_mut()[0] = field_element_a[0] * field_element_b[0];
72 } else {
73 destination.as_mut()[0] += field_element_a[0] * field_element_b[0];
74 }
75 return;
76 }
77
78 let (a0, a1) = Level::split(field_element_a);
79
80 let (b0, b1) = Level::split(field_element_b);
81
82 let (result0, result1) = Level::split_mut(destination);
83
84 let xored_halves_a = Level::Base::sum(a0, a1);
85
86 let xored_halves_b = Level::Base::sum(b0, b1);
87
88 let mut z2_z0 = <<Level as TowerLevel>::Base as TowerLevel>::default();
89
90 mul_main::<true, P, Level::Base>(a1, b1, &mut z2_z0, base_alpha);
92
93 mul_alpha::<WRITING_TO_ZEROS, P, Level::Base>(&z2_z0, result1, base_alpha);
95
96 mul_main::<false, P, Level::Base>(a0, b0, &mut z2_z0, base_alpha);
98
99 mul_main::<false, P, Level::Base>(&xored_halves_a, &xored_halves_b, result1, base_alpha);
101
102 Level::Base::add_into(&z2_z0, result1);
104
105 if WRITING_TO_ZEROS {
106 Level::Base::copy_into(&z2_z0, result0);
107 } else {
108 Level::Base::add_into(&z2_z0, result0);
109 }
110}