poulpy/poulpy-hal/src/reference/vec_znx/sub.rs
poulpy-hal/src/reference/vec_znx/sub.rsRaw
1use std::hint::black_box;
2
3use criterion::{BenchmarkId, Criterion};
4
5use crate::{
6 api::{ModuleNew, VecZnxSub, VecZnxSubInplace, VecZnxSubNegateInplace},
7 layouts::{Backend, FillUniform, Module, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos, ZnxView, ZnxViewMut},
8 oep::{ModuleNewImpl, VecZnxSubImpl, VecZnxSubInplaceImpl, VecZnxSubNegateInplaceImpl},
9 reference::znx::{ZnxCopy, ZnxNegate, ZnxNegateInplace, ZnxSub, ZnxSubInplace, ZnxSubNegateInplace, ZnxZero},
10 source::Source,
11};
12
13pub fn vec_znx_sub<R, A, B, ZNXARI>(res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
14where
15 R: VecZnxToMut,
16 A: VecZnxToRef,
17 B: VecZnxToRef,
18 ZNXARI: ZnxSub + ZnxNegate + ZnxZero + ZnxCopy,
19{
20 let a: VecZnx<&[u8]> = a.to_ref();
21 let b: VecZnx<&[u8]> = b.to_ref();
22 let mut res: VecZnx<&mut [u8]> = res.to_mut();
23
24 #[cfg(debug_assertions)]
25 {
26 assert_eq!(a.n(), res.n());
27 assert_eq!(b.n(), res.n());
28 }
29
30 let res_size: usize = res.size();
31 let a_size: usize = a.size();
32 let b_size: usize = b.size();
33
34 if a_size <= b_size {
35 let sum_size: usize = a_size.min(res_size);
36 let cpy_size: usize = b_size.min(res_size);
37
38 for j in 0..sum_size {
39 ZNXARI::znx_sub(res.at_mut(res_col, j), a.at(a_col, j), b.at(b_col, j));
40 }
41
42 for j in sum_size..cpy_size {
43 ZNXARI::znx_negate(res.at_mut(res_col, j), b.at(b_col, j));
44 }
45
46 for j in cpy_size..res_size {
47 ZNXARI::znx_zero(res.at_mut(res_col, j));
48 }
49 } else {
50 let sum_size: usize = b_size.min(res_size);
51 let cpy_size: usize = a_size.min(res_size);
52
53 for j in 0..sum_size {
54 ZNXARI::znx_sub(res.at_mut(res_col, j), a.at(a_col, j), b.at(b_col, j));
55 }
56
57 for j in sum_size..cpy_size {
58 ZNXARI::znx_copy(res.at_mut(res_col, j), a.at(a_col, j));
59 }
60
61 for j in cpy_size..res_size {
62 ZNXARI::znx_zero(res.at_mut(res_col, j));
63 }
64 }
65}
66
67pub fn vec_znx_sub_inplace<R, A, ZNXARI>(res: &mut R, res_col: usize, a: &A, a_col: usize)
68where
69 R: VecZnxToMut,
70 A: VecZnxToRef,
71 ZNXARI: ZnxSubInplace,
72{
73 let a: VecZnx<&[u8]> = a.to_ref();
74 let mut res: VecZnx<&mut [u8]> = res.to_mut();
75
76 #[cfg(debug_assertions)]
77 {
78 assert_eq!(a.n(), res.n());
79 }
80
81 let res_size: usize = res.size();
82 let a_size: usize = a.size();
83
84 let sum_size: usize = a_size.min(res_size);
85
86 for j in 0..sum_size {
87 ZNXARI::znx_sub_inplace(res.at_mut(res_col, j), a.at(a_col, j));
88 }
89}
90
91pub fn vec_znx_sub_negate_inplace<R, A, ZNXARI>(res: &mut R, res_col: usize, a: &A, a_col: usize)
92where
93 R: VecZnxToMut,
94 A: VecZnxToRef,
95 ZNXARI: ZnxSubNegateInplace + ZnxNegateInplace,
96{
97 let a: VecZnx<&[u8]> = a.to_ref();
98 let mut res: VecZnx<&mut [u8]> = res.to_mut();
99
100 #[cfg(debug_assertions)]
101 {
102 assert_eq!(a.n(), res.n());
103 }
104
105 let res_size: usize = res.size();
106 let a_size: usize = a.size();
107
108 let sum_size: usize = a_size.min(res_size);
109
110 for j in 0..sum_size {
111 ZNXARI::znx_sub_negate_inplace(res.at_mut(res_col, j), a.at(a_col, j));
112 }
113
114 for j in sum_size..res_size {
115 ZNXARI::znx_negate_inplace(res.at_mut(res_col, j));
116 }
117}
118
119pub fn bench_vec_znx_sub<B>(c: &mut Criterion, label: &str)
120where
121 B: Backend + ModuleNewImpl<B> + VecZnxSubImpl<B>,
122{
123 let group_name: String = format!("vec_znx_sub::{label}");
124
125 let mut group = c.benchmark_group(group_name);
126
127 fn runner<B: Backend>(params: [usize; 3]) -> impl FnMut()
128 where
129 Module<B>: VecZnxSub + ModuleNew<B>,
130 {
131 let n: usize = 1 << params[0];
132 let cols: usize = params[1];
133 let size: usize = params[2];
134
135 let module: Module<B> = Module::<B>::new(n as u64);
136
137 let mut source: Source = Source::new([0u8; 32]);
138
139 let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
140 let mut b: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
141 let mut c: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
142
143 // Fill a with random i64
144 a.fill_uniform(50, &mut source);
145 b.fill_uniform(50, &mut source);
146
147 move || {
148 for i in 0..cols {
149 module.vec_znx_sub(&mut c, i, &a, i, &b, i);
150 }
151 black_box(());
152 }
153 }
154
155 for params in [[10, 2, 2], [11, 2, 4], [12, 2, 8], [13, 2, 16], [14, 2, 32]] {
156 let id: BenchmarkId = BenchmarkId::from_parameter(format!("{}x({}x{})", 1 << params[0], params[1], params[2],));
157 let mut runner = runner::<B>(params);
158 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
159 }
160
161 group.finish();
162}
163
164pub fn bench_vec_znx_sub_inplace<B>(c: &mut Criterion, label: &str)
165where
166 B: Backend + ModuleNewImpl<B> + VecZnxSubInplaceImpl<B>,
167{
168 let group_name: String = format!("vec_znx_sub_inplace::{label}");
169
170 let mut group = c.benchmark_group(group_name);
171
172 fn runner<B: Backend>(params: [usize; 3]) -> impl FnMut()
173 where
174 Module<B>: VecZnxSubInplace + ModuleNew<B>,
175 {
176 let n: usize = 1 << params[0];
177 let cols: usize = params[1];
178 let size: usize = params[2];
179
180 let module: Module<B> = Module::<B>::new(n as u64);
181
182 let mut source: Source = Source::new([0u8; 32]);
183
184 let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
185 let mut b: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
186
187 // Fill a with random i64
188 a.fill_uniform(50, &mut source);
189 b.fill_uniform(50, &mut source);
190
191 move || {
192 for i in 0..cols {
193 module.vec_znx_sub_inplace(&mut b, i, &a, i);
194 }
195 black_box(());
196 }
197 }
198
199 for params in [[10, 2, 2], [11, 2, 4], [12, 2, 8], [13, 2, 16], [14, 2, 32]] {
200 let id: BenchmarkId = BenchmarkId::from_parameter(format!("{}x({}x{})", 1 << params[0], params[1], params[2]));
201 let mut runner = runner::<B>(params);
202 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
203 }
204
205 group.finish();
206}
207
208pub fn bench_vec_znx_sub_negate_inplace<B>(c: &mut Criterion, label: &str)
209where
210 B: Backend + ModuleNewImpl<B> + VecZnxSubNegateInplaceImpl<B>,
211{
212 let group_name: String = format!("vec_znx_sub_negate_inplace::{label}");
213
214 let mut group = c.benchmark_group(group_name);
215
216 fn runner<B: Backend>(params: [usize; 3]) -> impl FnMut()
217 where
218 Module<B>: VecZnxSubNegateInplace + ModuleNew<B>,
219 {
220 let n: usize = 1 << params[0];
221 let cols: usize = params[1];
222 let size: usize = params[2];
223
224 let module: Module<B> = Module::<B>::new(n as u64);
225
226 let mut source: Source = Source::new([0u8; 32]);
227
228 let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
229 let mut b: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
230
231 // Fill a with random i64
232 a.fill_uniform(50, &mut source);
233 b.fill_uniform(50, &mut source);
234
235 move || {
236 for i in 0..cols {
237 module.vec_znx_sub_negate_inplace(&mut b, i, &a, i);
238 }
239 black_box(());
240 }
241 }
242
243 for params in [[10, 2, 2], [11, 2, 4], [12, 2, 8], [13, 2, 16], [14, 2, 32]] {
244 let id: BenchmarkId = BenchmarkId::from_parameter(format!("{}x({}x{})", 1 << params[0], params[1], params[2]));
245 let mut runner = runner::<B>(params);
246 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
247 }
248
249 group.finish();
250}