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::{
  3        ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare,
  4        VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace,
  5        VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy,
  6        VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace,
  7        VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd,
  8        VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal, ZnFillUniform, ZnNormalizeInplace,
  9    },
 10    layouts::{Backend, Module, ScratchOwned, ZnxView},
 11    oep::{
 12        ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
 13        TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
 14    },
 15    source::Source,
 16};
 17
 18use crate::layouts::{
 19    LWECiphertext, LWECiphertextLayout, LWEPlaintext, LWESecret, LWESwitchingKey, LWESwitchingKeyLayout,
 20    prepared::{LWESwitchingKeyPrepared, PrepareAlloc},
 21};
 22
 23pub fn test_lwe_keyswitch<B>(module: &Module<B>)
 24where
 25    Module<B>: VecZnxDftAllocBytes
 26        + VecZnxBigNormalize<B>
 27        + VecZnxDftApply<B>
 28        + SvpApplyDftToDftInplace<B>
 29        + VecZnxIdftApplyConsume<B>
 30        + VecZnxFillUniform
 31        + VecZnxSubInplace
 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        + VmpApplyDftToDftTmpBytes
 48        + VmpApplyDftToDft<B>
 49        + VmpApplyDftToDftAdd<B>
 50        + VecZnxBigNormalizeTmpBytes
 51        + VecZnxSwitchRing
 52        + VecZnxAutomorphismInplace<B>
 53        + ZnNormalizeInplace<B>
 54        + ZnFillUniform
 55        + ZnAddNormal
 56        + VecZnxCopy,
 57    B: Backend
 58        + TakeVecZnxDftImpl<B>
 59        + TakeVecZnxBigImpl<B>
 60        + TakeSvpPPolImpl<B>
 61        + ScratchOwnedAllocImpl<B>
 62        + ScratchOwnedBorrowImpl<B>
 63        + ScratchAvailableImpl<B>
 64        + TakeScalarZnxImpl<B>
 65        + TakeVecZnxImpl<B>,
 66{
 67    let n: usize = module.n();
 68    let base2k: usize = 17;
 69
 70    let n_lwe_in: usize = 22;
 71    let n_lwe_out: usize = 30;
 72    let k_lwe_ct: usize = 2 * base2k;
 73    let k_lwe_pt: usize = 8;
 74
 75    let k_ksk: usize = k_lwe_ct + base2k;
 76    let dnum: usize = k_lwe_ct.div_ceil(base2k);
 77
 78    let mut source_xs: Source = Source::new([0u8; 32]);
 79    let mut source_xa: Source = Source::new([0u8; 32]);
 80    let mut source_xe: Source = Source::new([0u8; 32]);
 81
 82    let key_apply_infos: LWESwitchingKeyLayout = LWESwitchingKeyLayout {
 83        n: n.into(),
 84        base2k: base2k.into(),
 85        k: k_ksk.into(),
 86        dnum: dnum.into(),
 87    };
 88
 89    let lwe_in_infos: LWECiphertextLayout = LWECiphertextLayout {
 90        n: n_lwe_in.into(),
 91        base2k: base2k.into(),
 92        k: k_lwe_ct.into(),
 93    };
 94
 95    let lwe_out_infos: LWECiphertextLayout = LWECiphertextLayout {
 96        n: n_lwe_out.into(),
 97        k: k_lwe_ct.into(),
 98        base2k: base2k.into(),
 99    };
100
101    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
102        LWESwitchingKey::encrypt_sk_scratch_space(module, &key_apply_infos)
103            | LWECiphertext::keyswitch_scratch_space(module, &lwe_out_infos, &lwe_in_infos, &key_apply_infos),
104    );
105
106    let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in.into());
107    sk_lwe_in.fill_ternary_prob(0.5, &mut source_xs);
108
109    let mut sk_lwe_out: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_out.into());
110    sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs);
111
112    let data: i64 = 17;
113
114    let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_with(base2k.into(), k_lwe_pt.into());
115    lwe_pt_in.encode_i64(data, k_lwe_pt.into());
116
117    let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_in_infos);
118    lwe_ct_in.encrypt_sk(
119        module,
120        &lwe_pt_in,
121        &sk_lwe_in,
122        &mut source_xa,
123        &mut source_xe,
124    );
125
126    let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(&key_apply_infos);
127
128    ksk.encrypt_sk(
129        module,
130        &sk_lwe_in,
131        &sk_lwe_out,
132        &mut source_xa,
133        &mut source_xe,
134        scratch.borrow(),
135    );
136
137    let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_out_infos);
138
139    let ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow());
140
141    lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_prepared, scratch.borrow());
142
143    let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(&lwe_out_infos);
144    lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out);
145
146    assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
147}