poulpy/poulpy-hal/src/tests/vmp_pmat/vmp_apply.rs
poulpy-hal/src/tests/vmp_pmat/vmp_apply.rsRaw
1use crate::{
2 api::{
3 ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxBigAlloc, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
4 VecZnxDftAlloc, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigTmpA, VmpApply, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
5 ZnxInfos, ZnxViewMut,
6 },
7 layouts::{MatZnx, Module, ScratchOwned, VecZnx, VecZnxBig, VecZnxDft, VmpPMat},
8 oep::{
9 ModuleNewImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, VecZnxBigAllocImpl, VecZnxBigNormalizeImpl,
10 VecZnxBigNormalizeTmpBytesImpl, VecZnxDftAllocImpl, VecZnxDftFromVecZnxImpl, VecZnxDftToVecZnxBigTmpAImpl, VmpApplyImpl,
11 VmpApplyTmpBytesImpl, VmpPMatAllocImpl, VmpPMatPrepareImpl,
12 },
13};
14
15use crate::layouts::Backend;
16
17pub fn test_vmp_apply<B>()
18where
19 B: Backend
20 + ModuleNewImpl<B>
21 + VmpApplyTmpBytesImpl<B>
22 + VecZnxBigNormalizeTmpBytesImpl<B>
23 + VmpPMatAllocImpl<B>
24 + VecZnxDftAllocImpl<B>
25 + VecZnxBigAllocImpl<B>
26 + VmpPMatPrepareImpl<B>
27 + VecZnxDftFromVecZnxImpl<B>
28 + VmpApplyImpl<B>
29 + VecZnxDftToVecZnxBigTmpAImpl<B>
30 + ScratchOwnedAllocImpl<B>
31 + ScratchOwnedBorrowImpl<B>
32 + VecZnxBigNormalizeImpl<B>,
33{
34 let log_n: i32 = 5;
35 let n: usize = 1 << log_n;
36
37 let module: Module<B> = Module::<B>::new(n as u64);
38 let basek: usize = 15;
39 let a_size: usize = 5;
40 let mat_size: usize = 6;
41 let res_size: usize = a_size;
42
43 [1, 2].iter().for_each(|cols_in| {
44 [1, 2].iter().for_each(|cols_out| {
45 let a_cols: usize = *cols_in;
46 let res_cols: usize = *cols_out;
47
48 let mat_rows: usize = a_size;
49 let mat_cols_in: usize = a_cols;
50 let mat_cols_out: usize = res_cols;
51
52 let mut scratch = ScratchOwned::alloc(
53 module.vmp_apply_tmp_bytes(
54 res_size,
55 a_size,
56 mat_rows,
57 mat_cols_in,
58 mat_cols_out,
59 mat_size,
60 ) | module.vec_znx_big_normalize_tmp_bytes(),
61 );
62
63 let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, a_cols, a_size);
64
65 (0..a_cols).for_each(|i| {
66 a.at_mut(i, a_size - 1)[i + 1] = 1;
67 });
68
69 let mut vmp: VmpPMat<Vec<u8>, B> = module.vmp_pmat_alloc(mat_rows, mat_cols_in, mat_cols_out, mat_size);
70
71 let mut c_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(mat_cols_out, mat_size);
72 let mut c_big: VecZnxBig<Vec<u8>, B> = module.vec_znx_big_alloc(mat_cols_out, mat_size);
73
74 let mut mat: MatZnx<Vec<u8>> = MatZnx::alloc(n, mat_rows, mat_cols_in, mat_cols_out, mat_size);
75
76 // Construts a [VecZnxMatDft] that performs cyclic rotations on each submatrix.
77 (0..a.size()).for_each(|row_i| {
78 (0..mat_cols_in).for_each(|col_in_i| {
79 (0..mat_cols_out).for_each(|col_out_i| {
80 let idx = 1 + col_in_i * mat_cols_out + col_out_i;
81 mat.at_mut(row_i, col_in_i).at_mut(col_out_i, row_i)[idx] = 1_i64; // X^{idx}
82 });
83 });
84 });
85
86 module.vmp_prepare(&mut vmp, &mat, scratch.borrow());
87
88 let mut a_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(a_cols, a_size);
89 (0..a_cols).for_each(|i| {
90 module.vec_znx_dft_from_vec_znx(1, 0, &mut a_dft, i, &a, i);
91 });
92
93 module.vmp_apply(&mut c_dft, &a_dft, &vmp, scratch.borrow());
94
95 let mut res_have_vi64: Vec<i64> = vec![i64::default(); n];
96
97 let mut res_have: VecZnx<Vec<u8>> = VecZnx::alloc(n, res_cols, res_size);
98 (0..mat_cols_out).for_each(|i| {
99 module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut c_big, i, &mut c_dft, i);
100 module.vec_znx_big_normalize(basek, &mut res_have, i, &c_big, i, scratch.borrow());
101 });
102
103 (0..mat_cols_out).for_each(|col_i| {
104 let mut res_want_vi64: Vec<i64> = vec![i64::default(); n];
105 (0..a_cols).for_each(|i| {
106 res_want_vi64[(i + 1) + (1 + i * mat_cols_out + col_i)] = 1;
107 });
108 res_have.decode_vec_i64(basek, col_i, basek * a_size, &mut res_have_vi64);
109 assert_eq!(res_have_vi64, res_want_vi64);
110 });
111 });
112 });
113}