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