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