arnaucube
arnaucube/poulpyPublic Self-hosted repository
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}