phantom-zone/src/bool/parameters.rs
src/bool/parameters.rsRaw
1use num_traits::{ConstZero, FromPrimitive, PrimInt};
2
3use crate::{
4 backend::Modulus,
5 decomposer::{Decomposer, NumInfo},
6 utils::log2,
7};
8
9pub(crate) trait DoubleDecomposerCount {
10 type Count;
11 fn a(&self) -> Self::Count;
12 fn b(&self) -> Self::Count;
13}
14
15pub(crate) trait DoubleDecomposerParams {
16 type Base;
17 type Count;
18
19 fn decomposition_base(&self) -> Self::Base;
20 fn decomposition_count_a(&self) -> Self::Count;
21 fn decomposition_count_b(&self) -> Self::Count;
22}
23
24pub(crate) trait SingleDecomposerParams {
25 type Base;
26 type Count;
27
28 // fn new(base: Self::Base, count: Self::Count) -> Self;
29 fn decomposition_base(&self) -> Self::Base;
30 fn decomposition_count(&self) -> Self::Count;
31}
32
33impl DoubleDecomposerParams
34 for (
35 DecompostionLogBase,
36 // Assume (Decomposition count for A, Decomposition count for B)
37 (DecompositionCount, DecompositionCount),
38 )
39{
40 type Base = DecompostionLogBase;
41 type Count = DecompositionCount;
42
43 // fn new(
44 // base: DecompostionLogBase,
45 // count_a: DecompositionCount,
46 // count_b: DecompositionCount,
47 // ) -> Self {
48 // (base, (count_a, count_b))
49 // }
50
51 fn decomposition_base(&self) -> Self::Base {
52 self.0
53 }
54
55 fn decomposition_count_a(&self) -> Self::Count {
56 self.1 .0
57 }
58
59 fn decomposition_count_b(&self) -> Self::Count {
60 self.1 .1
61 }
62}
63
64impl SingleDecomposerParams for (DecompostionLogBase, DecompositionCount) {
65 type Base = DecompostionLogBase;
66 type Count = DecompositionCount;
67
68 // fn new(base: DecompostionLogBase, count: DecompositionCount) -> Self {
69 // (base, count)
70 // }
71
72 fn decomposition_base(&self) -> Self::Base {
73 self.0
74 }
75
76 fn decomposition_count(&self) -> Self::Count {
77 self.1
78 }
79}
80
81#[derive(Clone, PartialEq, Debug)]
82pub(crate) enum SecretKeyDistribution {
83 /// Elements of secret key are sample from Gaussian distribitution with
84 /// \sigma = 3.19 and \mu = 0.0
85 ErrorDistribution,
86 /// Elements of secret key are chosen from the set {1,0,-1} with hamming
87 /// weight `floor(N/2)` where `N` is the secret dimension.
88 TernaryDistribution,
89}
90
91#[derive(Clone, PartialEq, Debug)]
92pub(crate) enum ParameterVariant {
93 SingleParty,
94 MultiParty,
95 NonInteractiveMultiParty,
96}
97#[derive(Clone, PartialEq)]
98pub struct BoolParameters<El> {
99 /// RLWE secret key distribution
100 rlwe_secret_key_dist: SecretKeyDistribution,
101 /// LWE secret key distribtuion
102 lwe_secret_key_dist: SecretKeyDistribution,
103 /// RLWE ciphertext modulus Q
104 rlwe_q: CiphertextModulus<El>,
105 /// LWE ciphertext modulus q (usually referred to as Q_{ks})
106 lwe_q: CiphertextModulus<El>,
107 /// Blind rotation modulus. It is the modulus to which we switch before
108 /// blind rotation.
109 ///
110 /// Since blind rotation decrypts LWE ciphertext in the exponent of a ring
111 /// polynomial, which is a ring mod 2N, blind rotation modulus is
112 /// always <= 2N.
113 br_q: usize,
114 /// Ring dimension `N` for 2N^{th} cyclotomic polynomial ring
115 rlwe_n: PolynomialSize,
116 /// LWE dimension `n`
117 lwe_n: LweDimension,
118 /// LWE key switch decompositon params
119 lwe_decomposer_params: (DecompostionLogBase, DecompositionCount),
120 /// Decompostion parameters for RLWE x RGSW.
121 ///
122 /// We restrict decomposition for RLWE'(-sm) and RLWE'(m) to have same base
123 /// but can have different decomposition count. We refer to this
124 /// DoubleDecomposer / RlweDecomposer
125 ///
126 /// Decomposition count `d_a` (i.e. for SignedDecompose(RLWE_A(m)) x
127 /// RLWE'(-sm)) and `d_b` (i.e. for SignedDecompose(RLWE_B(m)) x RLWE'(m))
128 /// are always stored as `(d_a, d_b)`
129 rlrg_decomposer_params: (
130 DecompostionLogBase,
131 (DecompositionCount, DecompositionCount),
132 ),
133 /// Decomposition parameters for RLWE automorphism
134 auto_decomposer_params: (DecompostionLogBase, DecompositionCount),
135 /// Decomposition parameters for RGSW0 x RGSW1
136 ///
137 /// `0` and `1` indicate that RGSW0 and RGSW1 may not use same decomposition
138 /// parameters.
139 ///
140 /// In RGSW0 x RGSW1, decomposition parameters for RGSW1 are required.
141 /// Hence, the parameters we store are decomposition parameters of RGSW1.
142 ///
143 /// Like RLWE x RGSW decomposition parameters (1) we restrict to same base
144 /// but can have different decomposition counts `d_a` and `d_b` and (2)
145 /// decomposition count `d_a` and `d_b` are always stored as `(d_a, d_b)`
146 ///
147 /// RGSW0 x RGSW1 are optional because they only necessary to be supplied in
148 /// multi-party setting.
149 rgrg_decomposer_params: Option<(
150 DecompostionLogBase,
151 (DecompositionCount, DecompositionCount),
152 )>,
153 /// Decomposition parameters for non-interactive key switching from u_j to
154 /// s, hwere u_j is RLWE secret `u` of party `j` and `s` is the ideal RLWE
155 /// secret key.
156 ///
157 /// Decomposition parameters for non-interactive key switching are optional
158 /// and must be supplied only for non-interactive multi-party
159 non_interactive_ui_to_s_key_switch_decomposer:
160 Option<(DecompostionLogBase, DecompositionCount)>,
161 /// Group generator for Z^*_{br_q}
162 g: usize,
163 /// Window size parameter for LMKC++ blind rotation
164 w: usize,
165 /// Parameter variant
166 variant: ParameterVariant,
167}
168
169impl<El> BoolParameters<El> {
170 pub(crate) fn rlwe_secret_key_dist(&self) -> &SecretKeyDistribution {
171 &self.rlwe_secret_key_dist
172 }
173
174 pub(crate) fn lwe_secret_key_dist(&self) -> &SecretKeyDistribution {
175 &self.lwe_secret_key_dist
176 }
177
178 pub(crate) fn rlwe_q(&self) -> &CiphertextModulus<El> {
179 &self.rlwe_q
180 }
181
182 pub(crate) fn lwe_q(&self) -> &CiphertextModulus<El> {
183 &self.lwe_q
184 }
185
186 pub(crate) fn br_q(&self) -> &usize {
187 &self.br_q
188 }
189
190 pub(crate) fn rlwe_n(&self) -> &PolynomialSize {
191 &self.rlwe_n
192 }
193
194 pub(crate) fn lwe_n(&self) -> &LweDimension {
195 &self.lwe_n
196 }
197
198 pub(crate) fn g(&self) -> usize {
199 self.g
200 }
201
202 pub(crate) fn w(&self) -> usize {
203 self.w
204 }
205
206 pub(crate) fn rlwe_by_rgsw_decomposition_params(
207 &self,
208 ) -> &(
209 DecompostionLogBase,
210 (DecompositionCount, DecompositionCount),
211 ) {
212 &self.rlrg_decomposer_params
213 }
214
215 pub(crate) fn rgsw_by_rgsw_decomposition_params(
216 &self,
217 ) -> (
218 DecompostionLogBase,
219 (DecompositionCount, DecompositionCount),
220 ) {
221 self.rgrg_decomposer_params.expect(&format!(
222 "Parameter variant {:?} does not support RGSWxRGSW",
223 self.variant
224 ))
225 }
226
227 pub(crate) fn rlwe_rgsw_decomposition_base(&self) -> DecompostionLogBase {
228 self.rlrg_decomposer_params.0
229 }
230
231 pub(crate) fn rlwe_rgsw_decomposition_count(&self) -> (DecompositionCount, DecompositionCount) {
232 self.rlrg_decomposer_params.1
233 }
234
235 pub(crate) fn rgsw_rgsw_decomposition_count(&self) -> (DecompositionCount, DecompositionCount) {
236 let params = self.rgrg_decomposer_params.expect(&format!(
237 "Parameter variant {:?} does not support RGSW x RGSW",
238 self.variant
239 ));
240 params.1
241 }
242
243 pub(crate) fn auto_decomposition_param(&self) -> &(DecompostionLogBase, DecompositionCount) {
244 &self.auto_decomposer_params
245 }
246
247 pub(crate) fn auto_decomposition_base(&self) -> DecompostionLogBase {
248 self.auto_decomposer_params.decomposition_base()
249 }
250
251 pub(crate) fn auto_decomposition_count(&self) -> DecompositionCount {
252 self.auto_decomposer_params.decomposition_count()
253 }
254
255 pub(crate) fn lwe_decomposition_base(&self) -> DecompostionLogBase {
256 self.lwe_decomposer_params.decomposition_base()
257 }
258
259 pub(crate) fn lwe_decomposition_count(&self) -> DecompositionCount {
260 self.lwe_decomposer_params.decomposition_count()
261 }
262
263 pub(crate) fn non_interactive_ui_to_s_key_switch_decomposition_count(
264 &self,
265 ) -> DecompositionCount {
266 let params = self
267 .non_interactive_ui_to_s_key_switch_decomposer
268 .expect(&format!(
269 "Parameter variant {:?} does not support non-interactive",
270 self.variant
271 ));
272 params.decomposition_count()
273 }
274
275 pub(crate) fn rgsw_rgsw_decomposer<D: Decomposer<Element = El>>(&self) -> (D, D)
276 where
277 El: Copy,
278 {
279 let params = self.rgrg_decomposer_params.expect(&format!(
280 "Parameter variant {:?} does not support RGSW x RGSW",
281 self.variant
282 ));
283 (
284 // A
285 D::new(
286 self.rlwe_q.0,
287 params.decomposition_base().0,
288 params.decomposition_count_a().0,
289 ),
290 // B
291 D::new(
292 self.rlwe_q.0,
293 params.decomposition_base().0,
294 params.decomposition_count_b().0,
295 ),
296 )
297 }
298
299 pub(crate) fn auto_decomposer<D: Decomposer<Element = El>>(&self) -> D
300 where
301 El: Copy,
302 {
303 D::new(
304 self.rlwe_q.0,
305 self.auto_decomposer_params.decomposition_base().0,
306 self.auto_decomposer_params.decomposition_count().0,
307 )
308 }
309
310 pub(crate) fn lwe_decomposer<D: Decomposer<Element = El>>(&self) -> D
311 where
312 El: Copy,
313 {
314 D::new(
315 self.lwe_q.0,
316 self.lwe_decomposer_params.decomposition_base().0,
317 self.lwe_decomposer_params.decomposition_count().0,
318 )
319 }
320
321 pub(crate) fn rlwe_rgsw_decomposer<D: Decomposer<Element = El>>(&self) -> (D, D)
322 where
323 El: Copy,
324 {
325 (
326 // A
327 D::new(
328 self.rlwe_q.0,
329 self.rlrg_decomposer_params.decomposition_base().0,
330 self.rlrg_decomposer_params.decomposition_count_a().0,
331 ),
332 // B
333 D::new(
334 self.rlwe_q.0,
335 self.rlrg_decomposer_params.decomposition_base().0,
336 self.rlrg_decomposer_params.decomposition_count_b().0,
337 ),
338 )
339 }
340
341 pub(crate) fn non_interactive_ui_to_s_key_switch_decomposer<D: Decomposer<Element = El>>(
342 &self,
343 ) -> D
344 where
345 El: Copy,
346 {
347 let params = self
348 .non_interactive_ui_to_s_key_switch_decomposer
349 .expect(&format!(
350 "Parameter variant {:?} does not support non-interactive",
351 self.variant
352 ));
353 D::new(
354 self.rlwe_q.0,
355 params.decomposition_base().0,
356 params.decomposition_count().0,
357 )
358 }
359
360 /// Returns dlogs of `g` for which auto keys are required as
361 /// per the parameter. Given that autos are required for [-g, g, g^2, ...,
362 /// g^w] function returns the following [0, 1, 2, ..., w] where `w` is
363 /// the window size. Note that although g^0 = 1, we use 0 for -g.
364 pub(crate) fn auto_element_dlogs(&self) -> Vec<usize> {
365 let mut els = vec![0];
366 (1..self.w + 1).into_iter().for_each(|e| {
367 els.push(e);
368 });
369 els
370 }
371
372 pub(crate) fn variant(&self) -> &ParameterVariant {
373 &self.variant
374 }
375}
376
377#[derive(Clone, Copy, PartialEq)]
378pub struct DecompostionLogBase(pub(crate) usize);
379impl AsRef<usize> for DecompostionLogBase {
380 fn as_ref(&self) -> &usize {
381 &self.0
382 }
383}
384#[derive(Clone, Copy, PartialEq)]
385pub struct DecompositionCount(pub(crate) usize);
386impl AsRef<usize> for DecompositionCount {
387 fn as_ref(&self) -> &usize {
388 &self.0
389 }
390}
391
392#[derive(Clone, Copy, PartialEq)]
393pub(crate) struct LweDimension(pub(crate) usize);
394#[derive(Clone, Copy, PartialEq)]
395pub(crate) struct PolynomialSize(pub(crate) usize);
396#[derive(Clone, Copy, PartialEq, Debug)]
397
398/// T equals modulus when modulus is non-native. Otherwise T equals 0. bool is
399/// true when modulus is native, false otherwise.
400pub struct CiphertextModulus<T>(T, bool);
401
402impl<T: ConstZero> CiphertextModulus<T> {
403 const fn new_native() -> Self {
404 // T::zero is stored only for convenience. It has no use when modulus
405 // is native. That is, either u128,u64,u32,u16
406 Self(T::ZERO, true)
407 }
408
409 const fn new_non_native(q: T) -> Self {
410 Self(q, false)
411 }
412}
413
414impl<T> CiphertextModulus<T>
415where
416 T: PrimInt + NumInfo,
417{
418 fn _bits() -> usize {
419 T::BITS as usize
420 }
421
422 fn _native(&self) -> bool {
423 self.1
424 }
425
426 fn _half_q(&self) -> T {
427 if self._native() {
428 T::one() << (Self::_bits() - 1)
429 } else {
430 self.0 >> 1
431 }
432 }
433
434 fn _q(&self) -> Option<T> {
435 if self._native() {
436 None
437 } else {
438 Some(self.0)
439 }
440 }
441}
442
443impl<T> Modulus for CiphertextModulus<T>
444where
445 T: PrimInt + FromPrimitive + NumInfo,
446{
447 type Element = T;
448 fn is_native(&self) -> bool {
449 self._native()
450 }
451 fn largest_unsigned_value(&self) -> Self::Element {
452 if self._native() {
453 T::max_value()
454 } else {
455 self.0 - T::one()
456 }
457 }
458 fn neg_one(&self) -> Self::Element {
459 if self._native() {
460 T::max_value()
461 } else {
462 self.0 - T::one()
463 }
464 }
465 // fn signed_max(&self) -> Self::Element {}
466 // fn signed_min(&self) -> Self::Element {}
467 fn smallest_unsigned_value(&self) -> Self::Element {
468 T::zero()
469 }
470
471 fn map_element_to_i64(&self, v: &Self::Element) -> i64 {
472 assert!(*v <= self.largest_unsigned_value());
473 if *v > self._half_q() {
474 -((self.largest_unsigned_value() - *v) + T::one())
475 .to_i64()
476 .unwrap()
477 } else {
478 v.to_i64().unwrap()
479 }
480 }
481
482 fn map_element_from_f64(&self, v: f64) -> Self::Element {
483 let v = v.round();
484
485 let v_el = T::from_f64(v.abs()).unwrap();
486 assert!(v_el <= self.largest_unsigned_value());
487
488 if v < 0.0 {
489 self.largest_unsigned_value() - v_el + T::one()
490 } else {
491 v_el
492 }
493 }
494
495 fn map_element_from_i64(&self, v: i64) -> Self::Element {
496 let v_el = T::from_i64(v.abs()).unwrap();
497 assert!(v_el <= self.largest_unsigned_value());
498 if v < 0 {
499 self.largest_unsigned_value() - v_el + T::one()
500 } else {
501 v_el
502 }
503 }
504
505 fn q(&self) -> Option<Self::Element> {
506 self._q()
507 }
508
509 fn q_as_f64(&self) -> Option<f64> {
510 if self._native() {
511 Some(T::max_value().to_f64().unwrap() + 1.0)
512 } else {
513 self.0.to_f64()
514 }
515 }
516
517 fn log_q(&self) -> usize {
518 if self.is_native() {
519 Self::_bits()
520 } else {
521 log2(&self.q().unwrap())
522 }
523 }
524}
525
526pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
527 rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
528 lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
529 rlwe_q: CiphertextModulus::new_non_native(1152921504606830593),
530 lwe_q: CiphertextModulus::new_non_native(1 << 20),
531 br_q: 1 << 11,
532 rlwe_n: PolynomialSize(1 << 11),
533 lwe_n: LweDimension(500),
534 lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(5)),
535 rlrg_decomposer_params: (
536 DecompostionLogBase(12),
537 (DecompositionCount(5), DecompositionCount(5)),
538 ),
539 rgrg_decomposer_params: Some((
540 DecompostionLogBase(12),
541 (DecompositionCount(5), DecompositionCount(5)),
542 )),
543 auto_decomposer_params: (DecompostionLogBase(12), DecompositionCount(5)),
544 non_interactive_ui_to_s_key_switch_decomposer: None,
545 g: 5,
546 w: 10,
547 variant: ParameterVariant::MultiParty,
548};
549
550pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
551 rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
552 lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
553 rlwe_q: CiphertextModulus::new_non_native(36028797018820609),
554 lwe_q: CiphertextModulus::new_non_native(1 << 20),
555 br_q: 1 << 11,
556 rlwe_n: PolynomialSize(1 << 11),
557 lwe_n: LweDimension(600),
558 lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(5)),
559 rlrg_decomposer_params: (
560 DecompostionLogBase(11),
561 (DecompositionCount(2), DecompositionCount(1)),
562 ),
563 rgrg_decomposer_params: Some((
564 DecompostionLogBase(11),
565 (DecompositionCount(5), DecompositionCount(4)),
566 )),
567 auto_decomposer_params: (DecompostionLogBase(11), DecompositionCount(2)),
568 non_interactive_ui_to_s_key_switch_decomposer: None,
569 g: 5,
570 w: 10,
571 variant: ParameterVariant::MultiParty,
572};
573
574pub(crate) const I_2P: BoolParameters<u64> = BoolParameters::<u64> {
575 rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
576 lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
577 rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
578 lwe_q: CiphertextModulus::new_non_native(1 << 15),
579 br_q: 1 << 11,
580 rlwe_n: PolynomialSize(1 << 11),
581 lwe_n: LweDimension(480),
582 lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(11)),
583 rlrg_decomposer_params: (
584 DecompostionLogBase(16),
585 (DecompositionCount(1), DecompositionCount(1)),
586 ),
587 rgrg_decomposer_params: Some((
588 DecompostionLogBase(8),
589 (DecompositionCount(6), DecompositionCount(6)),
590 )),
591 auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
592 non_interactive_ui_to_s_key_switch_decomposer: None,
593 g: 5,
594 w: 10,
595 variant: ParameterVariant::MultiParty,
596};
597
598pub(crate) const NI_2P: BoolParameters<u64> = BoolParameters::<u64> {
599 rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
600 lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
601 rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
602 lwe_q: CiphertextModulus::new_non_native(1 << 15),
603 br_q: 1 << 11,
604 rlwe_n: PolynomialSize(1 << 11),
605 lwe_n: LweDimension(480),
606 lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(12)),
607 rlrg_decomposer_params: (
608 DecompostionLogBase(16),
609 (DecompositionCount(1), DecompositionCount(1)),
610 ),
611 rgrg_decomposer_params: Some((
612 DecompostionLogBase(6),
613 (DecompositionCount(7), DecompositionCount(7)),
614 )),
615 auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
616 non_interactive_ui_to_s_key_switch_decomposer: Some((
617 DecompostionLogBase(1),
618 DecompositionCount(50),
619 )),
620 g: 5,
621 w: 10,
622 variant: ParameterVariant::NonInteractiveMultiParty,
623};
624
625pub(crate) const NI_4P: BoolParameters<u64> = BoolParameters::<u64> {
626 rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
627 lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
628 rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
629 lwe_q: CiphertextModulus::new_non_native(1 << 16),
630 br_q: 1 << 11,
631 rlwe_n: PolynomialSize(1 << 11),
632 lwe_n: LweDimension(510),
633 lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(12)),
634 rlrg_decomposer_params: (
635 DecompostionLogBase(17),
636 (DecompositionCount(1), DecompositionCount(1)),
637 ),
638 rgrg_decomposer_params: Some((
639 DecompostionLogBase(4),
640 (DecompositionCount(10), DecompositionCount(9)),
641 )),
642 auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
643 non_interactive_ui_to_s_key_switch_decomposer: Some((
644 DecompostionLogBase(1),
645 DecompositionCount(50),
646 )),
647 g: 5,
648 w: 10,
649 variant: ParameterVariant::NonInteractiveMultiParty,
650};
651
652#[cfg(test)]
653pub(crate) const SP_TEST_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
654 rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
655 lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
656 rlwe_q: CiphertextModulus::new_non_native(268369921u64),
657 lwe_q: CiphertextModulus::new_non_native(1 << 16),
658 br_q: 1 << 9,
659 rlwe_n: PolynomialSize(1 << 9),
660 lwe_n: LweDimension(100),
661 lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(4)),
662 rlrg_decomposer_params: (
663 DecompostionLogBase(7),
664 (DecompositionCount(4), DecompositionCount(4)),
665 ),
666 rgrg_decomposer_params: None,
667 auto_decomposer_params: (DecompostionLogBase(7), DecompositionCount(4)),
668 non_interactive_ui_to_s_key_switch_decomposer: None,
669 g: 5,
670 w: 5,
671 variant: ParameterVariant::SingleParty,
672};
673
674#[cfg(test)]
675mod tests {
676
677 impl BoolParameters<u64> {
678 pub(crate) fn default_rlwe_modop(&self) -> ModularOpsU64<CiphertextModulus<u64>> {
679 ModularOpsU64::new(self.rlwe_q)
680 }
681 pub(crate) fn default_rlwe_nttop(&self) -> NttBackendU64 {
682 NttBackendU64::new(&self.rlwe_q, self.rlwe_n.0)
683 }
684 }
685
686 use crate::{utils::generate_prime, ModInit, ModularOpsU64, Ntt, NttBackendU64, NttInit};
687
688 use super::{BoolParameters, CiphertextModulus};
689
690 #[test]
691 fn find_prime() {
692 let bits = 60;
693 let ring_size = 1 << 11;
694 let prime = generate_prime(bits, ring_size * 2, 1 << bits).unwrap();
695 dbg!(prime);
696 }
697}