poulpy/base2k/src/vec_znx_big_ops.rs
base2k/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) where A: VecZnxBigToMut<BACKEND>;
119
120 /// Normalizes `a` and stores the result on `b`.
121 ///
122 /// # Arguments
123 ///
124 /// * `log_base2k`: normalization basis.
125 /// * `tmp_bytes`: scratch space of size at least [VecZnxBigOps::vec_znx_big_normalize].
126 fn vec_znx_big_normalize<R, A>(
127 &self,
128 log_base2k: usize,
129 res: &mut R,
130 res_col: usize,
131 a: &A,
132 a_col: usize,
133 scratch: &mut Scratch,
134 ) where
135 R: VecZnxToMut,
136 A: VecZnxBigToRef<BACKEND>;
137
138 /// Applies the automorphism X^i -> X^ik on `a` and stores the result on `b`.
139 fn vec_znx_big_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
140 where
141 R: VecZnxBigToMut<BACKEND>,
142 A: VecZnxBigToRef<BACKEND>;
143
144 /// Applies the automorphism X^i -> X^ik on `a` and stores the result on `a`.
145 fn vec_znx_big_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
146 where
147 A: VecZnxBigToMut<BACKEND>;
148}
149
150pub trait VecZnxBigScratch {
151 /// Returns the minimum number of bytes to apply [VecZnxBigOps::vec_znx_big_normalize].
152 fn vec_znx_big_normalize_tmp_bytes(&self) -> usize;
153}
154
155impl<B: Backend> VecZnxBigAlloc<B> for Module<B> {
156 fn new_vec_znx_big(&self, cols: usize, size: usize) -> VecZnxBigOwned<B> {
157 VecZnxBig::new(self, cols, size)
158 }
159
160 fn new_vec_znx_big_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxBigOwned<B> {
161 VecZnxBig::new_from_bytes(self, cols, size, bytes)
162 }
163
164 fn bytes_of_vec_znx_big(&self, cols: usize, size: usize) -> usize {
165 bytes_of_vec_znx_big(self, cols, size)
166 }
167}
168
169impl VecZnxBigOps<FFT64> for Module<FFT64> {
170 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)
171 where
172 R: VecZnxBigToMut<FFT64>,
173 A: VecZnxBigToRef<FFT64>,
174 B: VecZnxBigToRef<FFT64>,
175 {
176 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
177 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
178 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
179
180 #[cfg(debug_assertions)]
181 {
182 assert_eq!(a.n(), self.n());
183 assert_eq!(b.n(), self.n());
184 assert_eq!(res.n(), self.n());
185 assert_ne!(a.as_ptr(), b.as_ptr());
186 }
187 unsafe {
188 vec_znx::vec_znx_add(
189 self.ptr,
190 res.at_mut_ptr(res_col, 0),
191 res.size() as u64,
192 res.sl() as u64,
193 a.at_ptr(a_col, 0),
194 a.size() as u64,
195 a.sl() as u64,
196 b.at_ptr(b_col, 0),
197 b.size() as u64,
198 b.sl() as u64,
199 )
200 }
201 }
202
203 fn vec_znx_big_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
204 where
205 R: VecZnxBigToMut<FFT64>,
206 A: VecZnxBigToRef<FFT64>,
207 {
208 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
209 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
210
211 #[cfg(debug_assertions)]
212 {
213 assert_eq!(a.n(), self.n());
214 assert_eq!(res.n(), self.n());
215 }
216 unsafe {
217 vec_znx::vec_znx_add(
218 self.ptr,
219 res.at_mut_ptr(res_col, 0),
220 res.size() as u64,
221 res.sl() as u64,
222 a.at_ptr(a_col, 0),
223 a.size() as u64,
224 a.sl() as u64,
225 res.at_ptr(res_col, 0),
226 res.size() as u64,
227 res.sl() as u64,
228 )
229 }
230 }
231
232 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)
233 where
234 R: VecZnxBigToMut<FFT64>,
235 A: VecZnxBigToRef<FFT64>,
236 B: VecZnxBigToRef<FFT64>,
237 {
238 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
239 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
240 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
241
242 #[cfg(debug_assertions)]
243 {
244 assert_eq!(a.n(), self.n());
245 assert_eq!(b.n(), self.n());
246 assert_eq!(res.n(), self.n());
247 assert_ne!(a.as_ptr(), b.as_ptr());
248 }
249 unsafe {
250 vec_znx::vec_znx_sub(
251 self.ptr,
252 res.at_mut_ptr(res_col, 0),
253 res.size() as u64,
254 res.sl() as u64,
255 a.at_ptr(a_col, 0),
256 a.size() as u64,
257 a.sl() as u64,
258 b.at_ptr(b_col, 0),
259 b.size() as u64,
260 b.sl() as u64,
261 )
262 }
263 }
264
265 fn vec_znx_big_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
266 where
267 R: VecZnxBigToMut<FFT64>,
268 A: VecZnxBigToRef<FFT64>,
269 {
270 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
271 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
272
273 #[cfg(debug_assertions)]
274 {
275 assert_eq!(a.n(), self.n());
276 assert_eq!(res.n(), self.n());
277 }
278 unsafe {
279 vec_znx::vec_znx_sub(
280 self.ptr,
281 res.at_mut_ptr(res_col, 0),
282 res.size() as u64,
283 res.sl() as u64,
284 res.at_ptr(res_col, 0),
285 res.size() as u64,
286 res.sl() as u64,
287 a.at_ptr(a_col, 0),
288 a.size() as u64,
289 a.sl() as u64,
290 )
291 }
292 }
293
294 fn vec_znx_big_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
295 where
296 R: VecZnxBigToMut<FFT64>,
297 A: VecZnxBigToRef<FFT64>,
298 {
299 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
300 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
301
302 #[cfg(debug_assertions)]
303 {
304 assert_eq!(a.n(), self.n());
305 assert_eq!(res.n(), self.n());
306 }
307 unsafe {
308 vec_znx::vec_znx_sub(
309 self.ptr,
310 res.at_mut_ptr(res_col, 0),
311 res.size() as u64,
312 res.sl() as u64,
313 a.at_ptr(a_col, 0),
314 a.size() as u64,
315 a.sl() as u64,
316 res.at_ptr(res_col, 0),
317 res.size() as u64,
318 res.sl() as u64,
319 )
320 }
321 }
322
323 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)
324 where
325 R: VecZnxBigToMut<FFT64>,
326 A: VecZnxBigToRef<FFT64>,
327 B: VecZnxToRef,
328 {
329 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
330 let b: VecZnx<&[u8]> = b.to_ref();
331 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
332
333 #[cfg(debug_assertions)]
334 {
335 assert_eq!(a.n(), self.n());
336 assert_eq!(b.n(), self.n());
337 assert_eq!(res.n(), self.n());
338 assert_ne!(a.as_ptr(), b.as_ptr());
339 }
340 unsafe {
341 vec_znx::vec_znx_sub(
342 self.ptr,
343 res.at_mut_ptr(res_col, 0),
344 res.size() as u64,
345 res.sl() as u64,
346 a.at_ptr(a_col, 0),
347 a.size() as u64,
348 a.sl() as u64,
349 b.at_ptr(b_col, 0),
350 b.size() as u64,
351 b.sl() as u64,
352 )
353 }
354 }
355
356 fn vec_znx_big_sub_small_b_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
357 where
358 R: VecZnxBigToMut<FFT64>,
359 A: VecZnxToRef,
360 {
361 let a: VecZnx<&[u8]> = a.to_ref();
362 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
363
364 #[cfg(debug_assertions)]
365 {
366 assert_eq!(a.n(), self.n());
367 assert_eq!(res.n(), self.n());
368 }
369 unsafe {
370 vec_znx::vec_znx_sub(
371 self.ptr,
372 res.at_mut_ptr(res_col, 0),
373 res.size() as u64,
374 res.sl() as u64,
375 a.at_ptr(a_col, 0),
376 a.size() as u64,
377 a.sl() as u64,
378 res.at_ptr(res_col, 0),
379 res.size() as u64,
380 res.sl() as u64,
381 )
382 }
383 }
384
385 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)
386 where
387 R: VecZnxBigToMut<FFT64>,
388 A: VecZnxToRef,
389 B: VecZnxBigToRef<FFT64>,
390 {
391 let a: VecZnx<&[u8]> = a.to_ref();
392 let b: VecZnxBig<&[u8], FFT64> = b.to_ref();
393 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
394
395 #[cfg(debug_assertions)]
396 {
397 assert_eq!(a.n(), self.n());
398 assert_eq!(b.n(), self.n());
399 assert_eq!(res.n(), self.n());
400 assert_ne!(a.as_ptr(), b.as_ptr());
401 }
402 unsafe {
403 vec_znx::vec_znx_sub(
404 self.ptr,
405 res.at_mut_ptr(res_col, 0),
406 res.size() as u64,
407 res.sl() as u64,
408 a.at_ptr(a_col, 0),
409 a.size() as u64,
410 a.sl() as u64,
411 b.at_ptr(b_col, 0),
412 b.size() as u64,
413 b.sl() as u64,
414 )
415 }
416 }
417
418 fn vec_znx_big_sub_small_a_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
419 where
420 R: VecZnxBigToMut<FFT64>,
421 A: VecZnxToRef,
422 {
423 let a: VecZnx<&[u8]> = a.to_ref();
424 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
425
426 #[cfg(debug_assertions)]
427 {
428 assert_eq!(a.n(), self.n());
429 assert_eq!(res.n(), self.n());
430 }
431 unsafe {
432 vec_znx::vec_znx_sub(
433 self.ptr,
434 res.at_mut_ptr(res_col, 0),
435 res.size() as u64,
436 res.sl() as u64,
437 res.at_ptr(res_col, 0),
438 res.size() as u64,
439 res.sl() as u64,
440 a.at_ptr(a_col, 0),
441 a.size() as u64,
442 a.sl() as u64,
443 )
444 }
445 }
446
447 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)
448 where
449 R: VecZnxBigToMut<FFT64>,
450 A: VecZnxBigToRef<FFT64>,
451 B: VecZnxToRef,
452 {
453 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
454 let b: VecZnx<&[u8]> = b.to_ref();
455 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
456
457 #[cfg(debug_assertions)]
458 {
459 assert_eq!(a.n(), self.n());
460 assert_eq!(b.n(), self.n());
461 assert_eq!(res.n(), self.n());
462 assert_ne!(a.as_ptr(), b.as_ptr());
463 }
464 unsafe {
465 vec_znx::vec_znx_add(
466 self.ptr,
467 res.at_mut_ptr(res_col, 0),
468 res.size() as u64,
469 res.sl() as u64,
470 a.at_ptr(a_col, 0),
471 a.size() as u64,
472 a.sl() as u64,
473 b.at_ptr(b_col, 0),
474 b.size() as u64,
475 b.sl() as u64,
476 )
477 }
478 }
479
480 fn vec_znx_big_add_small_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
481 where
482 R: VecZnxBigToMut<FFT64>,
483 A: VecZnxToRef,
484 {
485 let a: VecZnx<&[u8]> = a.to_ref();
486 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
487
488 #[cfg(debug_assertions)]
489 {
490 assert_eq!(a.n(), self.n());
491 assert_eq!(res.n(), self.n());
492 }
493 unsafe {
494 vec_znx::vec_znx_add(
495 self.ptr,
496 res.at_mut_ptr(res_col, 0),
497 res.size() as u64,
498 res.sl() as u64,
499 res.at_ptr(res_col, 0),
500 res.size() as u64,
501 res.sl() as u64,
502 a.at_ptr(a_col, 0),
503 a.size() as u64,
504 a.sl() as u64,
505 )
506 }
507 }
508
509 fn vec_znx_big_negate_inplace<A>(&self, a: &mut A, res_col: usize) where A: VecZnxBigToMut<FFT64> {
510 let mut a: VecZnxBig<&mut [u8], FFT64> = a.to_mut();
511 #[cfg(debug_assertions)]
512 {
513 assert_eq!(a.n(), self.n());
514 }
515 unsafe {
516 vec_znx::vec_znx_negate(
517 self.ptr,
518 a.at_mut_ptr(res_col, 0),
519 a.size() as u64,
520 a.sl() as u64,
521 a.at_ptr(res_col, 0),
522 a.size() as u64,
523 a.sl() as u64,
524 )
525 }
526 }
527
528 fn vec_znx_big_normalize<R, A>(
529 &self,
530 log_base2k: usize,
531 res: &mut R,
532 res_col: usize,
533 a: &A,
534 a_col: usize,
535 scratch: &mut Scratch,
536 ) where
537 R: VecZnxToMut,
538 A: VecZnxBigToRef<FFT64>,
539 {
540 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
541 let mut res: VecZnx<&mut [u8]> = res.to_mut();
542
543 #[cfg(debug_assertions)]
544 {
545 assert_eq!(a.n(), self.n());
546 assert_eq!(res.n(), self.n());
547 //(Jay)Note: This is calling VezZnxOps::vec_znx_normalize_tmp_bytes and not VecZnxBigOps::vec_znx_big_normalize_tmp_bytes.
548 // In the FFT backend the tmp sizes are same but will be different in the NTT backend
549 // assert!(tmp_bytes.len() >= <Self as VecZnxOps<&mut [u8], & [u8]>>::vec_znx_normalize_tmp_bytes(&self));
550 // assert_alignement(tmp_bytes.as_ptr());
551 }
552
553 let (tmp_bytes, _) = scratch.tmp_slice(<Self as VecZnxBigScratch>::vec_znx_big_normalize_tmp_bytes(
554 &self,
555 ));
556 unsafe {
557 vec_znx::vec_znx_normalize_base2k(
558 self.ptr,
559 log_base2k as u64,
560 res.at_mut_ptr(res_col, 0),
561 res.size() as u64,
562 res.sl() as u64,
563 a.at_ptr(a_col, 0),
564 a.size() as u64,
565 a.sl() as u64,
566 tmp_bytes.as_mut_ptr(),
567 );
568 }
569 }
570
571 fn vec_znx_big_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
572 where
573 R: VecZnxBigToMut<FFT64>,
574 A: VecZnxBigToRef<FFT64>,
575 {
576 let a: VecZnxBig<&[u8], FFT64> = a.to_ref();
577 let mut res: VecZnxBig<&mut [u8], FFT64> = res.to_mut();
578
579 #[cfg(debug_assertions)]
580 {
581 assert_eq!(a.n(), self.n());
582 assert_eq!(res.n(), self.n());
583 }
584 unsafe {
585 vec_znx::vec_znx_automorphism(
586 self.ptr,
587 k,
588 res.at_mut_ptr(res_col, 0),
589 res.size() as u64,
590 res.sl() as u64,
591 a.at_ptr(a_col, 0),
592 a.size() as u64,
593 a.sl() as u64,
594 )
595 }
596 }
597
598 fn vec_znx_big_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
599 where
600 A: VecZnxBigToMut<FFT64>,
601 {
602 let mut a: VecZnxBig<&mut [u8], FFT64> = a.to_mut();
603
604 #[cfg(debug_assertions)]
605 {
606 assert_eq!(a.n(), self.n());
607 }
608 unsafe {
609 vec_znx::vec_znx_automorphism(
610 self.ptr,
611 k,
612 a.at_mut_ptr(a_col, 0),
613 a.size() as u64,
614 a.sl() as u64,
615 a.at_ptr(a_col, 0),
616 a.size() as u64,
617 a.sl() as u64,
618 )
619 }
620 }
621}
622
623impl<B: Backend> VecZnxBigScratch for Module<B> {
624 fn vec_znx_big_normalize_tmp_bytes(&self) -> usize {
625 <Self as VecZnxScratch>::vec_znx_normalize_tmp_bytes(self)
626 }
627}