poulpy_core/automorphism/
ggsw_ct.rs

1use poulpy_hal::{
2    api::ScratchAvailable,
3    layouts::{Backend, DataMut, Module, Scratch},
4};
5
6use crate::{
7    GGSWExpandRows, ScratchTakeCore,
8    automorphism::glwe_ct::GLWEAutomorphism,
9    layouts::{
10        GGLWEInfos, GGLWEPreparedToRef, GGLWEToGGSWKeyPrepared, GGLWEToGGSWKeyPreparedToRef, GGSW, GGSWInfos, GGSWToMut,
11        GGSWToRef, GetGaloisElement,
12    },
13};
14
15impl GGSW<Vec<u8>> {
16    pub fn automorphism_tmp_bytes<R, A, K, T, M, BE: Backend>(
17        module: &M,
18        res_infos: &R,
19        a_infos: &A,
20        key_infos: &K,
21        tsk_infos: &T,
22    ) -> usize
23    where
24        R: GGSWInfos,
25        A: GGSWInfos,
26        K: GGLWEInfos,
27        T: GGLWEInfos,
28        M: GGSWAutomorphism<BE>,
29    {
30        module.ggsw_automorphism_tmp_bytes(res_infos, a_infos, key_infos, tsk_infos)
31    }
32}
33
34impl<D: DataMut> GGSW<D> {
35    pub fn automorphism<A, K, T, M, BE: Backend>(&mut self, module: &M, a: &A, key: &K, tsk: &T, scratch: &mut Scratch<BE>)
36    where
37        A: GGSWToRef + GGSWInfos,
38        K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos,
39        T: GGLWEToGGSWKeyPreparedToRef<BE> + GGLWEInfos,
40        Scratch<BE>: ScratchTakeCore<BE>,
41        M: GGSWAutomorphism<BE>,
42    {
43        module.ggsw_automorphism(self, a, key, tsk, scratch);
44    }
45
46    pub fn automorphism_inplace<K, T, M, BE: Backend>(&mut self, module: &M, key: &K, tsk: &T, scratch: &mut Scratch<BE>)
47    where
48        K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos,
49        T: GGLWEToGGSWKeyPreparedToRef<BE>,
50        Scratch<BE>: ScratchTakeCore<BE>,
51        M: GGSWAutomorphism<BE>,
52    {
53        module.ggsw_automorphism_inplace(self, key, tsk, scratch);
54    }
55}
56
57impl<BE: Backend> GGSWAutomorphism<BE> for Module<BE> where Self: GLWEAutomorphism<BE> + GGSWExpandRows<BE> {}
58
59pub trait GGSWAutomorphism<BE: Backend>
60where
61    Self: GLWEAutomorphism<BE> + GGSWExpandRows<BE>,
62{
63    fn ggsw_automorphism_tmp_bytes<R, A, K, T>(&self, res_infos: &R, a_infos: &A, key_infos: &K, tsk_infos: &T) -> usize
64    where
65        R: GGSWInfos,
66        A: GGSWInfos,
67        K: GGLWEInfos,
68        T: GGLWEInfos,
69    {
70        self.glwe_automorphism_tmp_bytes(res_infos, a_infos, key_infos)
71            .max(self.ggsw_expand_rows_tmp_bytes(res_infos, tsk_infos))
72    }
73
74    fn ggsw_automorphism<R, A, K, T>(&self, res: &mut R, a: &A, key: &K, tsk: &T, scratch: &mut Scratch<BE>)
75    where
76        R: GGSWToMut + GGSWInfos,
77        A: GGSWToRef + GGSWInfos,
78        K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos,
79        T: GGLWEToGGSWKeyPreparedToRef<BE> + GGLWEInfos,
80        Scratch<BE>: ScratchTakeCore<BE>,
81    {
82        assert_eq!(res.dsize(), a.dsize());
83        assert_eq!(res.base2k(), a.base2k());
84        assert!(res.dnum() <= a.dnum());
85        assert!(scratch.available() >= self.ggsw_automorphism_tmp_bytes(res, a, key, tsk));
86
87        let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
88        let a: &GGSW<&[u8]> = &a.to_ref();
89        let tsk: &GGLWEToGGSWKeyPrepared<&[u8], BE> = &tsk.to_ref();
90
91        // Keyswitch the j-th row of the col 0
92        for row in 0..res.dnum().as_usize() {
93            // Key-switch column 0, i.e.
94            // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0pi^-1(s0) + a1pi^-1(s1) + a2pi^-1(s2)) + M[i], a0, a1, a2)
95            self.glwe_automorphism(&mut res.at_mut(row, 0), &a.at(row, 0), key, scratch);
96        }
97
98        self.ggsw_expand_row(res, tsk, scratch);
99    }
100
101    fn ggsw_automorphism_inplace<R, K, T>(&self, res: &mut R, key: &K, tsk: &T, scratch: &mut Scratch<BE>)
102    where
103        R: GGSWToMut,
104        K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos,
105        T: GGLWEToGGSWKeyPreparedToRef<BE>,
106        Scratch<BE>: ScratchTakeCore<BE>,
107    {
108        let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
109        let tsk: &GGLWEToGGSWKeyPrepared<&[u8], BE> = &tsk.to_ref();
110
111        // Keyswitch the j-th row of the col 0
112        for row in 0..res.dnum().as_usize() {
113            // Key-switch column 0, i.e.
114            // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0pi^-1(s0) + a1pi^-1(s1) + a2pi^-1(s2)) + M[i], a0, a1, a2)
115            self.glwe_automorphism_inplace(&mut res.at_mut(row, 0), key, scratch);
116        }
117
118        self.ggsw_expand_row(res, tsk, scratch);
119    }
120}
121
122impl<DataSelf: DataMut> GGSW<DataSelf> {}