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