arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/fhe_uint_prepared_debug.rs
poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/fhe_uint_prepared_debug.rsRaw
  1use std::marker::PhantomData;
  2
  3use crate::tfhe::bdd_arithmetic::{BDDKeyPrepared, FheUint, FheUintPrepareDebug, ToBits};
  4use crate::tfhe::{
  5    bdd_arithmetic::UnsignedInteger, blind_rotation::BlindRotationAlgo, circuit_bootstrapping::CirtuitBootstrappingExecute,
  6};
  7use poulpy_core::GGSWNoise;
  8
  9use poulpy_core::layouts::{Base2K, Dnum, Dsize, Rank, TorusPrecision};
 10use poulpy_core::layouts::{GGSW, GLWESecretPreparedToRef};
 11use poulpy_core::{
 12    LWEFromGLWE, ScratchTakeCore,
 13    layouts::{GGSWInfos, GGSWPreparedFactory, GLWEInfos, LWEInfos},
 14};
 15
 16use poulpy_hal::api::ModuleN;
 17use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
 18
 19pub struct FheUintPreparedDebug<D: Data, T: UnsignedInteger> {
 20    pub(crate) bits: Vec<GGSW<D>>,
 21    pub(crate) _phantom: PhantomData<T>,
 22}
 23
 24impl<T: UnsignedInteger> FheUintPreparedDebug<Vec<u8>, T> {
 25    pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
 26    where
 27        M: ModuleN,
 28        A: GGSWInfos,
 29    {
 30        Self::alloc(
 31            module,
 32            infos.base2k(),
 33            infos.k(),
 34            infos.dnum(),
 35            infos.dsize(),
 36            infos.rank(),
 37        )
 38    }
 39
 40    pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
 41    where
 42        M: ModuleN,
 43    {
 44        Self {
 45            bits: (0..T::BITS)
 46                .map(|_| GGSW::alloc(module.n().into(), base2k, k, rank, dnum, dsize))
 47                .collect(),
 48            _phantom: PhantomData,
 49        }
 50    }
 51}
 52
 53impl<D: DataRef, T: UnsignedInteger> LWEInfos for FheUintPreparedDebug<D, T> {
 54    fn base2k(&self) -> poulpy_core::layouts::Base2K {
 55        self.bits[0].base2k()
 56    }
 57
 58    fn k(&self) -> poulpy_core::layouts::TorusPrecision {
 59        self.bits[0].k()
 60    }
 61
 62    fn n(&self) -> poulpy_core::layouts::Degree {
 63        self.bits[0].n()
 64    }
 65}
 66
 67impl<D: DataRef, T: UnsignedInteger> GLWEInfos for FheUintPreparedDebug<D, T> {
 68    fn rank(&self) -> poulpy_core::layouts::Rank {
 69        self.bits[0].rank()
 70    }
 71}
 72
 73impl<D: DataRef, T: UnsignedInteger> GGSWInfos for FheUintPreparedDebug<D, T> {
 74    fn dsize(&self) -> poulpy_core::layouts::Dsize {
 75        self.bits[0].dsize()
 76    }
 77
 78    fn dnum(&self) -> poulpy_core::layouts::Dnum {
 79        self.bits[0].dnum()
 80    }
 81}
 82
 83impl<D: DataRef, T: UnsignedInteger + ToBits> FheUintPreparedDebug<D, T> {
 84    pub fn print_noise<S, M, BE: Backend>(&self, module: &M, sk: &S, want: T)
 85    where
 86        S: GLWESecretPreparedToRef<BE>,
 87        M: GGSWNoise<BE>,
 88    {
 89        for (i, ggsw) in self.bits.iter().enumerate() {
 90            use poulpy_hal::layouts::{ScalarZnx, ZnxViewMut};
 91            let mut pt_want = ScalarZnx::alloc(self.n().into(), 1);
 92            pt_want.at_mut(0, 0)[0] = want.bit(i) as i64;
 93            ggsw.print_noise(module, sk, &pt_want);
 94        }
 95    }
 96
 97    pub fn assert_noise<S, M, F, BE: Backend>(&self, module: &M, sk: &S, want: T, max_noise: &F)
 98    where
 99        S: GLWESecretPreparedToRef<BE>,
100        M: GGSWNoise<BE>,
101        F: Fn(usize) -> f64,
102    {
103        for (i, ggsw) in self.bits.iter().enumerate() {
104            use poulpy_hal::layouts::{ScalarZnx, ZnxViewMut};
105            let mut pt_want = ScalarZnx::alloc(self.n().into(), 1);
106            pt_want.at_mut(0, 0)[0] = want.bit(i) as i64;
107            ggsw.assert_noise(module, sk, &pt_want, max_noise);
108        }
109    }
110}
111
112impl<BRA: BlindRotationAlgo, BE: Backend, T: UnsignedInteger> FheUintPrepareDebug<BRA, T, BE> for Module<BE>
113where
114    Self: ModuleN + LWEFromGLWE<BE> + CirtuitBootstrappingExecute<BRA, BE> + GGSWPreparedFactory<BE>,
115    Scratch<BE>: ScratchTakeCore<BE>,
116{
117    fn fhe_uint_debug_prepare<DM, DR0, DR1>(
118        &self,
119        res: &mut FheUintPreparedDebug<DM, T>,
120        bits: &FheUint<DR0, T>,
121        key: &BDDKeyPrepared<DR1, BRA, BE>,
122        scratch: &mut Scratch<BE>,
123    ) where
124        DM: DataMut,
125        DR0: DataRef,
126        DR1: DataRef,
127    {
128        let (_, scratch_1) = scratch.take_ggsw(res);
129        let (mut tmp_lwe, scratch_2) = scratch_1.take_lwe(bits);
130        for (bit, dst) in res.bits.iter_mut().enumerate() {
131            bits.get_bit_lwe(self, bit, &mut tmp_lwe, &key.ks, scratch_2);
132            key.cbt
133                .execute_to_constant(self, dst, &tmp_lwe, 1, 1, scratch_2);
134        }
135    }
136}
137
138impl<D: DataMut, T: UnsignedInteger> FheUintPreparedDebug<D, T> {
139    pub fn prepare<BRA, M, O, K, BE: Backend>(
140        &mut self,
141        module: &M,
142        other: &FheUint<O, T>,
143        key: &BDDKeyPrepared<K, BRA, BE>,
144        scratch: &mut Scratch<BE>,
145    ) where
146        BRA: BlindRotationAlgo,
147        O: DataRef,
148        K: DataRef,
149        M: FheUintPrepareDebug<BRA, T, BE>,
150        Scratch<BE>: ScratchTakeCore<BE>,
151    {
152        module.fhe_uint_debug_prepare(self, other, key, scratch);
153    }
154}