arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/blind_rotation/algorithms/mod.rs
poulpy-schemes/src/tfhe/blind_rotation/algorithms/mod.rsRaw
  1mod cggi;
  2
  3pub use cggi::*;
  4
  5use itertools::izip;
  6use poulpy_core::{
  7    ScratchTakeCore,
  8    layouts::{GGSWInfos, GLWE, GLWEInfos, LWE, LWEInfos},
  9};
 10use poulpy_hal::layouts::{Backend, DataMut, DataRef, Scratch, ZnxView};
 11
 12use crate::tfhe::blind_rotation::{BlindRotationKeyInfos, BlindRotationKeyPrepared, LookUpTableRotationDirection, LookupTable};
 13
 14pub trait BlindRotationAlgo {}
 15
 16pub trait BlindRotationExecute<BRA: BlindRotationAlgo, BE: Backend> {
 17    fn blind_rotation_execute_tmp_bytes<G, B>(
 18        &self,
 19        block_size: usize,
 20        extension_factor: usize,
 21        glwe_infos: &G,
 22        brk_infos: &B,
 23    ) -> usize
 24    where
 25        G: GLWEInfos,
 26        B: GGSWInfos;
 27
 28    fn blind_rotation_execute<DR, DL, DB>(
 29        &self,
 30        res: &mut GLWE<DR>,
 31        lwe: &LWE<DL>,
 32        lut: &LookupTable,
 33        brk: &BlindRotationKeyPrepared<DB, BRA, BE>,
 34        scratch: &mut Scratch<BE>,
 35    ) where
 36        DR: DataMut,
 37        DL: DataRef,
 38        DB: DataRef;
 39}
 40
 41impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> BlindRotationKeyPrepared<D, BRA, BE>
 42where
 43    Scratch<BE>: ScratchTakeCore<BE>,
 44{
 45    pub fn execute<DR: DataMut, DI: DataRef, M>(
 46        &self,
 47        module: &M,
 48        res: &mut GLWE<DR>,
 49        lwe: &LWE<DI>,
 50        lut: &LookupTable,
 51        scratch: &mut Scratch<BE>,
 52    ) where
 53        M: BlindRotationExecute<BRA, BE>,
 54    {
 55        module.blind_rotation_execute(res, lwe, lut, self, scratch);
 56    }
 57}
 58
 59impl<BE: Backend, BRA: BlindRotationAlgo> BlindRotationKeyPrepared<Vec<u8>, BRA, BE> {
 60    pub fn execute_tmp_bytes<A, B, M>(
 61        module: &M,
 62        block_size: usize,
 63        extension_factor: usize,
 64        glwe_infos: &A,
 65        brk_infos: &B,
 66    ) -> usize
 67    where
 68        A: GLWEInfos,
 69        B: BlindRotationKeyInfos,
 70        M: BlindRotationExecute<BRA, BE>,
 71    {
 72        module.blind_rotation_execute_tmp_bytes(block_size, extension_factor, glwe_infos, brk_infos)
 73    }
 74}
 75
 76pub fn mod_switch_2n(n: usize, res: &mut [i64], lwe: &LWE<&[u8]>, rot_dir: LookUpTableRotationDirection) {
 77    let base2k: usize = lwe.base2k().into();
 78
 79    let log2n: usize = usize::BITS as usize - (n - 1).leading_zeros() as usize + 1;
 80
 81    res.copy_from_slice(lwe.data().at(0, 0));
 82
 83    match rot_dir {
 84        LookUpTableRotationDirection::Left => {
 85            res.iter_mut().for_each(|x| *x = -*x);
 86        }
 87        LookUpTableRotationDirection::Right => {}
 88    }
 89
 90    if base2k > log2n {
 91        let diff: usize = base2k - (log2n - 1); // additional -1 because we map to [-N/2, N/2) instead of [0, N)
 92        res.iter_mut().for_each(|x| {
 93            *x = div_round_by_pow2(x, diff);
 94        })
 95    } else {
 96        let rem: usize = base2k - (log2n % base2k);
 97        let size: usize = log2n.div_ceil(base2k);
 98        (1..size).for_each(|i| {
 99            if i == size - 1 && rem != base2k {
100                let k_rem: usize = base2k - rem;
101                izip!(lwe.data().at(0, i).iter(), res.iter_mut()).for_each(|(x, y)| {
102                    *y = (*y << k_rem) + (x >> rem);
103                });
104            } else {
105                izip!(lwe.data().at(0, i).iter(), res.iter_mut()).for_each(|(x, y)| {
106                    *y = (*y << base2k) + x;
107                });
108            }
109        })
110    }
111}
112
113#[inline(always)]
114fn div_round_by_pow2(x: &i64, k: usize) -> i64 {
115    (x + (1 << (k - 1))) >> k
116}