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