poulpy/poulpy-backend/src/implementation/cpu_spqlios/vec_znx_big_fft64.rs
poulpy-backend/src/implementation/cpu_spqlios/vec_znx_big_fft64.rsRaw
1use std::fmt;
2
3use rand_distr::{Distribution, Normal};
4
5use crate::{
6 hal::{
7 api::{
8 TakeSlice, VecZnxBigAddDistF64, VecZnxBigFillDistF64, VecZnxBigNormalizeTmpBytes, ZnxInfos, ZnxSliceSize, ZnxView,
9 ZnxViewMut,
10 },
11 layouts::{
12 Data, DataRef, Module, Scratch, VecZnx, VecZnxBig, VecZnxBigBytesOf, VecZnxBigOwned, VecZnxBigToMut, VecZnxBigToRef,
13 VecZnxToMut, VecZnxToRef,
14 },
15 oep::{
16 VecZnxBigAddDistF64Impl, VecZnxBigAddImpl, VecZnxBigAddInplaceImpl, VecZnxBigAddNormalImpl, VecZnxBigAddSmallImpl,
17 VecZnxBigAddSmallInplaceImpl, VecZnxBigAllocBytesImpl, VecZnxBigAllocImpl, VecZnxBigAutomorphismImpl,
18 VecZnxBigAutomorphismInplaceImpl, VecZnxBigFillDistF64Impl, VecZnxBigFillNormalImpl, VecZnxBigFromBytesImpl,
19 VecZnxBigNegateInplaceImpl, VecZnxBigNormalizeImpl, VecZnxBigNormalizeTmpBytesImpl, VecZnxBigSubABInplaceImpl,
20 VecZnxBigSubBAInplaceImpl, VecZnxBigSubImpl, VecZnxBigSubSmallAImpl, VecZnxBigSubSmallAInplaceImpl,
21 VecZnxBigSubSmallBImpl, VecZnxBigSubSmallBInplaceImpl,
22 },
23 source::Source,
24 },
25 implementation::cpu_spqlios::{ffi::vec_znx, module_fft64::FFT64},
26};
27
28const VEC_ZNX_BIG_FFT64_WORDSIZE: usize = 1;
29
30impl<D: DataRef> ZnxView for VecZnxBig<D, FFT64> {
31 type Scalar = i64;
32}
33
34impl<D: Data> VecZnxBigBytesOf for VecZnxBig<D, FFT64> {
35 fn bytes_of(n: usize, cols: usize, size: usize) -> usize {
36 VEC_ZNX_BIG_FFT64_WORDSIZE * n * cols * size * size_of::<f64>()
37 }
38}
39
40impl<D: Data> ZnxSliceSize for VecZnxBig<D, FFT64> {
41 fn sl(&self) -> usize {
42 VEC_ZNX_BIG_FFT64_WORDSIZE * self.n() * self.cols()
43 }
44}
45
46unsafe impl VecZnxBigAllocImpl<FFT64> for FFT64 {
47 fn vec_znx_big_alloc_impl(n: usize, cols: usize, size: usize) -> VecZnxBigOwned<FFT64> {
48 VecZnxBig::<Vec<u8>, FFT64>::new(n, cols, size)
49 }
50}
51
52unsafe impl VecZnxBigFromBytesImpl<FFT64> for FFT64 {
53 fn vec_znx_big_from_bytes_impl(n: usize, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxBigOwned<FFT64> {
54 VecZnxBig::<Vec<u8>, FFT64>::new_from_bytes(n, cols, size, bytes)
55 }
56}
57
58unsafe impl VecZnxBigAllocBytesImpl<FFT64> for FFT64 {
59 fn vec_znx_big_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize {
60 VecZnxBig::<Vec<u8>, FFT64>::bytes_of(n, cols, size)
61 }
62}
63
64unsafe impl VecZnxBigAddDistF64Impl<FFT64> for FFT64 {
65 fn add_dist_f64_impl<R: VecZnxBigToMut<FFT64>, D: Distribution<f64>>(
66 _module: &Module<FFT64>,
67 basek: usize,
68 res: &mut R,
69 res_col: usize,
70 k: usize,
71 source: &mut Source,
72 dist: D,
73 bound: f64,
74 ) {
75 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
76 assert!(
77 (bound.log2().ceil() as i64) < 64,
78 "invalid bound: ceil(log2(bound))={} > 63",
79 (bound.log2().ceil() as i64)
80 );
81
82 let limb: usize = k.div_ceil(basek) - 1;
83 let basek_rem: usize = (limb + 1) * basek - k;
84
85 if basek_rem != 0 {
86 res.at_mut(res_col, limb).iter_mut().for_each(|x| {
87 let mut dist_f64: f64 = dist.sample(source);
88 while dist_f64.abs() > bound {
89 dist_f64 = dist.sample(source)
90 }
91 *x += (dist_f64.round() as i64) << basek_rem;
92 });
93 } else {
94 res.at_mut(res_col, limb).iter_mut().for_each(|x| {
95 let mut dist_f64: f64 = dist.sample(source);
96 while dist_f64.abs() > bound {
97 dist_f64 = dist.sample(source)
98 }
99 *x += dist_f64.round() as i64
100 });
101 }
102 }
103}
104
105unsafe impl VecZnxBigAddNormalImpl<FFT64> for FFT64 {
106 fn add_normal_impl<R: VecZnxBigToMut<FFT64>>(
107 module: &Module<FFT64>,
108 basek: usize,
109 res: &mut R,
110 res_col: usize,
111 k: usize,
112 source: &mut Source,
113 sigma: f64,
114 bound: f64,
115 ) {
116 module.vec_znx_big_add_dist_f64(
117 basek,
118 res,
119 res_col,
120 k,
121 source,
122 Normal::new(0.0, sigma).unwrap(),
123 bound,
124 );
125 }
126}
127
128unsafe impl VecZnxBigFillDistF64Impl<FFT64> for FFT64 {
129 fn fill_dist_f64_impl<R: VecZnxBigToMut<FFT64>, D: Distribution<f64>>(
130 _module: &Module<FFT64>,
131 basek: usize,
132 res: &mut R,
133 res_col: usize,
134 k: usize,
135 source: &mut Source,
136 dist: D,
137 bound: f64,
138 ) {
139 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
140 assert!(
141 (bound.log2().ceil() as i64) < 64,
142 "invalid bound: ceil(log2(bound))={} > 63",
143 (bound.log2().ceil() as i64)
144 );
145
146 let limb: usize = k.div_ceil(basek) - 1;
147 let basek_rem: usize = (limb + 1) * basek - k;
148
149 if basek_rem != 0 {
150 res.at_mut(res_col, limb).iter_mut().for_each(|x| {
151 let mut dist_f64: f64 = dist.sample(source);
152 while dist_f64.abs() > bound {
153 dist_f64 = dist.sample(source)
154 }
155 *x = (dist_f64.round() as i64) << basek_rem;
156 });
157 } else {
158 res.at_mut(res_col, limb).iter_mut().for_each(|x| {
159 let mut dist_f64: f64 = dist.sample(source);
160 while dist_f64.abs() > bound {
161 dist_f64 = dist.sample(source)
162 }
163 *x = dist_f64.round() as i64
164 });
165 }
166 }
167}
168
169unsafe impl VecZnxBigFillNormalImpl<FFT64> for FFT64 {
170 fn fill_normal_impl<R: VecZnxBigToMut<FFT64>>(
171 module: &Module<FFT64>,
172 basek: usize,
173 res: &mut R,
174 res_col: usize,
175 k: usize,
176 source: &mut Source,
177 sigma: f64,
178 bound: f64,
179 ) {
180 module.vec_znx_big_fill_dist_f64(
181 basek,
182 res,
183 res_col,
184 k,
185 source,
186 Normal::new(0.0, sigma).unwrap(),
187 bound,
188 );
189 }
190}
191
192unsafe impl VecZnxBigAddImpl<FFT64> for FFT64 {
193 /// Adds `a` to `b` and stores the result on `c`.
194 fn vec_znx_big_add_impl<R, A, B>(
195 module: &Module<FFT64>,
196 res: &mut R,
197 res_col: usize,
198 a: &A,
199 a_col: usize,
200 b: &B,
201 b_col: usize,
202 ) where
203 R: VecZnxBigToMut<FFT64>,
204 A: VecZnxBigToRef<FFT64>,
205 B: VecZnxBigToRef<FFT64>,
206 {
207 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
208 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
209 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
210
211 #[cfg(debug_assertions)]
212 {
213 assert_eq!(a.n(), res.n());
214 assert_eq!(b.n(), res.n());
215 assert_ne!(a.as_ptr(), b.as_ptr());
216 }
217 unsafe {
218 vec_znx::vec_znx_add(
219 module.ptr(),
220 res.at_mut_ptr(res_col, 0),
221 res.size() as u64,
222 res.sl() as u64,
223 a.at_ptr(a_col, 0),
224 a.size() as u64,
225 a.sl() as u64,
226 b.at_ptr(b_col, 0),
227 b.size() as u64,
228 b.sl() as u64,
229 )
230 }
231 }
232}
233
234unsafe impl VecZnxBigAddInplaceImpl<FFT64> for FFT64 {
235 /// Adds `a` to `b` and stores the result on `b`.
236 fn vec_znx_big_add_inplace_impl<R, A>(module: &Module<FFT64>, res: &mut R, res_col: usize, a: &A, a_col: usize)
237 where
238 R: VecZnxBigToMut<FFT64>,
239 A: VecZnxBigToRef<FFT64>,
240 {
241 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
242 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
243
244 #[cfg(debug_assertions)]
245 {
246 assert_eq!(a.n(), res.n());
247 }
248 unsafe {
249 vec_znx::vec_znx_add(
250 module.ptr(),
251 res.at_mut_ptr(res_col, 0),
252 res.size() as u64,
253 res.sl() as u64,
254 a.at_ptr(a_col, 0),
255 a.size() as u64,
256 a.sl() as u64,
257 res.at_ptr(res_col, 0),
258 res.size() as u64,
259 res.sl() as u64,
260 )
261 }
262 }
263}
264
265unsafe impl VecZnxBigAddSmallImpl<FFT64> for FFT64 {
266 /// Adds `a` to `b` and stores the result on `c`.
267 fn vec_znx_big_add_small_impl<R, A, B>(
268 module: &Module<FFT64>,
269 res: &mut R,
270 res_col: usize,
271 a: &A,
272 a_col: usize,
273 b: &B,
274 b_col: usize,
275 ) where
276 R: VecZnxBigToMut<FFT64>,
277 A: VecZnxBigToRef<FFT64>,
278 B: VecZnxToRef,
279 {
280 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
281 let b: VecZnx<&[u8]> = b.to_ref();
282 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
283
284 #[cfg(debug_assertions)]
285 {
286 assert_eq!(a.n(), res.n());
287 assert_eq!(b.n(), res.n());
288 assert_ne!(a.as_ptr(), b.as_ptr());
289 }
290 unsafe {
291 vec_znx::vec_znx_add(
292 module.ptr(),
293 res.at_mut_ptr(res_col, 0),
294 res.size() as u64,
295 res.sl() as u64,
296 a.at_ptr(a_col, 0),
297 a.size() as u64,
298 a.sl() as u64,
299 b.at_ptr(b_col, 0),
300 b.size() as u64,
301 b.sl() as u64,
302 )
303 }
304 }
305}
306
307unsafe impl VecZnxBigAddSmallInplaceImpl<FFT64> for FFT64 {
308 /// Adds `a` to `b` and stores the result on `b`.
309 fn vec_znx_big_add_small_inplace_impl<R, A>(module: &Module<FFT64>, res: &mut R, res_col: usize, a: &A, a_col: usize)
310 where
311 R: VecZnxBigToMut<FFT64>,
312 A: VecZnxToRef,
313 {
314 let a: VecZnx<&[u8]> = a.to_ref();
315 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
316
317 #[cfg(debug_assertions)]
318 {
319 assert_eq!(a.n(), res.n());
320 }
321 unsafe {
322 vec_znx::vec_znx_add(
323 module.ptr(),
324 res.at_mut_ptr(res_col, 0),
325 res.size() as u64,
326 res.sl() as u64,
327 res.at_ptr(res_col, 0),
328 res.size() as u64,
329 res.sl() as u64,
330 a.at_ptr(a_col, 0),
331 a.size() as u64,
332 a.sl() as u64,
333 )
334 }
335 }
336}
337
338unsafe impl VecZnxBigSubImpl<FFT64> for FFT64 {
339 /// Subtracts `a` to `b` and stores the result on `c`.
340 fn vec_znx_big_sub_impl<R, A, B>(
341 module: &Module<FFT64>,
342 res: &mut R,
343 res_col: usize,
344 a: &A,
345 a_col: usize,
346 b: &B,
347 b_col: usize,
348 ) where
349 R: VecZnxBigToMut<FFT64>,
350 A: VecZnxBigToRef<FFT64>,
351 B: VecZnxBigToRef<FFT64>,
352 {
353 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
354 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
355 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
356
357 #[cfg(debug_assertions)]
358 {
359 assert_eq!(a.n(), res.n());
360 assert_eq!(b.n(), res.n());
361 assert_ne!(a.as_ptr(), b.as_ptr());
362 }
363 unsafe {
364 vec_znx::vec_znx_sub(
365 module.ptr(),
366 res.at_mut_ptr(res_col, 0),
367 res.size() as u64,
368 res.sl() as u64,
369 a.at_ptr(a_col, 0),
370 a.size() as u64,
371 a.sl() as u64,
372 b.at_ptr(b_col, 0),
373 b.size() as u64,
374 b.sl() as u64,
375 )
376 }
377 }
378}
379
380unsafe impl VecZnxBigSubABInplaceImpl<FFT64> for FFT64 {
381 /// Subtracts `a` from `b` and stores the result on `b`.
382 fn vec_znx_big_sub_ab_inplace_impl<R, A>(module: &Module<FFT64>, res: &mut R, res_col: usize, a: &A, a_col: usize)
383 where
384 R: VecZnxBigToMut<FFT64>,
385 A: VecZnxBigToRef<FFT64>,
386 {
387 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
388 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
389
390 #[cfg(debug_assertions)]
391 {
392 assert_eq!(a.n(), res.n());
393 }
394 unsafe {
395 vec_znx::vec_znx_sub(
396 module.ptr(),
397 res.at_mut_ptr(res_col, 0),
398 res.size() as u64,
399 res.sl() as u64,
400 res.at_ptr(res_col, 0),
401 res.size() as u64,
402 res.sl() as u64,
403 a.at_ptr(a_col, 0),
404 a.size() as u64,
405 a.sl() as u64,
406 )
407 }
408 }
409}
410
411unsafe impl VecZnxBigSubBAInplaceImpl<FFT64> for FFT64 {
412 /// Subtracts `b` from `a` and stores the result on `b`.
413 fn vec_znx_big_sub_ba_inplace_impl<R, A>(module: &Module<FFT64>, res: &mut R, res_col: usize, a: &A, a_col: usize)
414 where
415 R: VecZnxBigToMut<FFT64>,
416 A: VecZnxBigToRef<FFT64>,
417 {
418 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
419 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
420
421 #[cfg(debug_assertions)]
422 {
423 assert_eq!(a.n(), res.n());
424 }
425 unsafe {
426 vec_znx::vec_znx_sub(
427 module.ptr(),
428 res.at_mut_ptr(res_col, 0),
429 res.size() as u64,
430 res.sl() as u64,
431 a.at_ptr(a_col, 0),
432 a.size() as u64,
433 a.sl() as u64,
434 res.at_ptr(res_col, 0),
435 res.size() as u64,
436 res.sl() as u64,
437 )
438 }
439 }
440}
441
442unsafe impl VecZnxBigSubSmallAImpl<FFT64> for FFT64 {
443 /// Subtracts `b` from `a` and stores the result on `c`.
444 fn vec_znx_big_sub_small_a_impl<R, A, B>(
445 module: &Module<FFT64>,
446 res: &mut R,
447 res_col: usize,
448 a: &A,
449 a_col: usize,
450 b: &B,
451 b_col: usize,
452 ) where
453 R: VecZnxBigToMut<FFT64>,
454 A: VecZnxToRef,
455 B: VecZnxBigToRef<FFT64>,
456 {
457 let a: VecZnx<&[u8]> = a.to_ref();
458 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
459 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
460
461 #[cfg(debug_assertions)]
462 {
463 assert_eq!(a.n(), res.n());
464 assert_eq!(b.n(), res.n());
465 assert_ne!(a.as_ptr(), b.as_ptr());
466 }
467 unsafe {
468 vec_znx::vec_znx_sub(
469 module.ptr(),
470 res.at_mut_ptr(res_col, 0),
471 res.size() as u64,
472 res.sl() as u64,
473 a.at_ptr(a_col, 0),
474 a.size() as u64,
475 a.sl() as u64,
476 b.at_ptr(b_col, 0),
477 b.size() as u64,
478 b.sl() as u64,
479 )
480 }
481 }
482}
483
484unsafe impl VecZnxBigSubSmallAInplaceImpl<FFT64> for FFT64 {
485 /// Subtracts `a` from `res` and stores the result on `res`.
486 fn vec_znx_big_sub_small_a_inplace_impl<R, A>(module: &Module<FFT64>, res: &mut R, res_col: usize, a: &A, a_col: usize)
487 where
488 R: VecZnxBigToMut<FFT64>,
489 A: VecZnxToRef,
490 {
491 let a: VecZnx<&[u8]> = a.to_ref();
492 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
493
494 #[cfg(debug_assertions)]
495 {
496 assert_eq!(a.n(), res.n());
497 }
498 unsafe {
499 vec_znx::vec_znx_sub(
500 module.ptr(),
501 res.at_mut_ptr(res_col, 0),
502 res.size() as u64,
503 res.sl() as u64,
504 res.at_ptr(res_col, 0),
505 res.size() as u64,
506 res.sl() as u64,
507 a.at_ptr(a_col, 0),
508 a.size() as u64,
509 a.sl() as u64,
510 )
511 }
512 }
513}
514
515unsafe impl VecZnxBigSubSmallBImpl<FFT64> for FFT64 {
516 /// Subtracts `b` from `a` and stores the result on `c`.
517 fn vec_znx_big_sub_small_b_impl<R, A, B>(
518 module: &Module<FFT64>,
519 res: &mut R,
520 res_col: usize,
521 a: &A,
522 a_col: usize,
523 b: &B,
524 b_col: usize,
525 ) where
526 R: VecZnxBigToMut<FFT64>,
527 A: VecZnxBigToRef<FFT64>,
528 B: VecZnxToRef,
529 {
530 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
531 let b: VecZnx<&[u8]> = b.to_ref();
532 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
533
534 #[cfg(debug_assertions)]
535 {
536 assert_eq!(a.n(), res.n());
537 assert_eq!(b.n(), res.n());
538 assert_ne!(a.as_ptr(), b.as_ptr());
539 }
540 unsafe {
541 vec_znx::vec_znx_sub(
542 module.ptr(),
543 res.at_mut_ptr(res_col, 0),
544 res.size() as u64,
545 res.sl() as u64,
546 a.at_ptr(a_col, 0),
547 a.size() as u64,
548 a.sl() as u64,
549 b.at_ptr(b_col, 0),
550 b.size() as u64,
551 b.sl() as u64,
552 )
553 }
554 }
555}
556
557unsafe impl VecZnxBigSubSmallBInplaceImpl<FFT64> for FFT64 {
558 /// Subtracts `res` from `a` and stores the result on `res`.
559 fn vec_znx_big_sub_small_b_inplace_impl<R, A>(module: &Module<FFT64>, res: &mut R, res_col: usize, a: &A, a_col: usize)
560 where
561 R: VecZnxBigToMut<FFT64>,
562 A: VecZnxToRef,
563 {
564 let a: VecZnx<&[u8]> = a.to_ref();
565 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
566
567 #[cfg(debug_assertions)]
568 {
569 assert_eq!(a.n(), res.n());
570 }
571 unsafe {
572 vec_znx::vec_znx_sub(
573 module.ptr(),
574 res.at_mut_ptr(res_col, 0),
575 res.size() as u64,
576 res.sl() as u64,
577 a.at_ptr(a_col, 0),
578 a.size() as u64,
579 a.sl() as u64,
580 res.at_ptr(res_col, 0),
581 res.size() as u64,
582 res.sl() as u64,
583 )
584 }
585 }
586}
587
588unsafe impl VecZnxBigNegateInplaceImpl<FFT64> for FFT64 {
589 fn vec_znx_big_negate_inplace_impl<A>(module: &Module<FFT64>, a: &mut A, a_col: usize)
590 where
591 A: VecZnxBigToMut<FFT64>,
592 {
593 let mut a: VecZnxBig<&mut [u8], FFT64> = a.to_mut();
594 unsafe {
595 vec_znx::vec_znx_negate(
596 module.ptr(),
597 a.at_mut_ptr(a_col, 0),
598 a.size() as u64,
599 a.sl() as u64,
600 a.at_ptr(a_col, 0),
601 a.size() as u64,
602 a.sl() as u64,
603 )
604 }
605 }
606}
607
608unsafe impl VecZnxBigNormalizeTmpBytesImpl<FFT64> for FFT64 {
609 fn vec_znx_big_normalize_tmp_bytes_impl(module: &Module<FFT64>, n: usize) -> usize {
610 unsafe { vec_znx::vec_znx_normalize_base2k_tmp_bytes(module.ptr(), n as u64) as usize }
611 }
612}
613
614unsafe impl VecZnxBigNormalizeImpl<FFT64> for FFT64 {
615 fn vec_znx_big_normalize_impl<R, A>(
616 module: &Module<FFT64>,
617 basek: usize,
618 res: &mut R,
619 res_col: usize,
620 a: &A,
621 a_col: usize,
622 scratch: &mut Scratch<FFT64>,
623 ) where
624 R: VecZnxToMut,
625 A: VecZnxBigToRef<FFT64>,
626 {
627 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
628 let mut res: VecZnx<&mut [u8]> = res.to_mut();
629
630 #[cfg(debug_assertions)]
631 {
632 assert_eq!(res.n(), a.n());
633 }
634
635 let (tmp_bytes, _) = scratch.take_slice(module.vec_znx_big_normalize_tmp_bytes(a.n()));
636 unsafe {
637 vec_znx::vec_znx_normalize_base2k(
638 module.ptr(),
639 a.n() as u64,
640 basek as u64,
641 res.at_mut_ptr(res_col, 0),
642 res.size() as u64,
643 res.sl() as u64,
644 a.at_ptr(a_col, 0),
645 a.size() as u64,
646 a.sl() as u64,
647 tmp_bytes.as_mut_ptr(),
648 );
649 }
650 }
651}
652
653unsafe impl VecZnxBigAutomorphismImpl<FFT64> for FFT64 {
654 /// Applies the automorphism X^i -> X^ik on `a` and stores the result on `b`.
655 fn vec_znx_big_automorphism_impl<R, A>(module: &Module<FFT64>, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
656 where
657 R: VecZnxBigToMut<FFT64>,
658 A: VecZnxBigToRef<FFT64>,
659 {
660 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
661 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
662
663 #[cfg(debug_assertions)]
664 {
665 assert_eq!(a.n(), res.n());
666 }
667 unsafe {
668 vec_znx::vec_znx_automorphism(
669 module.ptr(),
670 k,
671 res.at_mut_ptr(res_col, 0),
672 res.size() as u64,
673 res.sl() as u64,
674 a.at_ptr(a_col, 0),
675 a.size() as u64,
676 a.sl() as u64,
677 )
678 }
679 }
680}
681
682unsafe impl VecZnxBigAutomorphismInplaceImpl<FFT64> for FFT64 {
683 /// Applies the automorphism X^i -> X^ik on `a` and stores the result on `a`.
684 fn vec_znx_big_automorphism_inplace_impl<A>(module: &Module<FFT64>, k: i64, a: &mut A, a_col: usize)
685 where
686 A: VecZnxBigToMut<FFT64>,
687 {
688 let mut a: VecZnxBig<&mut [u8], FFT64> = a.to_mut();
689 unsafe {
690 vec_znx::vec_znx_automorphism(
691 module.ptr(),
692 k,
693 a.at_mut_ptr(a_col, 0),
694 a.size() as u64,
695 a.sl() as u64,
696 a.at_ptr(a_col, 0),
697 a.size() as u64,
698 a.sl() as u64,
699 )
700 }
701 }
702}
703
704impl<D: DataRef> fmt::Display for VecZnxBig<D, FFT64> {
705 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
706 writeln!(
707 f,
708 "VecZnxBig(n={}, cols={}, size={})",
709 self.n, self.cols, self.size
710 )?;
711
712 for col in 0..self.cols {
713 writeln!(f, "Column {}:", col)?;
714 for size in 0..self.size {
715 let coeffs = self.at(col, size);
716 write!(f, " Size {}: [", size)?;
717
718 let max_show = 100;
719 let show_count = coeffs.len().min(max_show);
720
721 for (i, &coeff) in coeffs.iter().take(show_count).enumerate() {
722 if i > 0 {
723 write!(f, ", ")?;
724 }
725 write!(f, "{}", coeff)?;
726 }
727
728 if coeffs.len() > max_show {
729 write!(f, ", ... ({} more)", coeffs.len() - max_show)?;
730 }
731
732 writeln!(f, "]")?;
733 }
734 }
735 Ok(())
736 }
737}