poulpy/poulpy-hal/src/reference/vec_znx/switch_ring.rs
poulpy-hal/src/reference/vec_znx/switch_ring.rsRaw
1use crate::{
2 layouts::{VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos, ZnxView, ZnxViewMut},
3 reference::{
4 vec_znx::vec_znx_copy,
5 znx::{ZnxCopy, ZnxSwitchRing, ZnxZero},
6 },
7};
8
9/// Maps between negacyclic rings by changing the polynomial degree.
10/// Up: Z[X]/(X^N+1) -> Z[X]/(X^{2^d N}+1) via X ↦ X^{2^d}
11/// Down: Z[X]/(X^N+1) -> Z[X]/(X^{N/2^d}+1) by folding indices.
12pub fn vec_znx_switch_ring<R, A, ZNXARI>(res: &mut R, res_col: usize, a: &A, a_col: usize)
13where
14 R: VecZnxToMut,
15 A: VecZnxToRef,
16 ZNXARI: ZnxCopy + ZnxSwitchRing + ZnxZero,
17{
18 let a: VecZnx<&[u8]> = a.to_ref();
19 let mut res: VecZnx<&mut [u8]> = res.to_mut();
20
21 let (n_in, n_out) = (a.n(), res.n());
22
23 if n_in == n_out {
24 vec_znx_copy::<_, _, ZNXARI>(&mut res, res_col, &a, a_col);
25 return;
26 }
27
28 let min_size: usize = a.size().min(res.size());
29
30 for j in 0..min_size {
31 ZNXARI::znx_switch_ring(res.at_mut(res_col, j), a.at(a_col, j));
32 }
33
34 for j in min_size..res.size() {
35 ZNXARI::znx_zero(res.at_mut(res_col, j));
36 }
37}