poulpy/poulpy-hal/src/reference/fft64/vec_znx_big.rs
poulpy-hal/src/reference/fft64/vec_znx_big.rsRaw
1use std::f64::consts::SQRT_2;
2
3use crate::{
4 api::VecZnxBigAddNormal,
5 layouts::{
6 Backend, Module, VecZnx, VecZnxBig, VecZnxBigToMut, VecZnxBigToRef, VecZnxToMut, VecZnxToRef, ZnxView, ZnxViewMut,
7 },
8 oep::VecZnxBigAllocBytesImpl,
9 reference::{
10 vec_znx::{
11 vec_znx_add, vec_znx_add_inplace, vec_znx_automorphism, vec_znx_automorphism_inplace, vec_znx_negate,
12 vec_znx_negate_inplace, vec_znx_normalize, vec_znx_sub, vec_znx_sub_inplace, vec_znx_sub_negate_inplace,
13 },
14 znx::{
15 ZnxAdd, ZnxAddInplace, ZnxAutomorphism, ZnxCopy, ZnxExtractDigitAddMul, ZnxMulPowerOfTwoInplace, ZnxNegate,
16 ZnxNegateInplace, ZnxNormalizeDigit, ZnxNormalizeFinalStep, ZnxNormalizeFirstStep, ZnxNormalizeFirstStepCarryOnly,
17 ZnxNormalizeMiddleStep, ZnxNormalizeMiddleStepCarryOnly, ZnxSub, ZnxSubInplace, ZnxSubNegateInplace, ZnxZero,
18 znx_add_normal_f64_ref,
19 },
20 },
21 source::Source,
22};
23
24pub fn vec_znx_big_add<R, A, B, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
25where
26 BE: Backend<ScalarBig = i64> + ZnxAdd + ZnxCopy + ZnxZero,
27 R: VecZnxBigToMut<BE>,
28 A: VecZnxBigToRef<BE>,
29 B: VecZnxBigToRef<BE>,
30{
31 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
32 let a: VecZnxBig<&[u8], BE> = a.to_ref();
33 let b: VecZnxBig<&[u8], BE> = b.to_ref();
34
35 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
36 data: res.data,
37 n: res.n,
38 cols: res.cols,
39 size: res.size,
40 max_size: res.max_size,
41 };
42
43 let a_vznx: VecZnx<&[u8]> = VecZnx {
44 data: a.data,
45 n: a.n,
46 cols: a.cols,
47 size: a.size,
48 max_size: a.max_size,
49 };
50
51 let b_vznx: VecZnx<&[u8]> = VecZnx {
52 data: b.data,
53 n: b.n,
54 cols: b.cols,
55 size: b.size,
56 max_size: b.max_size,
57 };
58
59 vec_znx_add::<_, _, _, BE>(&mut res_vznx, res_col, &a_vznx, a_col, &b_vznx, b_col);
60}
61
62pub fn vec_znx_big_add_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
63where
64 BE: Backend<ScalarBig = i64> + ZnxAddInplace,
65 R: VecZnxBigToMut<BE>,
66 A: VecZnxBigToRef<BE>,
67{
68 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
69 let a: VecZnxBig<&[u8], BE> = a.to_ref();
70
71 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
72 data: res.data,
73 n: res.n,
74 cols: res.cols,
75 size: res.size,
76 max_size: res.max_size,
77 };
78
79 let a_vznx: VecZnx<&[u8]> = VecZnx {
80 data: a.data,
81 n: a.n,
82 cols: a.cols,
83 size: a.size,
84 max_size: a.max_size,
85 };
86
87 vec_znx_add_inplace::<_, _, BE>(&mut res_vznx, res_col, &a_vznx, a_col);
88}
89
90pub fn vec_znx_big_add_small<R, A, B, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
91where
92 BE: Backend<ScalarBig = i64> + ZnxAdd + ZnxCopy + ZnxZero,
93 R: VecZnxBigToMut<BE>,
94 A: VecZnxBigToRef<BE>,
95 B: VecZnxToRef,
96{
97 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
98 let a: VecZnxBig<&[u8], BE> = a.to_ref();
99
100 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
101 data: res.data,
102 n: res.n,
103 cols: res.cols,
104 size: res.size,
105 max_size: res.max_size,
106 };
107
108 let a_vznx: VecZnx<&[u8]> = VecZnx {
109 data: a.data,
110 n: a.n,
111 cols: a.cols,
112 size: a.size,
113 max_size: a.max_size,
114 };
115
116 vec_znx_add::<_, _, _, BE>(&mut res_vznx, res_col, &a_vznx, a_col, b, b_col);
117}
118
119pub fn vec_znx_big_add_small_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
120where
121 BE: Backend<ScalarBig = i64> + ZnxAddInplace,
122 R: VecZnxBigToMut<BE>,
123 A: VecZnxToRef,
124{
125 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
126 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
127 data: res.data,
128 n: res.n,
129 cols: res.cols,
130 size: res.size,
131 max_size: res.max_size,
132 };
133
134 vec_znx_add_inplace::<_, _, BE>(&mut res_vznx, res_col, a, a_col);
135}
136
137pub fn vec_znx_big_automorphism_inplace_tmp_bytes(n: usize) -> usize {
138 n * size_of::<i64>()
139}
140
141pub fn vec_znx_big_automorphism<R, A, BE>(p: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
142where
143 BE: Backend<ScalarBig = i64> + ZnxAutomorphism + ZnxZero,
144 R: VecZnxBigToMut<BE>,
145 A: VecZnxBigToRef<BE>,
146{
147 let res: VecZnxBig<&mut [u8], _> = res.to_mut();
148 let a: VecZnxBig<&[u8], _> = a.to_ref();
149
150 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
151 data: res.data,
152 n: res.n,
153 cols: res.cols,
154 size: res.size,
155 max_size: res.max_size,
156 };
157
158 let a_vznx: VecZnx<&[u8]> = VecZnx {
159 data: a.data,
160 n: a.n,
161 cols: a.cols,
162 size: a.size,
163 max_size: a.max_size,
164 };
165
166 vec_znx_automorphism::<_, _, BE>(p, &mut res_vznx, res_col, &a_vznx, a_col);
167}
168
169pub fn vec_znx_big_automorphism_inplace<R, BE>(p: i64, res: &mut R, res_col: usize, tmp: &mut [i64])
170where
171 BE: Backend<ScalarBig = i64> + ZnxAutomorphism + ZnxCopy,
172 R: VecZnxBigToMut<BE>,
173{
174 let res: VecZnxBig<&mut [u8], _> = res.to_mut();
175
176 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
177 data: res.data,
178 n: res.n,
179 cols: res.cols,
180 size: res.size,
181 max_size: res.max_size,
182 };
183
184 vec_znx_automorphism_inplace::<_, BE>(p, &mut res_vznx, res_col, tmp);
185}
186
187pub fn vec_znx_big_negate<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
188where
189 BE: Backend<ScalarBig = i64> + ZnxNegate + ZnxZero,
190 R: VecZnxBigToMut<BE>,
191 A: VecZnxBigToRef<BE>,
192{
193 let res: VecZnxBig<&mut [u8], _> = res.to_mut();
194 let a: VecZnxBig<&[u8], _> = a.to_ref();
195
196 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
197 data: res.data,
198 n: res.n,
199 cols: res.cols,
200 size: res.size,
201 max_size: res.max_size,
202 };
203
204 let a_vznx: VecZnx<&[u8]> = VecZnx {
205 data: a.data,
206 n: a.n,
207 cols: a.cols,
208 size: a.size,
209 max_size: a.max_size,
210 };
211
212 vec_znx_negate::<_, _, BE>(&mut res_vznx, res_col, &a_vznx, a_col);
213}
214
215pub fn vec_znx_big_negate_inplace<R, BE>(res: &mut R, res_col: usize)
216where
217 BE: Backend<ScalarBig = i64> + ZnxNegateInplace,
218 R: VecZnxBigToMut<BE>,
219{
220 let res: VecZnxBig<&mut [u8], _> = res.to_mut();
221
222 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
223 data: res.data,
224 n: res.n,
225 cols: res.cols,
226 size: res.size,
227 max_size: res.max_size,
228 };
229
230 vec_znx_negate_inplace::<_, BE>(&mut res_vznx, res_col);
231}
232
233pub fn vec_znx_big_normalize_tmp_bytes(n: usize) -> usize {
234 2 * n * size_of::<i64>()
235}
236
237pub fn vec_znx_big_normalize<R, A, BE>(
238 res_basek: usize,
239 res: &mut R,
240 res_col: usize,
241 a_basek: usize,
242 a: &A,
243 a_col: usize,
244 carry: &mut [i64],
245) where
246 R: VecZnxToMut,
247 A: VecZnxBigToRef<BE>,
248 BE: Backend<ScalarBig = i64>
249 + ZnxZero
250 + ZnxCopy
251 + ZnxAddInplace
252 + ZnxMulPowerOfTwoInplace
253 + ZnxNormalizeFirstStepCarryOnly
254 + ZnxNormalizeMiddleStepCarryOnly
255 + ZnxNormalizeMiddleStep
256 + ZnxNormalizeFinalStep
257 + ZnxNormalizeFirstStep
258 + ZnxExtractDigitAddMul
259 + ZnxNormalizeDigit,
260{
261 let a: VecZnxBig<&[u8], _> = a.to_ref();
262 let a_vznx: VecZnx<&[u8]> = VecZnx {
263 data: a.data,
264 n: a.n,
265 cols: a.cols,
266 size: a.size,
267 max_size: a.max_size,
268 };
269
270 vec_znx_normalize::<_, _, BE>(res_basek, res, res_col, a_basek, &a_vznx, a_col, carry);
271}
272
273pub fn vec_znx_big_add_normal_ref<R, B: Backend<ScalarBig = i64>>(
274 base2k: usize,
275 res: &mut R,
276 res_col: usize,
277 k: usize,
278 sigma: f64,
279 bound: f64,
280 source: &mut Source,
281) where
282 R: VecZnxBigToMut<B>,
283{
284 let mut res: VecZnxBig<&mut [u8], B> = res.to_mut();
285 assert!(
286 (bound.log2().ceil() as i64) < 64,
287 "invalid bound: ceil(log2(bound))={} > 63",
288 (bound.log2().ceil() as i64)
289 );
290
291 let limb: usize = k.div_ceil(base2k) - 1;
292 let scale: f64 = (1 << ((limb + 1) * base2k - k)) as f64;
293 znx_add_normal_f64_ref(
294 res.at_mut(res_col, limb),
295 sigma * scale,
296 bound * scale,
297 source,
298 )
299}
300
301pub fn test_vec_znx_big_add_normal<B>(module: &Module<B>)
302where
303 Module<B>: VecZnxBigAddNormal<B>,
304 B: Backend<ScalarBig = i64> + VecZnxBigAllocBytesImpl<B>,
305{
306 let n: usize = module.n();
307 let base2k: usize = 17;
308 let k: usize = 2 * 17;
309 let size: usize = 5;
310 let sigma: f64 = 3.2;
311 let bound: f64 = 6.0 * sigma;
312 let mut source: Source = Source::new([0u8; 32]);
313 let cols: usize = 2;
314 let zero: Vec<i64> = vec![0; n];
315 let k_f64: f64 = (1u64 << k as u64) as f64;
316 let sqrt2: f64 = SQRT_2;
317 (0..cols).for_each(|col_i| {
318 let mut a: VecZnxBig<Vec<u8>, B> = VecZnxBig::alloc(n, cols, size);
319 module.vec_znx_big_add_normal(base2k, &mut a, col_i, k, &mut source, sigma, bound);
320 module.vec_znx_big_add_normal(base2k, &mut a, col_i, k, &mut source, sigma, bound);
321 (0..cols).for_each(|col_j| {
322 if col_j != col_i {
323 (0..size).for_each(|limb_i| {
324 assert_eq!(a.at(col_j, limb_i), zero);
325 })
326 } else {
327 let std: f64 = a.std(base2k, col_i) * k_f64;
328 assert!(
329 (std - sigma * sqrt2).abs() < 0.1,
330 "std={} ~!= {}",
331 std,
332 sigma * sqrt2
333 );
334 }
335 })
336 });
337}
338
339/// R <- A - B
340pub fn vec_znx_big_sub<R, A, B, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
341where
342 BE: Backend<ScalarBig = i64> + ZnxSub + ZnxNegate + ZnxZero + ZnxCopy,
343 R: VecZnxBigToMut<BE>,
344 A: VecZnxBigToRef<BE>,
345 B: VecZnxBigToRef<BE>,
346{
347 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
348 let a: VecZnxBig<&[u8], BE> = a.to_ref();
349 let b: VecZnxBig<&[u8], BE> = b.to_ref();
350
351 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
352 data: res.data,
353 n: res.n,
354 cols: res.cols,
355 size: res.size,
356 max_size: res.max_size,
357 };
358
359 let a_vznx: VecZnx<&[u8]> = VecZnx {
360 data: a.data,
361 n: a.n,
362 cols: a.cols,
363 size: a.size,
364 max_size: a.max_size,
365 };
366
367 let b_vznx: VecZnx<&[u8]> = VecZnx {
368 data: b.data,
369 n: b.n,
370 cols: b.cols,
371 size: b.size,
372 max_size: b.max_size,
373 };
374
375 vec_znx_sub::<_, _, _, BE>(&mut res_vznx, res_col, &a_vznx, a_col, &b_vznx, b_col);
376}
377
378/// R <- A - B
379pub fn vec_znx_big_sub_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
380where
381 BE: Backend<ScalarBig = i64> + ZnxSubInplace,
382 R: VecZnxBigToMut<BE>,
383 A: VecZnxBigToRef<BE>,
384{
385 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
386 let a: VecZnxBig<&[u8], BE> = a.to_ref();
387
388 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
389 data: res.data,
390 n: res.n,
391 cols: res.cols,
392 size: res.size,
393 max_size: res.max_size,
394 };
395
396 let a_vznx: VecZnx<&[u8]> = VecZnx {
397 data: a.data,
398 n: a.n,
399 cols: a.cols,
400 size: a.size,
401 max_size: a.max_size,
402 };
403
404 vec_znx_sub_inplace::<_, _, BE>(&mut res_vznx, res_col, &a_vznx, a_col);
405}
406
407/// R <- B - A
408pub fn vec_znx_big_sub_negate_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
409where
410 BE: Backend<ScalarBig = i64> + ZnxSubNegateInplace + ZnxNegateInplace,
411 R: VecZnxBigToMut<BE>,
412 A: VecZnxBigToRef<BE>,
413{
414 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
415 let a: VecZnxBig<&[u8], BE> = a.to_ref();
416
417 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
418 data: res.data,
419 n: res.n,
420 cols: res.cols,
421 size: res.size,
422 max_size: res.max_size,
423 };
424
425 let a_vznx: VecZnx<&[u8]> = VecZnx {
426 data: a.data,
427 n: a.n,
428 cols: a.cols,
429 size: a.size,
430 max_size: a.max_size,
431 };
432
433 vec_znx_sub_negate_inplace::<_, _, BE>(&mut res_vznx, res_col, &a_vznx, a_col);
434}
435
436/// R <- A - B
437pub fn vec_znx_big_sub_small_a<R, A, B, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
438where
439 BE: Backend<ScalarBig = i64> + ZnxSub + ZnxNegate + ZnxZero + ZnxCopy,
440 R: VecZnxBigToMut<BE>,
441 A: VecZnxToRef,
442 B: VecZnxBigToRef<BE>,
443{
444 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
445 let b: VecZnxBig<&[u8], BE> = b.to_ref();
446
447 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
448 data: res.data,
449 n: res.n,
450 cols: res.cols,
451 size: res.size,
452 max_size: res.max_size,
453 };
454
455 let b_vznx: VecZnx<&[u8]> = VecZnx {
456 data: b.data,
457 n: b.n,
458 cols: b.cols,
459 size: b.size,
460 max_size: b.max_size,
461 };
462
463 vec_znx_sub::<_, _, _, BE>(&mut res_vznx, res_col, a, a_col, &b_vznx, b_col);
464}
465
466/// R <- A - B
467pub fn vec_znx_big_sub_small_b<R, A, B, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
468where
469 BE: Backend<ScalarBig = i64> + ZnxSub + ZnxNegate + ZnxZero + ZnxCopy,
470 R: VecZnxBigToMut<BE>,
471 A: VecZnxBigToRef<BE>,
472 B: VecZnxToRef,
473{
474 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
475 let a: VecZnxBig<&[u8], BE> = a.to_ref();
476
477 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
478 data: res.data,
479 n: res.n,
480 cols: res.cols,
481 size: res.size,
482 max_size: res.max_size,
483 };
484
485 let a_vznx: VecZnx<&[u8]> = VecZnx {
486 data: a.data,
487 n: a.n,
488 cols: a.cols,
489 size: a.size,
490 max_size: a.max_size,
491 };
492
493 vec_znx_sub::<_, _, _, BE>(&mut res_vznx, res_col, &a_vznx, a_col, b, b_col);
494}
495
496/// R <- R - A
497pub fn vec_znx_big_sub_small_a_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
498where
499 BE: Backend<ScalarBig = i64> + ZnxSubInplace,
500 R: VecZnxBigToMut<BE>,
501 A: VecZnxToRef,
502{
503 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
504
505 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
506 data: res.data,
507 n: res.n,
508 cols: res.cols,
509 size: res.size,
510 max_size: res.max_size,
511 };
512
513 vec_znx_sub_inplace::<_, _, BE>(&mut res_vznx, res_col, a, a_col);
514}
515
516/// R <- A - R
517pub fn vec_znx_big_sub_small_b_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
518where
519 BE: Backend<ScalarBig = i64> + ZnxSubNegateInplace + ZnxNegateInplace,
520 R: VecZnxBigToMut<BE>,
521 A: VecZnxToRef,
522{
523 let res: VecZnxBig<&mut [u8], BE> = res.to_mut();
524
525 let mut res_vznx: VecZnx<&mut [u8]> = VecZnx {
526 data: res.data,
527 n: res.n,
528 cols: res.cols,
529 size: res.size,
530 max_size: res.max_size,
531 };
532
533 vec_znx_sub_negate_inplace::<_, _, BE>(&mut res_vznx, res_col, a, a_col);
534}