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