poulpy/backend/src/vec_znx_big_ops.rs
backend/src/vec_znx_big_ops.rsRaw
1use crate::ffi::vec_znx;
2use crate::znx_base::{ZnxInfos, ZnxView, ZnxViewMut};
3use crate::{
4 Backend, FFT64, Module, Scratch, VecZnx, VecZnxBig, VecZnxBigOwned, VecZnxBigToMut, VecZnxBigToRef, VecZnxScratch,
5 VecZnxToMut, VecZnxToRef, ZnxSliceSize, bytes_of_vec_znx_big,
6};
7
8pub trait VecZnxBigAlloc<B: Backend> {
9 /// Allocates a vector Z[X]/(X^N+1) that stores not normalized values.
10 fn new_vec_znx_big(&self, cols: usize, size: usize) -> VecZnxBigOwned<B>;
11
12 /// Returns a new [VecZnxBig] with the provided bytes array as backing array.
13 ///
14 /// Behavior: takes ownership of the backing array.
15 ///
16 /// # Arguments
17 ///
18 /// * `cols`: the number of polynomials..
19 /// * `size`: the number of polynomials per column.
20 /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_big].
21 ///
22 /// # Panics
23 /// If `bytes.len()` < [Module::bytes_of_vec_znx_big].
24 fn new_vec_znx_big_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxBigOwned<B>;
25
26 // /// Returns a new [VecZnxBig] with the provided bytes array as backing array.
27 // ///
28 // /// Behavior: the backing array is only borrowed.
29 // ///
30 // /// # Arguments
31 // ///
32 // /// * `cols`: the number of polynomials..
33 // /// * `size`: the number of polynomials per column.
34 // /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_big].
35 // ///
36 // /// # Panics
37 // /// If `bytes.len()` < [Module::bytes_of_vec_znx_big].
38 // fn new_vec_znx_big_from_bytes_borrow(&self, cols: usize, size: usize, tmp_bytes: &mut [u8]) -> VecZnxBig<B>;
39
40 /// Returns the minimum number of bytes necessary to allocate
41 /// a new [VecZnxBig] through [VecZnxBig::from_bytes].
42 fn bytes_of_vec_znx_big(&self, cols: usize, size: usize) -> usize;
43}
44
45pub trait VecZnxBigOps<BACKEND: Backend> {
46 /// Adds `a` to `b` and stores the result on `c`.
47 fn vec_znx_big_add<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
48 where
49 R: VecZnxBigToMut<BACKEND>,
50 A: VecZnxBigToRef<BACKEND>,
51 B: VecZnxBigToRef<BACKEND>;
52
53 /// Adds `a` to `b` and stores the result on `b`.
54 fn vec_znx_big_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
55 where
56 R: VecZnxBigToMut<BACKEND>,
57 A: VecZnxBigToRef<BACKEND>;
58
59 /// Adds `a` to `b` and stores the result on `c`.
60 fn vec_znx_big_add_small<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
61 where
62 R: VecZnxBigToMut<BACKEND>,
63 A: VecZnxBigToRef<BACKEND>,
64 B: VecZnxToRef;
65
66 /// Adds `a` to `b` and stores the result on `b`.
67 fn vec_znx_big_add_small_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
68 where
69 R: VecZnxBigToMut<BACKEND>,
70 A: VecZnxToRef;
71
72 /// Subtracts `a` to `b` and stores the result on `c`.
73 fn vec_znx_big_sub<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
74 where
75 R: VecZnxBigToMut<BACKEND>,
76 A: VecZnxBigToRef<BACKEND>,
77 B: VecZnxBigToRef<BACKEND>;
78
79 /// Subtracts `a` from `b` and stores the result on `b`.
80 fn vec_znx_big_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
81 where
82 R: VecZnxBigToMut<BACKEND>,
83 A: VecZnxBigToRef<BACKEND>;
84
85 /// Subtracts `b` from `a` and stores the result on `b`.
86 fn vec_znx_big_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
87 where
88 R: VecZnxBigToMut<BACKEND>,
89 A: VecZnxBigToRef<BACKEND>;
90
91 /// Subtracts `b` from `a` and stores the result on `c`.
92 fn vec_znx_big_sub_small_a<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
93 where
94 R: VecZnxBigToMut<BACKEND>,
95 A: VecZnxToRef,
96 B: VecZnxBigToRef<BACKEND>;
97
98 /// Subtracts `a` from `res` and stores the result on `res`.
99 fn vec_znx_big_sub_small_a_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
100 where
101 R: VecZnxBigToMut<BACKEND>,
102 A: VecZnxToRef;
103
104 /// Subtracts `b` from `a` and stores the result on `c`.
105 fn vec_znx_big_sub_small_b<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
106 where
107 R: VecZnxBigToMut<BACKEND>,
108 A: VecZnxBigToRef<BACKEND>,
109 B: VecZnxToRef;
110
111 /// Subtracts `res` from `a` and stores the result on `res`.
112 fn vec_znx_big_sub_small_b_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
113 where
114 R: VecZnxBigToMut<BACKEND>,
115 A: VecZnxToRef;
116
117 /// Negates `a` inplace.
118 fn vec_znx_big_negate_inplace<A>(&self, a: &mut A, a_col: usize)
119 where
120 A: VecZnxBigToMut<BACKEND>;
121
122 /// Normalizes `a` and stores the result on `b`.
123 ///
124 /// # Arguments
125 ///
126 /// * `basek`: normalization basis.
127 /// * `tmp_bytes`: scratch space of size at least [VecZnxBigOps::vec_znx_big_normalize].
128 fn vec_znx_big_normalize<R, A>(
129 &self,
130 basek: usize,
131 res: &mut R,
132 res_col: usize,
133 a: &A,
134 a_col: usize,
135 scratch: &mut Scratch,
136 ) where
137 R: VecZnxToMut,
138 A: VecZnxBigToRef<BACKEND>;
139
140 /// Applies the automorphism X^i -> X^ik on `a` and stores the result on `b`.
141 fn vec_znx_big_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
142 where
143 R: VecZnxBigToMut<BACKEND>,
144 A: VecZnxBigToRef<BACKEND>;
145
146 /// Applies the automorphism X^i -> X^ik on `a` and stores the result on `a`.
147 fn vec_znx_big_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
148 where
149 A: VecZnxBigToMut<BACKEND>;
150}
151
152pub trait VecZnxBigScratch {
153 /// Returns the minimum number of bytes to apply [VecZnxBigOps::vec_znx_big_normalize].
154 fn vec_znx_big_normalize_tmp_bytes(&self) -> usize;
155}
156
157impl<B: Backend> VecZnxBigAlloc<B> for Module<B> {
158 fn new_vec_znx_big(&self, cols: usize, size: usize) -> VecZnxBigOwned<B> {
159 VecZnxBig::new(self, cols, size)
160 }
161
162 fn new_vec_znx_big_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxBigOwned<B> {
163 VecZnxBig::new_from_bytes(self, cols, size, bytes)
164 }
165
166 fn bytes_of_vec_znx_big(&self, cols: usize, size: usize) -> usize {
167 bytes_of_vec_znx_big(self, cols, size)
168 }
169}
170
171impl VecZnxBigOps<FFT64> for Module<FFT64> {
172 fn vec_znx_big_add<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
173 where
174 R: VecZnxBigToMut<FFT64>,
175 A: VecZnxBigToRef<FFT64>,
176 B: VecZnxBigToRef<FFT64>,
177 {
178 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
179 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
180 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
181
182 #[cfg(debug_assertions)]
183 {
184 assert_eq!(a.n(), self.n());
185 assert_eq!(b.n(), self.n());
186 assert_eq!(res.n(), self.n());
187 assert_ne!(a.as_ptr(), b.as_ptr());
188 }
189 unsafe {
190 vec_znx::vec_znx_add(
191 self.ptr,
192 res.at_mut_ptr(res_col, 0),
193 res.size() as u64,
194 res.sl() as u64,
195 a.at_ptr(a_col, 0),
196 a.size() as u64,
197 a.sl() as u64,
198 b.at_ptr(b_col, 0),
199 b.size() as u64,
200 b.sl() as u64,
201 )
202 }
203 }
204
205 fn vec_znx_big_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
206 where
207 R: VecZnxBigToMut<FFT64>,
208 A: VecZnxBigToRef<FFT64>,
209 {
210 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
211 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
212
213 #[cfg(debug_assertions)]
214 {
215 assert_eq!(a.n(), self.n());
216 assert_eq!(res.n(), self.n());
217 }
218 unsafe {
219 vec_znx::vec_znx_add(
220 self.ptr,
221 res.at_mut_ptr(res_col, 0),
222 res.size() as u64,
223 res.sl() as u64,
224 a.at_ptr(a_col, 0),
225 a.size() as u64,
226 a.sl() as u64,
227 res.at_ptr(res_col, 0),
228 res.size() as u64,
229 res.sl() as u64,
230 )
231 }
232 }
233
234 fn vec_znx_big_sub<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
235 where
236 R: VecZnxBigToMut<FFT64>,
237 A: VecZnxBigToRef<FFT64>,
238 B: VecZnxBigToRef<FFT64>,
239 {
240 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
241 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
242 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
243
244 #[cfg(debug_assertions)]
245 {
246 assert_eq!(a.n(), self.n());
247 assert_eq!(b.n(), self.n());
248 assert_eq!(res.n(), self.n());
249 assert_ne!(a.as_ptr(), b.as_ptr());
250 }
251 unsafe {
252 vec_znx::vec_znx_sub(
253 self.ptr,
254 res.at_mut_ptr(res_col, 0),
255 res.size() as u64,
256 res.sl() as u64,
257 a.at_ptr(a_col, 0),
258 a.size() as u64,
259 a.sl() as u64,
260 b.at_ptr(b_col, 0),
261 b.size() as u64,
262 b.sl() as u64,
263 )
264 }
265 }
266
267 fn vec_znx_big_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
268 where
269 R: VecZnxBigToMut<FFT64>,
270 A: VecZnxBigToRef<FFT64>,
271 {
272 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
273 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
274
275 #[cfg(debug_assertions)]
276 {
277 assert_eq!(a.n(), self.n());
278 assert_eq!(res.n(), self.n());
279 }
280 unsafe {
281 vec_znx::vec_znx_sub(
282 self.ptr,
283 res.at_mut_ptr(res_col, 0),
284 res.size() as u64,
285 res.sl() as u64,
286 res.at_ptr(res_col, 0),
287 res.size() as u64,
288 res.sl() as u64,
289 a.at_ptr(a_col, 0),
290 a.size() as u64,
291 a.sl() as u64,
292 )
293 }
294 }
295
296 fn vec_znx_big_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
297 where
298 R: VecZnxBigToMut<FFT64>,
299 A: VecZnxBigToRef<FFT64>,
300 {
301 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
302 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
303
304 #[cfg(debug_assertions)]
305 {
306 assert_eq!(a.n(), self.n());
307 assert_eq!(res.n(), self.n());
308 }
309 unsafe {
310 vec_znx::vec_znx_sub(
311 self.ptr,
312 res.at_mut_ptr(res_col, 0),
313 res.size() as u64,
314 res.sl() as u64,
315 a.at_ptr(a_col, 0),
316 a.size() as u64,
317 a.sl() as u64,
318 res.at_ptr(res_col, 0),
319 res.size() as u64,
320 res.sl() as u64,
321 )
322 }
323 }
324
325 fn vec_znx_big_sub_small_b<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
326 where
327 R: VecZnxBigToMut<FFT64>,
328 A: VecZnxBigToRef<FFT64>,
329 B: VecZnxToRef,
330 {
331 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
332 let b: VecZnx<&[u8]> = b.to_ref();
333 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
334
335 #[cfg(debug_assertions)]
336 {
337 assert_eq!(a.n(), self.n());
338 assert_eq!(b.n(), self.n());
339 assert_eq!(res.n(), self.n());
340 assert_ne!(a.as_ptr(), b.as_ptr());
341 }
342 unsafe {
343 vec_znx::vec_znx_sub(
344 self.ptr,
345 res.at_mut_ptr(res_col, 0),
346 res.size() as u64,
347 res.sl() as u64,
348 a.at_ptr(a_col, 0),
349 a.size() as u64,
350 a.sl() as u64,
351 b.at_ptr(b_col, 0),
352 b.size() as u64,
353 b.sl() as u64,
354 )
355 }
356 }
357
358 fn vec_znx_big_sub_small_b_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
359 where
360 R: VecZnxBigToMut<FFT64>,
361 A: VecZnxToRef,
362 {
363 let a: VecZnx<&[u8]> = a.to_ref();
364 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
365
366 #[cfg(debug_assertions)]
367 {
368 assert_eq!(a.n(), self.n());
369 assert_eq!(res.n(), self.n());
370 }
371 unsafe {
372 vec_znx::vec_znx_sub(
373 self.ptr,
374 res.at_mut_ptr(res_col, 0),
375 res.size() as u64,
376 res.sl() as u64,
377 a.at_ptr(a_col, 0),
378 a.size() as u64,
379 a.sl() as u64,
380 res.at_ptr(res_col, 0),
381 res.size() as u64,
382 res.sl() as u64,
383 )
384 }
385 }
386
387 fn vec_znx_big_sub_small_a<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
388 where
389 R: VecZnxBigToMut<FFT64>,
390 A: VecZnxToRef,
391 B: VecZnxBigToRef<FFT64>,
392 {
393 let a: VecZnx<&[u8]> = a.to_ref();
394 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
395 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
396
397 #[cfg(debug_assertions)]
398 {
399 assert_eq!(a.n(), self.n());
400 assert_eq!(b.n(), self.n());
401 assert_eq!(res.n(), self.n());
402 assert_ne!(a.as_ptr(), b.as_ptr());
403 }
404 unsafe {
405 vec_znx::vec_znx_sub(
406 self.ptr,
407 res.at_mut_ptr(res_col, 0),
408 res.size() as u64,
409 res.sl() as u64,
410 a.at_ptr(a_col, 0),
411 a.size() as u64,
412 a.sl() as u64,
413 b.at_ptr(b_col, 0),
414 b.size() as u64,
415 b.sl() as u64,
416 )
417 }
418 }
419
420 fn vec_znx_big_sub_small_a_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
421 where
422 R: VecZnxBigToMut<FFT64>,
423 A: VecZnxToRef,
424 {
425 let a: VecZnx<&[u8]> = a.to_ref();
426 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
427
428 #[cfg(debug_assertions)]
429 {
430 assert_eq!(a.n(), self.n());
431 assert_eq!(res.n(), self.n());
432 }
433 unsafe {
434 vec_znx::vec_znx_sub(
435 self.ptr,
436 res.at_mut_ptr(res_col, 0),
437 res.size() as u64,
438 res.sl() as u64,
439 res.at_ptr(res_col, 0),
440 res.size() as u64,
441 res.sl() as u64,
442 a.at_ptr(a_col, 0),
443 a.size() as u64,
444 a.sl() as u64,
445 )
446 }
447 }
448
449 fn vec_znx_big_add_small<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
450 where
451 R: VecZnxBigToMut<FFT64>,
452 A: VecZnxBigToRef<FFT64>,
453 B: VecZnxToRef,
454 {
455 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
456 let b: VecZnx<&[u8]> = b.to_ref();
457 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
458
459 #[cfg(debug_assertions)]
460 {
461 assert_eq!(a.n(), self.n());
462 assert_eq!(b.n(), self.n());
463 assert_eq!(res.n(), self.n());
464 assert_ne!(a.as_ptr(), b.as_ptr());
465 }
466 unsafe {
467 vec_znx::vec_znx_add(
468 self.ptr,
469 res.at_mut_ptr(res_col, 0),
470 res.size() as u64,
471 res.sl() as u64,
472 a.at_ptr(a_col, 0),
473 a.size() as u64,
474 a.sl() as u64,
475 b.at_ptr(b_col, 0),
476 b.size() as u64,
477 b.sl() as u64,
478 )
479 }
480 }
481
482 fn vec_znx_big_add_small_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
483 where
484 R: VecZnxBigToMut<FFT64>,
485 A: VecZnxToRef,
486 {
487 let a: VecZnx<&[u8]> = a.to_ref();
488 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
489
490 #[cfg(debug_assertions)]
491 {
492 assert_eq!(a.n(), self.n());
493 assert_eq!(res.n(), self.n());
494 }
495 unsafe {
496 vec_znx::vec_znx_add(
497 self.ptr,
498 res.at_mut_ptr(res_col, 0),
499 res.size() as u64,
500 res.sl() as u64,
501 res.at_ptr(res_col, 0),
502 res.size() as u64,
503 res.sl() as u64,
504 a.at_ptr(a_col, 0),
505 a.size() as u64,
506 a.sl() as u64,
507 )
508 }
509 }
510
511 fn vec_znx_big_negate_inplace<A>(&self, a: &mut A, res_col: usize)
512 where
513 A: VecZnxBigToMut<FFT64>,
514 {
515 let mut a: VecZnxBig<&mut [u8], FFT64> = a.to_mut();
516 #[cfg(debug_assertions)]
517 {
518 assert_eq!(a.n(), self.n());
519 }
520 unsafe {
521 vec_znx::vec_znx_negate(
522 self.ptr,
523 a.at_mut_ptr(res_col, 0),
524 a.size() as u64,
525 a.sl() as u64,
526 a.at_ptr(res_col, 0),
527 a.size() as u64,
528 a.sl() as u64,
529 )
530 }
531 }
532
533 fn vec_znx_big_normalize<R, A>(
534 &self,
535 basek: usize,
536 res: &mut R,
537 res_col: usize,
538 a: &A,
539 a_col: usize,
540 scratch: &mut Scratch,
541 ) where
542 R: VecZnxToMut,
543 A: VecZnxBigToRef<FFT64>,
544 {
545 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
546 let mut res: VecZnx<&mut [u8]> = res.to_mut();
547
548 #[cfg(debug_assertions)]
549 {
550 assert_eq!(a.n(), self.n());
551 assert_eq!(res.n(), self.n());
552 //(Jay)Note: This is calling VezZnxOps::vec_znx_normalize_tmp_bytes and not VecZnxBigOps::vec_znx_big_normalize_tmp_bytes.
553 // In the FFT backend the tmp sizes are same but will be different in the NTT backend
554 // assert!(tmp_bytes.len() >= <Self as VecZnxOps<&mut [u8], & [u8]>>::vec_znx_normalize_tmp_bytes(&self));
555 // assert_alignement(tmp_bytes.as_ptr());
556 }
557
558 let (tmp_bytes, _) = scratch.tmp_slice(<Self as VecZnxBigScratch>::vec_znx_big_normalize_tmp_bytes(
559 &self,
560 ));
561 unsafe {
562 vec_znx::vec_znx_normalize_base2k(
563 self.ptr,
564 basek as u64,
565 res.at_mut_ptr(res_col, 0),
566 res.size() as u64,
567 res.sl() as u64,
568 a.at_ptr(a_col, 0),
569 a.size() as u64,
570 a.sl() as u64,
571 tmp_bytes.as_mut_ptr(),
572 );
573 }
574 }
575
576 fn vec_znx_big_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
577 where
578 R: VecZnxBigToMut<FFT64>,
579 A: VecZnxBigToRef<FFT64>,
580 {
581 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
582 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
583
584 #[cfg(debug_assertions)]
585 {
586 assert_eq!(a.n(), self.n());
587 assert_eq!(res.n(), self.n());
588 }
589 unsafe {
590 vec_znx::vec_znx_automorphism(
591 self.ptr,
592 k,
593 res.at_mut_ptr(res_col, 0),
594 res.size() as u64,
595 res.sl() as u64,
596 a.at_ptr(a_col, 0),
597 a.size() as u64,
598 a.sl() as u64,
599 )
600 }
601 }
602
603 fn vec_znx_big_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
604 where
605 A: VecZnxBigToMut<FFT64>,
606 {
607 let mut a: VecZnxBig<&mut [u8], FFT64> = a.to_mut();
608
609 #[cfg(debug_assertions)]
610 {
611 assert_eq!(a.n(), self.n());
612 }
613 unsafe {
614 vec_znx::vec_znx_automorphism(
615 self.ptr,
616 k,
617 a.at_mut_ptr(a_col, 0),
618 a.size() as u64,
619 a.sl() as u64,
620 a.at_ptr(a_col, 0),
621 a.size() as u64,
622 a.sl() as u64,
623 )
624 }
625 }
626}
627
628impl<B: Backend> VecZnxBigScratch for Module<B> {
629 fn vec_znx_big_normalize_tmp_bytes(&self) -> usize {
630 <Self as VecZnxScratch>::vec_znx_normalize_tmp_bytes(self)
631 }
632}