poulpy/poulpy-hal/src/reference/vec_znx/normalize.rs
poulpy-hal/src/reference/vec_znx/normalize.rsRaw
1use std::hint::black_box;
2
3use criterion::{BenchmarkId, Criterion};
4
5use crate::{
6 api::{ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes},
7 layouts::{Backend, FillUniform, Module, ScratchOwned, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos, ZnxView, ZnxViewMut},
8 reference::znx::{
9 ZnxNormalizeFinalStep, ZnxNormalizeFinalStepInplace, ZnxNormalizeFirstStep, ZnxNormalizeFirstStepCarryOnly,
10 ZnxNormalizeFirstStepInplace, ZnxNormalizeMiddleStep, ZnxNormalizeMiddleStepCarryOnly, ZnxNormalizeMiddleStepInplace,
11 ZnxZero,
12 },
13 source::Source,
14};
15
16pub fn vec_znx_normalize_tmp_bytes(n: usize) -> usize {
17 n * size_of::<i64>()
18}
19
20pub fn vec_znx_normalize<R, A, ZNXARI>(basek: usize, res: &mut R, res_col: usize, a: &A, a_col: usize, carry: &mut [i64])
21where
22 R: VecZnxToMut,
23 A: VecZnxToRef,
24 ZNXARI: ZnxZero
25 + ZnxNormalizeFirstStepCarryOnly
26 + ZnxNormalizeMiddleStepCarryOnly
27 + ZnxNormalizeMiddleStep
28 + ZnxNormalizeFinalStep
29 + ZnxNormalizeFirstStep,
30{
31 let mut res: VecZnx<&mut [u8]> = res.to_mut();
32 let a: VecZnx<&[u8]> = a.to_ref();
33
34 #[cfg(debug_assertions)]
35 {
36 assert!(carry.len() >= res.n());
37 }
38
39 let res_size: usize = res.size();
40 let a_size = a.size();
41
42 if a_size > res_size {
43 for j in (res_size..a_size).rev() {
44 if j == a_size - 1 {
45 ZNXARI::znx_normalize_first_step_carry_only(basek, 0, a.at(a_col, j), carry);
46 } else {
47 ZNXARI::znx_normalize_middle_step_carry_only(basek, 0, a.at(a_col, j), carry);
48 }
49 }
50
51 for j in (1..res_size).rev() {
52 ZNXARI::znx_normalize_middle_step(basek, 0, res.at_mut(res_col, j), a.at(a_col, j), carry);
53 }
54
55 ZNXARI::znx_normalize_final_step(basek, 0, res.at_mut(res_col, 0), a.at(a_col, 0), carry);
56 } else {
57 for j in (0..a_size).rev() {
58 if j == a_size - 1 {
59 ZNXARI::znx_normalize_first_step(basek, 0, res.at_mut(res_col, j), a.at(a_col, j), carry);
60 } else if j == 0 {
61 ZNXARI::znx_normalize_final_step(basek, 0, res.at_mut(res_col, j), a.at(a_col, j), carry);
62 } else {
63 ZNXARI::znx_normalize_middle_step(basek, 0, res.at_mut(res_col, j), a.at(a_col, j), carry);
64 }
65 }
66
67 for j in a_size..res_size {
68 ZNXARI::znx_zero(res.at_mut(res_col, j));
69 }
70 }
71}
72
73pub fn vec_znx_normalize_inplace<R: VecZnxToMut, ZNXARI>(basek: usize, res: &mut R, res_col: usize, carry: &mut [i64])
74where
75 ZNXARI: ZnxNormalizeFirstStepInplace + ZnxNormalizeMiddleStepInplace + ZnxNormalizeFinalStepInplace,
76{
77 let mut res: VecZnx<&mut [u8]> = res.to_mut();
78
79 #[cfg(debug_assertions)]
80 {
81 assert!(carry.len() >= res.n());
82 }
83
84 let res_size: usize = res.size();
85
86 for j in (0..res_size).rev() {
87 if j == res_size - 1 {
88 ZNXARI::znx_normalize_first_step_inplace(basek, 0, res.at_mut(res_col, j), carry);
89 } else if j == 0 {
90 ZNXARI::znx_normalize_final_step_inplace(basek, 0, res.at_mut(res_col, j), carry);
91 } else {
92 ZNXARI::znx_normalize_middle_step_inplace(basek, 0, res.at_mut(res_col, j), carry);
93 }
94 }
95}
96
97pub fn bench_vec_znx_normalize<B: Backend>(c: &mut Criterion, label: &str)
98where
99 Module<B>: VecZnxNormalize<B> + ModuleNew<B> + VecZnxNormalizeTmpBytes,
100 ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
101{
102 let group_name: String = format!("vec_znx_normalize::{}", label);
103
104 let mut group = c.benchmark_group(group_name);
105
106 fn runner<B: Backend>(params: [usize; 3]) -> impl FnMut()
107 where
108 Module<B>: VecZnxNormalize<B> + ModuleNew<B> + VecZnxNormalizeTmpBytes,
109 ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
110 {
111 let n: usize = 1 << params[0];
112 let cols: usize = params[1];
113 let size: usize = params[2];
114
115 let module: Module<B> = Module::<B>::new(n as u64);
116
117 let basek: usize = 50;
118
119 let mut source: Source = Source::new([0u8; 32]);
120
121 let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
122 let mut res: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
123
124 // Fill a with random i64
125 a.fill_uniform(50, &mut source);
126 res.fill_uniform(50, &mut source);
127
128 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(module.vec_znx_normalize_tmp_bytes());
129
130 move || {
131 for i in 0..cols {
132 module.vec_znx_normalize(basek, &mut res, i, &a, i, scratch.borrow());
133 }
134 black_box(());
135 }
136 }
137
138 for params in [[10, 2, 2], [11, 2, 4], [12, 2, 8], [13, 2, 16], [14, 2, 32]] {
139 let id: BenchmarkId = BenchmarkId::from_parameter(format!("{}x({}x{})", 1 << params[0], params[1], params[2],));
140 let mut runner = runner::<B>(params);
141 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
142 }
143
144 group.finish();
145}
146
147pub fn bench_vec_znx_normalize_inplace<B: Backend>(c: &mut Criterion, label: &str)
148where
149 Module<B>: VecZnxNormalizeInplace<B> + ModuleNew<B> + VecZnxNormalizeTmpBytes,
150 ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
151{
152 let group_name: String = format!("vec_znx_normalize_inplace::{}", label);
153
154 let mut group = c.benchmark_group(group_name);
155
156 fn runner<B: Backend>(params: [usize; 3]) -> impl FnMut()
157 where
158 Module<B>: VecZnxNormalizeInplace<B> + ModuleNew<B> + VecZnxNormalizeTmpBytes,
159 ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
160 {
161 let n: usize = 1 << params[0];
162 let cols: usize = params[1];
163 let size: usize = params[2];
164
165 let module: Module<B> = Module::<B>::new(n as u64);
166
167 let basek: usize = 50;
168
169 let mut source: Source = Source::new([0u8; 32]);
170
171 let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, cols, size);
172
173 // Fill a with random i64
174 a.fill_uniform(50, &mut source);
175
176 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(module.vec_znx_normalize_tmp_bytes());
177
178 move || {
179 for i in 0..cols {
180 module.vec_znx_normalize_inplace(basek, &mut a, i, scratch.borrow());
181 }
182 black_box(());
183 }
184 }
185
186 for params in [[10, 2, 2], [11, 2, 4], [12, 2, 8], [13, 2, 16], [14, 2, 32]] {
187 let id: BenchmarkId = BenchmarkId::from_parameter(format!("{}x({}x{})", 1 << params[0], params[1], params[2],));
188 let mut runner = runner::<B>(params);
189 group.bench_with_input(id, &(), |b, _| b.iter(&mut runner));
190 }
191
192 group.finish();
193}