arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block_prepared.rs
poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block_prepared.rsRaw
  1use std::marker::PhantomData;
  2
  3use poulpy_core::layouts::{
  4    Base2K, Dnum, Dsize, GGSWInfos, GGSWPreparedFactory, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWPrepared,
  5};
  6use poulpy_core::layouts::{GGSWPreparedToMut, GGSWPreparedToRef};
  7
  8use poulpy_core::{GGSWEncryptSk, ScratchTakeCore, layouts::GLWESecretPreparedToRef};
  9use poulpy_hal::layouts::{Backend, Data, DataRef, Module};
 10
 11use poulpy_hal::{
 12    api::ModuleN,
 13    layouts::{DataMut, Scratch},
 14    source::Source,
 15};
 16
 17use crate::tfhe::bdd_arithmetic::ToBits;
 18use crate::tfhe::bdd_arithmetic::UnsignedInteger;
 19
 20/// A prepared FHE ciphertext encrypting the bits of an [UnsignedInteger].
 21pub struct FheUintBlocksPrepared<D: Data, T: UnsignedInteger, B: Backend> {
 22    pub(crate) blocks: Vec<GGSWPrepared<D, B>>,
 23    pub(crate) _base: u8,
 24    pub(crate) _phantom: PhantomData<T>,
 25}
 26
 27impl<D: Data, T: UnsignedInteger, B: Backend> FheUintBlocksPrepared<D, T, B> {
 28    pub fn blocks(&self) -> &Vec<GGSWPrepared<D, B>> {
 29        &self.blocks
 30    }
 31}
 32
 33impl<T: UnsignedInteger, BE: Backend> FheUintBlocksPreparedFactory<T, BE> for Module<BE> where
 34    Self: Sized + GGSWPreparedFactory<BE>
 35{
 36}
 37
 38pub trait GetGGSWBit<T: UnsignedInteger, BE: Backend> {
 39    fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE>;
 40}
 41
 42impl<D: DataRef, T: UnsignedInteger, BE: Backend> GetGGSWBit<T, BE> for FheUintBlocksPrepared<D, T, BE> {
 43    fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE> {
 44        assert!(bit <= self.blocks.len());
 45        self.blocks[bit].to_ref()
 46    }
 47}
 48
 49pub trait GetGGSWBitMut<T: UnsignedInteger, BE: Backend> {
 50    fn get_bit(&mut self, bit: usize) -> GGSWPrepared<&mut [u8], BE>;
 51}
 52
 53impl<D: DataMut, T: UnsignedInteger, BE: Backend> GetGGSWBitMut<T, BE> for FheUintBlocksPrepared<D, T, BE> {
 54    fn get_bit(&mut self, bit: usize) -> GGSWPrepared<&mut [u8], BE> {
 55        assert!(bit <= self.blocks.len());
 56        self.blocks[bit].to_mut()
 57    }
 58}
 59
 60pub trait FheUintBlocksPreparedFactory<T: UnsignedInteger, BE: Backend>
 61where
 62    Self: Sized + GGSWPreparedFactory<BE>,
 63{
 64    fn alloc_fhe_uint_blocks_prepared(
 65        &self,
 66        base2k: Base2K,
 67        k: TorusPrecision,
 68        dnum: Dnum,
 69        dsize: Dsize,
 70        rank: Rank,
 71    ) -> FheUintBlocksPrepared<Vec<u8>, T, BE> {
 72        FheUintBlocksPrepared {
 73            blocks: (0..T::WORD_SIZE)
 74                .map(|_| GGSWPrepared::alloc(self, base2k, k, dnum, dsize, rank))
 75                .collect(),
 76            _base: 1,
 77            _phantom: PhantomData,
 78        }
 79    }
 80
 81    fn alloc_fhe_uint_blocks_prepared_from_infos<A>(&self, infos: &A) -> FheUintBlocksPrepared<Vec<u8>, T, BE>
 82    where
 83        A: GGSWInfos,
 84    {
 85        self.alloc_fhe_uint_blocks_prepared(
 86            infos.base2k(),
 87            infos.k(),
 88            infos.dnum(),
 89            infos.dsize(),
 90            infos.rank(),
 91        )
 92    }
 93}
 94
 95impl<T: UnsignedInteger, BE: Backend> FheUintBlocksPrepared<Vec<u8>, T, BE> {
 96    pub fn alloc<A, M>(module: &M, infos: &A) -> Self
 97    where
 98        A: GGSWInfos,
 99        M: FheUintBlocksPreparedFactory<T, BE>,
100    {
101        module.alloc_fhe_uint_blocks_prepared_from_infos(infos)
102    }
103
104    pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
105    where
106        M: FheUintBlocksPreparedFactory<T, BE>,
107    {
108        module.alloc_fhe_uint_blocks_prepared(base2k, k, dnum, dsize, rank)
109    }
110}
111
112impl<T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPreparedEncryptSk<T, BE> for Module<BE> where
113    Self: Sized + ModuleN + GGSWEncryptSk<BE> + GGSWPreparedFactory<BE>
114{
115}
116
117pub trait FheUintBlocksPreparedEncryptSk<T: UnsignedInteger + ToBits, BE: Backend>
118where
119    Self: Sized + ModuleN + GGSWEncryptSk<BE> + GGSWPreparedFactory<BE>,
120{
121    fn fhe_uint_blocks_prepared_encrypt_sk<DM, S>(
122        &self,
123        res: &mut FheUintBlocksPrepared<DM, T, BE>,
124        value: T,
125        sk: &S,
126        source_xa: &mut Source,
127        source_xe: &mut Source,
128        scratch: &mut Scratch<BE>,
129    ) where
130        DM: DataMut,
131        S: GLWESecretPreparedToRef<BE> + GLWEInfos,
132        Scratch<BE>: ScratchTakeCore<BE>,
133    {
134        use poulpy_hal::{api::ScratchTakeBasic, layouts::ZnxZero};
135
136        assert!(self.n().is_multiple_of(T::WORD_SIZE));
137        assert_eq!(res.n(), self.n() as u32);
138        assert_eq!(sk.n(), self.n() as u32);
139
140        let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(res);
141        let (mut pt, scratch_2) = scratch_1.take_scalar_znx(self.n(), 1);
142        pt.zero();
143
144        for i in 0..T::WORD_SIZE {
145            use poulpy_hal::layouts::ZnxViewMut;
146            pt.at_mut(0, 0)[0] = value.bit(i) as i64;
147            tmp_ggsw.encrypt_sk(self, &pt, sk, source_xa, source_xe, scratch_2);
148            res.blocks[i].prepare(self, &tmp_ggsw, scratch_2);
149        }
150    }
151}
152
153impl<D: DataMut, T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPrepared<D, T, BE> {
154    pub fn encrypt_sk<M, S>(
155        &mut self,
156        module: &M,
157        value: T,
158        sk: &S,
159        source_xa: &mut Source,
160        source_xe: &mut Source,
161        scratch: &mut Scratch<BE>,
162    ) where
163        S: GLWESecretPreparedToRef<BE> + GLWEInfos,
164        M: FheUintBlocksPreparedEncryptSk<T, BE>,
165        Scratch<BE>: ScratchTakeCore<BE>,
166    {
167        module.fhe_uint_blocks_prepared_encrypt_sk(self, value, sk, source_xa, source_xe, scratch);
168    }
169}
170
171impl<D: DataRef, T: UnsignedInteger, B: Backend> LWEInfos for FheUintBlocksPrepared<D, T, B> {
172    fn base2k(&self) -> poulpy_core::layouts::Base2K {
173        self.blocks[0].base2k()
174    }
175
176    fn k(&self) -> poulpy_core::layouts::TorusPrecision {
177        self.blocks[0].k()
178    }
179
180    fn n(&self) -> poulpy_core::layouts::Degree {
181        self.blocks[0].n()
182    }
183}
184
185impl<D: DataRef, T: UnsignedInteger, B: Backend> GLWEInfos for FheUintBlocksPrepared<D, T, B> {
186    fn rank(&self) -> poulpy_core::layouts::Rank {
187        self.blocks[0].rank()
188    }
189}
190
191impl<D: DataRef, T: UnsignedInteger, B: Backend> GGSWInfos for FheUintBlocksPrepared<D, T, B> {
192    fn dsize(&self) -> poulpy_core::layouts::Dsize {
193        self.blocks[0].dsize()
194    }
195
196    fn dnum(&self) -> poulpy_core::layouts::Dnum {
197        self.blocks[0].dnum()
198    }
199}