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