arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/tests/generics/keyswitch/lwe_ct.rs
poulpy-core/src/tests/generics/keyswitch/lwe_ct.rsRaw
  1use poulpy_backend::hal::{
  2    api::{
  3        ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace,
  4        VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
  5        VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
  6        VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes,
  7        VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree, VmpApply, VmpApplyAdd, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
  8        ZnxView,
  9    },
 10    layouts::{Backend, Module, ScratchOwned},
 11    oep::{
 12        ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
 13        TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
 14    },
 15    source::Source,
 16};
 17
 18use crate::layouts::{
 19    Infos, LWECiphertext, LWEPlaintext, LWESecret, LWESwitchingKey,
 20    prepared::{LWESwitchingKeyPrepared, PrepareAlloc},
 21};
 22
 23pub fn test_lwe_keyswitch<B>(module: &Module<B>)
 24where
 25    Module<B>: VecZnxDftAllocBytes
 26        + VecZnxBigNormalize<B>
 27        + VecZnxDftFromVecZnx<B>
 28        + SvpApplyInplace<B>
 29        + VecZnxDftToVecZnxBigConsume<B>
 30        + VecZnxFillUniform
 31        + VecZnxSubABInplace
 32        + VecZnxAddInplace
 33        + VecZnxNormalizeInplace<B>
 34        + VecZnxAddNormal
 35        + VecZnxNormalize<B>
 36        + VecZnxSub
 37        + SvpPrepare<B>
 38        + SvpPPolAllocBytes
 39        + SvpPPolAlloc<B>
 40        + VecZnxBigAllocBytes
 41        + VecZnxBigAddInplace<B>
 42        + VecZnxBigAddSmallInplace<B>
 43        + VecZnxNormalizeTmpBytes
 44        + VecZnxAddScalarInplace
 45        + VmpPMatAlloc<B>
 46        + VmpPrepare<B>
 47        + VmpApplyTmpBytes
 48        + VmpApply<B>
 49        + VmpApplyAdd<B>
 50        + VecZnxBigNormalizeTmpBytes
 51        + VecZnxSwithcDegree
 52        + VecZnxAutomorphismInplace,
 53    B: Backend
 54        + TakeVecZnxDftImpl<B>
 55        + TakeVecZnxBigImpl<B>
 56        + TakeSvpPPolImpl<B>
 57        + ScratchOwnedAllocImpl<B>
 58        + ScratchOwnedBorrowImpl<B>
 59        + ScratchAvailableImpl<B>
 60        + TakeScalarZnxImpl<B>
 61        + TakeVecZnxImpl<B>,
 62{
 63    let n: usize = module.n();
 64    let basek: usize = 17;
 65    let sigma: f64 = 3.2;
 66
 67    let n_lwe_in: usize = 22;
 68    let n_lwe_out: usize = 30;
 69    let k_lwe_ct: usize = 2 * basek;
 70    let k_lwe_pt: usize = 8;
 71
 72    let k_ksk: usize = k_lwe_ct + basek;
 73
 74    let mut source_xs: Source = Source::new([0u8; 32]);
 75    let mut source_xa: Source = Source::new([0u8; 32]);
 76    let mut source_xe: Source = Source::new([0u8; 32]);
 77
 78    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
 79        LWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ksk)
 80            | LWECiphertext::keyswitch_scratch_space(module, n, basek, k_lwe_ct, k_lwe_ct, k_ksk),
 81    );
 82
 83    let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in);
 84    sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs);
 85
 86    let mut sk_lwe_out: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_out);
 87    sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs);
 88
 89    let data: i64 = 17;
 90
 91    let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_pt);
 92
 93    lwe_pt_in.encode_i64(data, k_lwe_pt);
 94
 95    let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_in, basek, k_lwe_ct);
 96    lwe_ct_in.encrypt_sk(
 97        module,
 98        &lwe_pt_in,
 99        &sk_lwe_in,
100        &mut source_xa,
101        &mut source_xe,
102        sigma,
103    );
104
105    let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(n, basek, k_ksk, lwe_ct_in.size());
106
107    ksk.encrypt_sk(
108        module,
109        &sk_lwe_in,
110        &sk_lwe_out,
111        &mut source_xa,
112        &mut source_xe,
113        sigma,
114        scratch.borrow(),
115    );
116
117    let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(n_lwe_out, basek, k_lwe_ct);
118
119    let ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
120
121    lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_prepared, scratch.borrow());
122
123    let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(basek, k_lwe_ct);
124    lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out);
125
126    assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
127}