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    #[allow(dead_code)]
 97    pub(crate) fn alloc<A, M>(module: &M, infos: &A) -> Self
 98    where
 99        A: GGSWInfos,
100        M: FheUintBlocksPreparedFactory<T, BE>,
101    {
102        module.alloc_fhe_uint_blocks_prepared_from_infos(infos)
103    }
104
105    #[allow(dead_code)]
106    pub(crate) fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
107    where
108        M: FheUintBlocksPreparedFactory<T, BE>,
109    {
110        module.alloc_fhe_uint_blocks_prepared(base2k, k, dnum, dsize, rank)
111    }
112}
113
114impl<T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPreparedEncryptSk<T, BE> for Module<BE> where
115    Self: Sized + ModuleN + GGSWEncryptSk<BE> + GGSWPreparedFactory<BE>
116{
117}
118
119pub trait FheUintBlocksPreparedEncryptSk<T: UnsignedInteger + ToBits, BE: Backend>
120where
121    Self: Sized + ModuleN + GGSWEncryptSk<BE> + GGSWPreparedFactory<BE>,
122{
123    fn fhe_uint_blocks_prepared_encrypt_sk<DM, S>(
124        &self,
125        res: &mut FheUintBlocksPrepared<DM, T, BE>,
126        value: T,
127        sk: &S,
128        source_xa: &mut Source,
129        source_xe: &mut Source,
130        scratch: &mut Scratch<BE>,
131    ) where
132        DM: DataMut,
133        S: GLWESecretPreparedToRef<BE> + GLWEInfos,
134        Scratch<BE>: ScratchTakeCore<BE>,
135    {
136        use poulpy_hal::{api::ScratchTakeBasic, layouts::ZnxZero};
137
138        assert!(self.n().is_multiple_of(T::WORD_SIZE));
139        assert_eq!(res.n(), self.n() as u32);
140        assert_eq!(sk.n(), self.n() as u32);
141
142        let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(res);
143        let (mut pt, scratch_2) = scratch_1.take_scalar_znx(self.n(), 1);
144        pt.zero();
145
146        for i in 0..T::WORD_SIZE {
147            use poulpy_hal::layouts::ZnxViewMut;
148            pt.at_mut(0, 0)[0] = value.bit(i) as i64;
149            tmp_ggsw.encrypt_sk(self, &pt, sk, source_xa, source_xe, scratch_2);
150            res.blocks[i].prepare(self, &tmp_ggsw, scratch_2);
151        }
152    }
153}
154
155impl<D: DataMut, T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPrepared<D, T, BE> {
156    pub(crate) fn encrypt_sk<M, S>(
157        &mut self,
158        module: &M,
159        value: T,
160        sk: &S,
161        source_xa: &mut Source,
162        source_xe: &mut Source,
163        scratch: &mut Scratch<BE>,
164    ) where
165        S: GLWESecretPreparedToRef<BE> + GLWEInfos,
166        M: FheUintBlocksPreparedEncryptSk<T, BE>,
167        Scratch<BE>: ScratchTakeCore<BE>,
168    {
169        module.fhe_uint_blocks_prepared_encrypt_sk(self, value, sk, source_xa, source_xe, scratch);
170    }
171}
172
173impl<D: DataRef, T: UnsignedInteger, B: Backend> LWEInfos for FheUintBlocksPrepared<D, T, B> {
174    fn base2k(&self) -> poulpy_core::layouts::Base2K {
175        self.blocks[0].base2k()
176    }
177
178    fn k(&self) -> poulpy_core::layouts::TorusPrecision {
179        self.blocks[0].k()
180    }
181
182    fn n(&self) -> poulpy_core::layouts::Degree {
183        self.blocks[0].n()
184    }
185}
186
187impl<D: DataRef, T: UnsignedInteger, B: Backend> GLWEInfos for FheUintBlocksPrepared<D, T, B> {
188    fn rank(&self) -> poulpy_core::layouts::Rank {
189        self.blocks[0].rank()
190    }
191}
192
193impl<D: DataRef, T: UnsignedInteger, B: Backend> GGSWInfos for FheUintBlocksPrepared<D, T, B> {
194    fn dsize(&self) -> poulpy_core::layouts::Dsize {
195        self.blocks[0].dsize()
196    }
197
198    fn dnum(&self) -> poulpy_core::layouts::Dnum {
199        self.blocks[0].dnum()
200    }
201}