arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/automorphism/gglwe_atk.rs
poulpy-core/src/automorphism/gglwe_atk.rsRaw
  1use poulpy_hal::{
  2    api::VecZnxAutomorphism,
  3    layouts::{Backend, DataMut, GaloisElement, Module, Scratch},
  4};
  5
  6use crate::{
  7    ScratchTakeCore,
  8    automorphism::glwe_ct::GLWEAutomorphism,
  9    layouts::{
 10        AutomorphismKey, GGLWE, GGLWEInfos, GGLWEPreparedToRef, GGLWEToMut, GGLWEToRef, GLWE, GetGaloisElement, SetGaloisElement,
 11    },
 12};
 13
 14impl AutomorphismKey<Vec<u8>> {
 15    pub fn automorphism_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
 16    where
 17        R: GGLWEInfos,
 18        A: GGLWEInfos,
 19        K: GGLWEInfos,
 20        M: GLWEAutomorphismKeyAutomorphism<BE>,
 21    {
 22        module.automorphism_key_automorphism_tmp_bytes(res_infos, a_infos, key_infos)
 23    }
 24}
 25
 26impl<DataSelf: DataMut> AutomorphismKey<DataSelf> {
 27    pub fn automorphism<A, K, M, BE: Backend>(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch<BE>)
 28    where
 29        A: GGLWEToRef + GetGaloisElement + GGLWEInfos,
 30        K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
 31        Scratch<BE>: ScratchTakeCore<BE>,
 32        M: GLWEAutomorphismKeyAutomorphism<BE>,
 33    {
 34        module.automorphism_key_automorphism(self, a, key, scratch);
 35    }
 36
 37    pub fn automorphism_inplace<K, M, BE: Backend>(&mut self, module: &M, key: &K, scratch: &mut Scratch<BE>)
 38    where
 39        K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
 40        Scratch<BE>: ScratchTakeCore<BE>,
 41        M: GLWEAutomorphismKeyAutomorphism<BE>,
 42    {
 43        module.automorphism_key_automorphism_inplace(self, key, scratch);
 44    }
 45}
 46
 47impl<BE: Backend> GLWEAutomorphismKeyAutomorphism<BE> for Module<BE> where
 48    Self: GaloisElement + GLWEAutomorphism<BE> + VecZnxAutomorphism
 49{
 50}
 51
 52pub trait GLWEAutomorphismKeyAutomorphism<BE: Backend>
 53where
 54    Self: GaloisElement + GLWEAutomorphism<BE> + VecZnxAutomorphism,
 55{
 56    fn automorphism_key_automorphism_tmp_bytes<R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
 57    where
 58        R: GGLWEInfos,
 59        A: GGLWEInfos,
 60        K: GGLWEInfos,
 61    {
 62        self.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos)
 63    }
 64
 65    fn automorphism_key_automorphism<R, A, K>(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch<BE>)
 66    where
 67        R: GGLWEToMut + SetGaloisElement + GGLWEInfos,
 68        A: GGLWEToRef + GetGaloisElement + GGLWEInfos,
 69        K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
 70        Scratch<BE>: ScratchTakeCore<BE>,
 71    {
 72        assert!(
 73            res.dnum().as_u32() <= a.dnum().as_u32(),
 74            "res dnum: {} > a dnum: {}",
 75            res.dnum(),
 76            a.dnum()
 77        );
 78
 79        assert_eq!(
 80            res.dsize(),
 81            a.dsize(),
 82            "res dnum: {} != a dnum: {}",
 83            res.dsize(),
 84            a.dsize()
 85        );
 86
 87        let cols_out: usize = (key.rank_out() + 1).into();
 88        let cols_in: usize = key.rank_in().into();
 89
 90        let p: i64 = a.p();
 91        let p_inv: i64 = self.galois_element_inv(p);
 92
 93        {
 94            let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut();
 95            let a: &GGLWE<&[u8]> = &a.to_ref();
 96
 97            for row in 0..res.dnum().as_usize() {
 98                for col in 0..cols_in {
 99                    let mut res_tmp: GLWE<&mut [u8]> = res.at_mut(row, col);
100                    let a_ct: GLWE<&[u8]> = a.at(row, col);
101
102                    // Reverts the automorphism X^{-k}: (-pi^{-1}_{k}(s)a + s, a) to (-sa + pi_{k}(s), a)
103                    for i in 0..cols_out {
104                        self.vec_znx_automorphism(p, res_tmp.data_mut(), i, &a_ct.data, i);
105                    }
106
107                    // Key-switch (-sa + pi_{k}(s), a) to (-pi^{-1}_{k'}(s)a + pi_{k}(s), a)
108                    self.glwe_keyswitch_inplace(&mut res_tmp, key, scratch);
109
110                    // Applies back the automorphism X^{-k}: (-pi^{-1}_{k'}(s)a + pi_{k}(s), a) to (-pi^{-1}_{k'+k}(s)a + s, a)
111                    (0..cols_out).for_each(|i| {
112                        self.vec_znx_automorphism_inplace(p_inv, res_tmp.data_mut(), i, scratch);
113                    });
114                }
115            }
116        }
117
118        res.set_p((p * key.p()) % (self.cyclotomic_order() as i64));
119    }
120
121    fn automorphism_key_automorphism_inplace<R, K>(&self, res: &mut R, key: &K, scratch: &mut Scratch<BE>)
122    where
123        R: GGLWEToMut + SetGaloisElement + GetGaloisElement + GGLWEInfos,
124        K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
125        Scratch<BE>: ScratchTakeCore<BE>,
126    {
127        assert_eq!(
128            res.rank(),
129            key.rank(),
130            "key rank: {} != key rank: {}",
131            res.rank(),
132            key.rank()
133        );
134
135        let cols_out: usize = (key.rank_out() + 1).into();
136        let cols_in: usize = key.rank_in().into();
137        let p: i64 = res.p();
138        let p_inv: i64 = self.galois_element_inv(p);
139
140        {
141            let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut();
142            for row in 0..res.dnum().as_usize() {
143                for col in 0..cols_in {
144                    let mut res_tmp: GLWE<&mut [u8]> = res.at_mut(row, col);
145
146                    // Reverts the automorphism X^{-k}: (-pi^{-1}_{k}(s)a + s, a) to (-sa + pi_{k}(s), a)
147                    for i in 0..cols_out {
148                        self.vec_znx_automorphism_inplace(p, res_tmp.data_mut(), i, scratch);
149                    }
150
151                    // Key-switch (-sa + pi_{k}(s), a) to (-pi^{-1}_{k'}(s)a + pi_{k}(s), a)
152                    self.glwe_keyswitch_inplace(&mut res_tmp, key, scratch);
153
154                    // Applies back the automorphism X^{-k}: (-pi^{-1}_{k'}(s)a + pi_{k}(s), a) to (-pi^{-1}_{k'+k}(s)a + s, a)
155                    for i in 0..cols_out {
156                        self.vec_znx_automorphism_inplace(p_inv, res_tmp.data_mut(), i, scratch);
157                    }
158                }
159            }
160        }
161
162        res.set_p((res.p() * key.p()) % (self.cyclotomic_order() as i64));
163    }
164}