arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_rotation.rs
poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_rotation.rsRaw
 1use poulpy_core::{
 2    GLWECopy, GLWERotate, ScratchTakeCore,
 3    layouts::{GGSW, GGSWInfos, GGSWToMut, GLWE, GLWEInfos, GLWEToMut},
 4};
 5use poulpy_hal::layouts::{Backend, Scratch};
 6
 7use crate::tfhe::bdd_arithmetic::{Cmux, GetGGSWBit, UnsignedInteger};
 8
 9pub trait GGSWBlindRotation<T: UnsignedInteger, BE: Backend>
10where
11    Self: GLWEBlindRotation<T, BE>,
12    Scratch<BE>: ScratchTakeCore<BE>,
13{
14    fn ggsw_blind_rotation_tmp_bytes<R, K>(&self, res_infos: &R, k_infos: &K) -> usize
15    where
16        R: GLWEInfos,
17        K: GGSWInfos,
18    {
19        self.glwe_blind_rotation_tmp_bytes(res_infos, k_infos)
20    }
21
22    fn ggsw_blind_rotation<R, K>(
23        &self,
24        res: &mut R,
25        k: &K,
26        bit_start: usize,
27        bit_size: usize,
28        bit_step: usize,
29        scratch: &mut Scratch<BE>,
30    ) where
31        R: GGSWToMut,
32        K: GetGGSWBit<T, BE>,
33        Scratch<BE>: ScratchTakeCore<BE>,
34    {
35        let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
36
37        for row in 0..res.dnum().into() {
38            for col in 0..(res.rank() + 1).into() {
39                self.glwe_blind_rotation(
40                    &mut res.at_mut(row, col),
41                    k,
42                    bit_start,
43                    bit_size,
44                    bit_step,
45                    scratch,
46                );
47            }
48        }
49    }
50}
51
52pub trait GLWEBlindRotation<T: UnsignedInteger, BE: Backend>
53where
54    Self: GLWECopy + GLWERotate<BE> + Cmux<BE>,
55    Scratch<BE>: ScratchTakeCore<BE>,
56{
57    fn glwe_blind_rotation_tmp_bytes<R, K>(&self, res_infos: &R, k_infos: &K) -> usize
58    where
59        R: GLWEInfos,
60        K: GGSWInfos,
61    {
62        self.cmux_tmp_bytes(res_infos, res_infos, k_infos) + GLWE::bytes_of_from_infos(res_infos)
63    }
64
65    /// Homomorphic multiplication of res by X^{k[bit_start..bit_start + bit_size] * bit_step}.
66    fn glwe_blind_rotation<R, K>(
67        &self,
68        res: &mut R,
69        k: &K,
70        bit_start: usize,
71        bit_size: usize,
72        bit_step: usize,
73        scratch: &mut Scratch<BE>,
74    ) where
75        R: GLWEToMut,
76        K: GetGGSWBit<T, BE>,
77        Scratch<BE>: ScratchTakeCore<BE>,
78    {
79        let res: &mut GLWE<&mut [u8]> = &mut res.to_mut();
80
81        let (mut tmp_res, scratch_1) = scratch.take_glwe(res);
82
83        self.glwe_copy(&mut tmp_res, res);
84
85        for i in 1..bit_size {
86            // res' = res * X^2^(i * bit_step)
87            self.glwe_rotate(1 << (i + bit_step), &mut tmp_res, res);
88
89            // res = (res - res') * GGSW(b[i]) + res'
90            self.cmux_inplace(res, &tmp_res, &k.get_bit(i + bit_start), scratch_1);
91        }
92    }
93}