arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/tests/test_suite/keyswitch/lwe_ct.rs
poulpy-core/src/tests/test_suite/keyswitch/lwe_ct.rsRaw
  1use poulpy_hal::{
  2    api::{ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow},
  3    layouts::{Backend, Module, Scratch, ScratchOwned, ZnxView},
  4    source::Source,
  5};
  6
  7use crate::{
  8    ScratchTakeCore,
  9    layouts::{
 10        LWE, LWELayout, LWEPlaintext, LWESecret, LWESwitchingKey, LWESwitchingKeyLayout, prepared::LWESwitchingKeyPrepared,
 11    },
 12};
 13
 14pub fn test_lwe_keyswitch<BE: Backend>(module: &Module<BE>)
 15where
 16    Module<BE>:,
 17    ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
 18    Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
 19{
 20    let n: usize = module.n();
 21    let base2k: usize = 17;
 22
 23    let n_lwe_in: usize = 22;
 24    let n_lwe_out: usize = 30;
 25    let k_lwe_ct: usize = 2 * base2k;
 26    let k_lwe_pt: usize = 8;
 27
 28    let k_ksk: usize = k_lwe_ct + base2k;
 29    let dnum: usize = k_lwe_ct.div_ceil(base2k);
 30
 31    let mut source_xs: Source = Source::new([0u8; 32]);
 32    let mut source_xa: Source = Source::new([0u8; 32]);
 33    let mut source_xe: Source = Source::new([0u8; 32]);
 34
 35    let key_apply_infos: LWESwitchingKeyLayout = LWESwitchingKeyLayout {
 36        n: n.into(),
 37        base2k: base2k.into(),
 38        k: k_ksk.into(),
 39        dnum: dnum.into(),
 40    };
 41
 42    let lwe_in_infos: LWELayout = LWELayout {
 43        n: n_lwe_in.into(),
 44        base2k: base2k.into(),
 45        k: k_lwe_ct.into(),
 46    };
 47
 48    let lwe_out_infos: LWELayout = LWELayout {
 49        n: n_lwe_out.into(),
 50        k: k_lwe_ct.into(),
 51        base2k: base2k.into(),
 52    };
 53
 54    let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(
 55        LWESwitchingKey::encrypt_sk_tmp_bytes(module, &key_apply_infos)
 56            | LWE::keyswitch_tmp_bytes(module, &lwe_out_infos, &lwe_in_infos, &key_apply_infos),
 57    );
 58
 59    let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in.into());
 60    sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs);
 61
 62    let mut sk_lwe_out: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_out.into());
 63    sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs);
 64
 65    let data: i64 = 17;
 66
 67    let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k.into(), k_lwe_pt.into());
 68    lwe_pt_in.encode_i64(data, k_lwe_pt.into());
 69
 70    let mut lwe_ct_in: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_in_infos);
 71    lwe_ct_in.encrypt_sk(
 72        module,
 73        &lwe_pt_in,
 74        &sk_lwe_in,
 75        &mut source_xa,
 76        &mut source_xe,
 77    );
 78
 79    let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc_from_infos(&key_apply_infos);
 80
 81    ksk.encrypt_sk(
 82        module,
 83        &sk_lwe_in,
 84        &sk_lwe_out,
 85        &mut source_xa,
 86        &mut source_xe,
 87        scratch.borrow(),
 88    );
 89
 90    let mut lwe_ct_out: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_out_infos);
 91
 92    let ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, BE> = ksk.prepare_alloc(module, scratch.borrow());
 93
 94    lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_prepared, scratch.borrow());
 95
 96    let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_from_infos(&lwe_out_infos);
 97    lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out);
 98
 99    assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
100}