poulpy/poulpy-backend/src/cpu_spqlios/fft64/vec_znx_dft.rs
poulpy-backend/src/cpu_spqlios/fft64/vec_znx_dft.rsRaw
1use poulpy_hal::{
2 api::{TakeSlice, VecZnxIdftApplyTmpBytes},
3 layouts::{
4 Backend, Data, Module, Scratch, VecZnx, VecZnxBig, VecZnxBigToMut, VecZnxDft, VecZnxDftOwned, VecZnxDftToMut,
5 VecZnxDftToRef, VecZnxToRef, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut,
6 },
7 oep::{
8 VecZnxDftAddImpl, VecZnxDftAddInplaceImpl, VecZnxDftAllocBytesImpl, VecZnxDftAllocImpl, VecZnxDftApplyImpl,
9 VecZnxDftCopyImpl, VecZnxDftFromBytesImpl, VecZnxDftSubImpl, VecZnxDftSubInplaceImpl, VecZnxDftSubNegateInplaceImpl,
10 VecZnxDftZeroImpl, VecZnxIdftApplyConsumeImpl, VecZnxIdftApplyImpl, VecZnxIdftApplyTmpAImpl, VecZnxIdftApplyTmpBytesImpl,
11 },
12 reference::{
13 fft64::{
14 reim::{ReimCopy, ReimZero, reim_copy_ref, reim_negate_inplace_ref, reim_negate_ref, reim_zero_ref},
15 vec_znx_dft::vec_znx_dft_copy,
16 },
17 znx::znx_zero_ref,
18 },
19};
20
21use crate::cpu_spqlios::{
22 FFT64Spqlios,
23 ffi::{vec_znx_big, vec_znx_dft},
24};
25
26unsafe impl VecZnxDftFromBytesImpl<Self> for FFT64Spqlios {
27 fn vec_znx_dft_from_bytes_impl(n: usize, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<Self> {
28 VecZnxDft::<Vec<u8>, Self>::from_bytes(n, cols, size, bytes)
29 }
30}
31
32unsafe impl VecZnxDftAllocBytesImpl<Self> for FFT64Spqlios {
33 fn vec_znx_dft_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize {
34 Self::layout_prep_word_count() * n * cols * size * size_of::<<FFT64Spqlios as Backend>::ScalarPrep>()
35 }
36}
37
38unsafe impl VecZnxDftAllocImpl<Self> for FFT64Spqlios {
39 fn vec_znx_dft_alloc_impl(n: usize, cols: usize, size: usize) -> VecZnxDftOwned<Self> {
40 VecZnxDftOwned::alloc(n, cols, size)
41 }
42}
43
44unsafe impl VecZnxIdftApplyTmpBytesImpl<Self> for FFT64Spqlios {
45 fn vec_znx_idft_apply_tmp_bytes_impl(module: &Module<Self>) -> usize {
46 unsafe { vec_znx_dft::vec_znx_idft_tmp_bytes(module.ptr()) as usize }
47 }
48}
49
50unsafe impl VecZnxIdftApplyImpl<Self> for FFT64Spqlios {
51 fn vec_znx_idft_apply_impl<R, A>(
52 module: &Module<Self>,
53 res: &mut R,
54 res_col: usize,
55 a: &A,
56 a_col: usize,
57 scratch: &mut Scratch<Self>,
58 ) where
59 R: VecZnxBigToMut<Self>,
60 A: VecZnxDftToRef<Self>,
61 {
62 let mut res: VecZnxBig<&mut [u8], Self> = res.to_mut();
63 let a: VecZnxDft<&[u8], Self> = a.to_ref();
64
65 #[cfg(debug_assertions)]
66 {
67 assert_eq!(res.n(), a.n())
68 }
69
70 let (tmp_bytes, _) = scratch.take_slice(module.vec_znx_idft_apply_tmp_bytes());
71
72 let min_size: usize = res.size().min(a.size());
73
74 unsafe {
75 (0..min_size).for_each(|j| {
76 vec_znx_dft::vec_znx_idft(
77 module.ptr(),
78 res.at_mut_ptr(res_col, j) as *mut vec_znx_big::vec_znx_big_t,
79 1_u64,
80 a.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
81 1_u64,
82 tmp_bytes.as_mut_ptr(),
83 )
84 });
85 (min_size..res.size()).for_each(|j| znx_zero_ref(res.at_mut(res_col, j)));
86 }
87 }
88}
89
90unsafe impl VecZnxIdftApplyTmpAImpl<Self> for FFT64Spqlios {
91 fn vec_znx_idft_apply_tmpa_impl<R, A>(module: &Module<Self>, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
92 where
93 R: VecZnxBigToMut<Self>,
94 A: VecZnxDftToMut<Self>,
95 {
96 let mut res: VecZnxBig<&mut [u8], Self> = res.to_mut();
97 let mut a_mut: VecZnxDft<&mut [u8], Self> = a.to_mut();
98
99 let min_size: usize = res.size().min(a_mut.size());
100
101 unsafe {
102 (0..min_size).for_each(|j| {
103 vec_znx_dft::vec_znx_idft_tmp_a(
104 module.ptr(),
105 res.at_mut_ptr(res_col, j) as *mut vec_znx_big::vec_znx_big_t,
106 1_u64,
107 a_mut.at_mut_ptr(a_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
108 1_u64,
109 )
110 });
111 (min_size..res.size()).for_each(|j| znx_zero_ref(res.at_mut(res_col, j)))
112 }
113 }
114}
115
116unsafe impl VecZnxIdftApplyConsumeImpl<Self> for FFT64Spqlios {
117 fn vec_znx_idft_apply_consume_impl<D: Data>(module: &Module<Self>, mut a: VecZnxDft<D, Self>) -> VecZnxBig<D, Self>
118 where
119 VecZnxDft<D, Self>: VecZnxDftToMut<Self>,
120 {
121 let mut a_mut: VecZnxDft<&mut [u8], Self> = a.to_mut();
122
123 unsafe {
124 // Rev col and rows because ZnxDft.sl() >= ZnxBig.sl()
125 (0..a_mut.size()).for_each(|j| {
126 (0..a_mut.cols()).for_each(|i| {
127 vec_znx_dft::vec_znx_idft_tmp_a(
128 module.ptr(),
129 a_mut.at_mut_ptr(i, j) as *mut vec_znx_big::vec_znx_big_t,
130 1_u64,
131 a_mut.at_mut_ptr(i, j) as *mut vec_znx_dft::vec_znx_dft_t,
132 1_u64,
133 )
134 });
135 });
136 }
137
138 a.into_big()
139 }
140}
141
142unsafe impl VecZnxDftApplyImpl<Self> for FFT64Spqlios {
143 fn vec_znx_dft_apply_impl<R, A>(
144 module: &Module<Self>,
145 step: usize,
146 offset: usize,
147 res: &mut R,
148 res_col: usize,
149 a: &A,
150 a_col: usize,
151 ) where
152 R: VecZnxDftToMut<Self>,
153 A: VecZnxToRef,
154 {
155 let mut res: VecZnxDft<&mut [u8], Self> = res.to_mut();
156 let a: VecZnx<&[u8]> = a.to_ref();
157 let steps: usize = a.size().div_ceil(step);
158 let min_steps: usize = res.size().min(steps);
159 unsafe {
160 (0..min_steps).for_each(|j| {
161 let limb: usize = offset + j * step;
162 if limb < a.size() {
163 vec_znx_dft::vec_znx_dft(
164 module.ptr(),
165 res.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
166 1_u64,
167 a.at_ptr(a_col, limb),
168 1_u64,
169 a.sl() as u64,
170 )
171 }
172 });
173 (min_steps..res.size()).for_each(|j| reim_zero_ref(res.at_mut(res_col, j)));
174 }
175 }
176}
177
178unsafe impl VecZnxDftAddImpl<Self> for FFT64Spqlios {
179 fn vec_znx_dft_add_impl<R, A, D>(module: &Module<Self>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
180 where
181 R: VecZnxDftToMut<Self>,
182 A: VecZnxDftToRef<Self>,
183 D: VecZnxDftToRef<Self>,
184 {
185 let mut res: VecZnxDft<&mut [u8], Self> = res.to_mut();
186 let a: VecZnxDft<&[u8], Self> = a.to_ref();
187 let b: VecZnxDft<&[u8], Self> = b.to_ref();
188
189 let res_size: usize = res.size();
190 let a_size: usize = a.size();
191 let b_size: usize = b.size();
192
193 unsafe {
194 if a_size <= b_size {
195 let sum_size: usize = a_size.min(res_size);
196 let cpy_size: usize = b_size.min(res_size);
197
198 (0..sum_size).for_each(|j| {
199 vec_znx_dft::vec_dft_add(
200 module.ptr(),
201 res.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
202 1,
203 a.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
204 1,
205 b.at_ptr(b_col, j) as *const vec_znx_dft::vec_znx_dft_t,
206 1,
207 );
208 });
209
210 for j in sum_size..cpy_size {
211 reim_copy_ref(res.at_mut(res_col, j), b.at(b_col, j));
212 }
213
214 for j in cpy_size..res_size {
215 reim_zero_ref(res.at_mut(res_col, j));
216 }
217 } else {
218 let sum_size: usize = b_size.min(res_size);
219 let cpy_size: usize = a_size.min(res_size);
220
221 (0..sum_size).for_each(|j| {
222 vec_znx_dft::vec_dft_add(
223 module.ptr(),
224 res.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
225 1,
226 a.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
227 1,
228 b.at_ptr(b_col, j) as *const vec_znx_dft::vec_znx_dft_t,
229 1,
230 );
231 });
232
233 for j in sum_size..cpy_size {
234 reim_copy_ref(res.at_mut(res_col, j), a.at(b_col, j));
235 }
236
237 for j in cpy_size..res_size {
238 reim_zero_ref(res.at_mut(res_col, j));
239 }
240 }
241 }
242 }
243}
244
245unsafe impl VecZnxDftAddInplaceImpl<Self> for FFT64Spqlios {
246 fn vec_znx_dft_add_inplace_impl<R, A>(module: &Module<Self>, res: &mut R, res_col: usize, a: &A, a_col: usize)
247 where
248 R: VecZnxDftToMut<Self>,
249 A: VecZnxDftToRef<Self>,
250 {
251 let mut res: VecZnxDft<&mut [u8], Self> = res.to_mut();
252 let a: VecZnxDft<&[u8], Self> = a.to_ref();
253
254 let min_size: usize = res.size().min(a.size());
255
256 unsafe {
257 (0..min_size).for_each(|j| {
258 vec_znx_dft::vec_dft_add(
259 module.ptr(),
260 res.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
261 1,
262 res.at_ptr(res_col, j) as *const vec_znx_dft::vec_znx_dft_t,
263 1,
264 a.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
265 1,
266 );
267 });
268 }
269 }
270}
271
272unsafe impl VecZnxDftSubImpl<Self> for FFT64Spqlios {
273 fn vec_znx_dft_sub_impl<R, A, D>(module: &Module<Self>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
274 where
275 R: VecZnxDftToMut<Self>,
276 A: VecZnxDftToRef<Self>,
277 D: VecZnxDftToRef<Self>,
278 {
279 let mut res: VecZnxDft<&mut [u8], Self> = res.to_mut();
280 let a: VecZnxDft<&[u8], Self> = a.to_ref();
281 let b: VecZnxDft<&[u8], Self> = b.to_ref();
282
283 unsafe {
284 let res_size: usize = res.size();
285 let a_size: usize = a.size();
286 let b_size: usize = b.size();
287
288 if a_size <= b_size {
289 let sum_size: usize = a_size.min(res_size);
290 let cpy_size: usize = b_size.min(res_size);
291
292 (0..sum_size).for_each(|j| {
293 vec_znx_dft::vec_dft_sub(
294 module.ptr(),
295 res.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
296 1,
297 a.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
298 1,
299 b.at_ptr(b_col, j) as *const vec_znx_dft::vec_znx_dft_t,
300 1,
301 );
302 });
303
304 for j in sum_size..cpy_size {
305 reim_negate_ref(res.at_mut(res_col, j), b.at(b_col, j));
306 }
307
308 for j in cpy_size..res_size {
309 reim_zero_ref(res.at_mut(res_col, j));
310 }
311 } else {
312 let sum_size: usize = b_size.min(res_size);
313 let cpy_size: usize = a_size.min(res_size);
314
315 (0..sum_size).for_each(|j| {
316 vec_znx_dft::vec_dft_sub(
317 module.ptr(),
318 res.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
319 1,
320 a.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
321 1,
322 b.at_ptr(b_col, j) as *const vec_znx_dft::vec_znx_dft_t,
323 1,
324 );
325 });
326
327 for j in sum_size..cpy_size {
328 reim_copy_ref(res.at_mut(res_col, j), a.at(a_col, j));
329 }
330
331 for j in cpy_size..res_size {
332 reim_zero_ref(res.at_mut(res_col, j));
333 }
334 }
335 }
336 }
337}
338
339unsafe impl VecZnxDftSubInplaceImpl<Self> for FFT64Spqlios {
340 fn vec_znx_dft_sub_inplace_impl<R, A>(module: &Module<Self>, res: &mut R, res_col: usize, a: &A, a_col: usize)
341 where
342 R: VecZnxDftToMut<Self>,
343 A: VecZnxDftToRef<Self>,
344 {
345 let mut res: VecZnxDft<&mut [u8], Self> = res.to_mut();
346 let a: VecZnxDft<&[u8], Self> = a.to_ref();
347
348 let min_size: usize = res.size().min(a.size());
349
350 unsafe {
351 (0..min_size).for_each(|j| {
352 vec_znx_dft::vec_dft_sub(
353 module.ptr(),
354 res.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
355 1,
356 res.at_ptr(res_col, j) as *const vec_znx_dft::vec_znx_dft_t,
357 1,
358 a.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
359 1,
360 );
361 });
362 }
363 }
364}
365
366unsafe impl VecZnxDftSubNegateInplaceImpl<Self> for FFT64Spqlios {
367 fn vec_znx_dft_sub_negate_inplace_impl<R, A>(module: &Module<Self>, res: &mut R, res_col: usize, a: &A, a_col: usize)
368 where
369 R: VecZnxDftToMut<Self>,
370 A: VecZnxDftToRef<Self>,
371 {
372 let mut res: VecZnxDft<&mut [u8], Self> = res.to_mut();
373 let a: VecZnxDft<&[u8], Self> = a.to_ref();
374
375 let min_size: usize = res.size().min(a.size());
376
377 unsafe {
378 (0..min_size).for_each(|j| {
379 vec_znx_dft::vec_dft_sub(
380 module.ptr(),
381 res.at_mut_ptr(res_col, j) as *mut vec_znx_dft::vec_znx_dft_t,
382 1,
383 a.at_ptr(a_col, j) as *const vec_znx_dft::vec_znx_dft_t,
384 1,
385 res.at_ptr(res_col, j) as *const vec_znx_dft::vec_znx_dft_t,
386 1,
387 );
388 });
389
390 for j in min_size..res.size() {
391 reim_negate_inplace_ref(res.at_mut(res_col, j));
392 }
393 }
394 }
395}
396
397unsafe impl VecZnxDftCopyImpl<Self> for FFT64Spqlios {
398 fn vec_znx_dft_copy_impl<R, A>(
399 _module: &Module<Self>,
400 step: usize,
401 offset: usize,
402 res: &mut R,
403 res_col: usize,
404 a: &A,
405 a_col: usize,
406 ) where
407 R: VecZnxDftToMut<Self>,
408 A: VecZnxDftToRef<Self>,
409 {
410 vec_znx_dft_copy(step, offset, res, res_col, a, a_col);
411 }
412}
413
414impl ReimCopy for FFT64Spqlios {
415 #[inline(always)]
416 fn reim_copy(res: &mut [f64], a: &[f64]) {
417 reim_copy_ref(res, a);
418 }
419}
420
421impl ReimZero for FFT64Spqlios {
422 #[inline(always)]
423 fn reim_zero(res: &mut [f64]) {
424 reim_zero_ref(res);
425 }
426}
427
428unsafe impl VecZnxDftZeroImpl<Self> for FFT64Spqlios {
429 fn vec_znx_dft_zero_impl<R>(_module: &Module<Self>, res: &mut R)
430 where
431 R: VecZnxDftToMut<Self>,
432 {
433 res.to_mut().data.fill(0);
434 }
435}