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)
119    where
120        A: VecZnxBigToMut<BACKEND>;
121
122    /// Normalizes `a` and stores the result on `b`.
123    ///
124    /// # Arguments
125    ///
126    /// * `log_base2k`: 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        log_base2k: 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        log_base2k: 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                log_base2k 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}