arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/blind_rotation/key_prepared.rs
poulpy-schemes/src/tfhe/blind_rotation/key_prepared.rsRaw
  1use poulpy_hal::{
  2    api::{SvpPPolAlloc, SvpPrepare, VmpPMatAlloc, VmpPrepare},
  3    layouts::{Backend, Data, DataMut, DataRef, Module, ScalarZnx, Scratch, SvpPPol},
  4};
  5
  6use std::marker::PhantomData;
  7
  8use poulpy_core::{
  9    Distribution,
 10    layouts::{
 11        Base2K, Degree, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
 12        prepared::{GGSWCiphertextPrepared, Prepare, PrepareAlloc},
 13    },
 14};
 15
 16use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyInfos, utils::set_xai_plus_y};
 17
 18pub trait BlindRotationKeyPreparedAlloc<B: Backend> {
 19    fn alloc<A>(module: &Module<B>, infos: &A) -> Self
 20    where
 21        A: BlindRotationKeyInfos;
 22}
 23
 24#[derive(PartialEq, Eq)]
 25pub struct BlindRotationKeyPrepared<D: Data, BRT: BlindRotationAlgo, B: Backend> {
 26    pub(crate) data: Vec<GGSWCiphertextPrepared<D, B>>,
 27    pub(crate) dist: Distribution,
 28    pub(crate) x_pow_a: Option<Vec<SvpPPol<Vec<u8>, B>>>,
 29    pub(crate) _phantom: PhantomData<BRT>,
 30}
 31
 32impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyInfos for BlindRotationKeyPrepared<D, BRT, B> {
 33    fn n_glwe(&self) -> Degree {
 34        self.n()
 35    }
 36
 37    fn n_lwe(&self) -> Degree {
 38        Degree(self.data.len() as u32)
 39    }
 40}
 41
 42impl<D: Data, BRT: BlindRotationAlgo, B: Backend> LWEInfos for BlindRotationKeyPrepared<D, BRT, B> {
 43    fn base2k(&self) -> Base2K {
 44        self.data[0].base2k()
 45    }
 46
 47    fn k(&self) -> TorusPrecision {
 48        self.data[0].k()
 49    }
 50
 51    fn n(&self) -> Degree {
 52        self.data[0].n()
 53    }
 54
 55    fn size(&self) -> usize {
 56        self.data[0].size()
 57    }
 58}
 59
 60impl<D: Data, BRT: BlindRotationAlgo, B: Backend> GLWEInfos for BlindRotationKeyPrepared<D, BRT, B> {
 61    fn rank(&self) -> Rank {
 62        self.data[0].rank()
 63    }
 64}
 65impl<D: Data, BRT: BlindRotationAlgo, B: Backend> GGSWInfos for BlindRotationKeyPrepared<D, BRT, B> {
 66    fn dsize(&self) -> poulpy_core::layouts::Dsize {
 67        Dsize(1)
 68    }
 69
 70    fn dnum(&self) -> Dnum {
 71        self.data[0].dnum()
 72    }
 73}
 74
 75impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyPrepared<D, BRT, B> {
 76    pub fn block_size(&self) -> usize {
 77        match self.dist {
 78            Distribution::BinaryBlock(value) => value,
 79            _ => 1,
 80        }
 81    }
 82}
 83
 84impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>
 85    for BlindRotationKey<D, BRA>
 86where
 87    BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlindRotationKeyPreparedAlloc<B>,
 88    BlindRotationKeyPrepared<Vec<u8>, BRA, B>: Prepare<B, BlindRotationKey<D, BRA>>,
 89{
 90    fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> BlindRotationKeyPrepared<Vec<u8>, BRA, B> {
 91        let mut brk: BlindRotationKeyPrepared<Vec<u8>, BRA, B> = BlindRotationKeyPrepared::alloc(module, self);
 92        brk.prepare(module, self, scratch);
 93        brk
 94    }
 95}
 96
 97impl<DM: DataMut, DR: DataRef, BRA: BlindRotationAlgo, B: Backend> Prepare<B, BlindRotationKey<DR, BRA>>
 98    for BlindRotationKeyPrepared<DM, BRA, B>
 99where
100    Module<B>: VmpPMatAlloc<B> + VmpPrepare<B> + SvpPPolAlloc<B> + SvpPrepare<B>,
101{
102    fn prepare(&mut self, module: &Module<B>, other: &BlindRotationKey<DR, BRA>, scratch: &mut Scratch<B>) {
103        #[cfg(debug_assertions)]
104        {
105            assert_eq!(self.data.len(), other.keys.len());
106        }
107
108        let n: usize = other.n().as_usize();
109
110        self.data
111            .iter_mut()
112            .zip(other.keys.iter())
113            .for_each(|(ggsw_prepared, other)| {
114                ggsw_prepared.prepare(module, other, scratch);
115            });
116
117        self.dist = other.dist;
118
119        if let Distribution::BinaryBlock(_) = other.dist {
120            let mut x_pow_a: Vec<SvpPPol<Vec<u8>, B>> = Vec::with_capacity(n << 1);
121            let mut buf: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
122            (0..n << 1).for_each(|i| {
123                let mut res: SvpPPol<Vec<u8>, B> = module.svp_ppol_alloc(1);
124                set_xai_plus_y(module, i, 0, &mut res, &mut buf);
125                x_pow_a.push(res);
126            });
127            self.x_pow_a = Some(x_pow_a);
128        }
129    }
130}