phantom-zone/src/bool/parameters.rs
src/bool/parameters.rsRaw
1use num_traits::{ConstZero, FromPrimitive, PrimInt};
2
3use crate::{backend::Modulus, decomposer::Decomposer};
4
5trait DoubleDecomposerParams {
6 type Base;
7 type Count;
8
9 fn new(base: Self::Base, count_a: Self::Count, count_b: Self::Count) -> Self;
10 fn decomposition_base(&self) -> Self::Base;
11 fn decomposition_count_a(&self) -> Self::Count;
12 fn decomposition_count_b(&self) -> Self::Count;
13}
14
15trait SingleDecomposerParams {
16 type Base;
17 type Count;
18
19 fn new(base: Self::Base, count: Self::Count) -> Self;
20 fn decomposition_base(&self) -> Self::Base;
21 fn decomposition_count(&self) -> Self::Count;
22}
23
24impl DoubleDecomposerParams
25 for (
26 DecompostionLogBase,
27 (DecompositionCount, DecompositionCount),
28 )
29{
30 type Base = DecompostionLogBase;
31 type Count = DecompositionCount;
32
33 fn new(
34 base: DecompostionLogBase,
35 count_a: DecompositionCount,
36 count_b: DecompositionCount,
37 ) -> Self {
38 (base, (count_a, count_b))
39 }
40
41 fn decomposition_base(&self) -> Self::Base {
42 self.0
43 }
44
45 fn decomposition_count_a(&self) -> Self::Count {
46 self.1 .0
47 }
48
49 fn decomposition_count_b(&self) -> Self::Count {
50 self.1 .1
51 }
52}
53
54impl SingleDecomposerParams for (DecompostionLogBase, DecompositionCount) {
55 type Base = DecompostionLogBase;
56 type Count = DecompositionCount;
57
58 fn new(base: DecompostionLogBase, count: DecompositionCount) -> Self {
59 (base, count)
60 }
61
62 fn decomposition_base(&self) -> Self::Base {
63 self.0
64 }
65
66 fn decomposition_count(&self) -> Self::Count {
67 self.1
68 }
69}
70
71// impl DecomposerParams for (DecompostionLogBase, (DecompositionCount)) {
72// type Base = DecompostionLogBase;
73// type Count = DecompositionCount;
74
75// fn decomposition_base(&self) -> Self::Base {
76// self.0
77// }
78
79// fn decomposition_count(&self) -> Self::Count {
80// self.1
81// }
82// }
83
84#[derive(Clone, PartialEq, Debug)]
85pub(crate) enum ParameterVariant {
86 SingleParty,
87 MultiParty,
88 NonInteractiveMultiParty,
89}
90#[derive(Clone, PartialEq)]
91pub struct BoolParameters<El> {
92 rlwe_q: CiphertextModulus<El>,
93 lwe_q: CiphertextModulus<El>,
94 br_q: usize,
95 rlwe_n: PolynomialSize,
96 lwe_n: LweDimension,
97 lwe_decomposer_params: (DecompostionLogBase, DecompositionCount),
98 /// RLWE x RGSW decomposition count for (part A, part B)
99 rlrg_decomposer_params: (
100 DecompostionLogBase,
101 (DecompositionCount, DecompositionCount),
102 ),
103 /// RGSW x RGSW decomposition count for (part A, part B)
104 rgrg_decomposer_params: Option<(
105 DecompostionLogBase,
106 (DecompositionCount, DecompositionCount),
107 )>,
108 auto_decomposer_params: (DecompostionLogBase, DecompositionCount),
109 g: usize,
110 w: usize,
111 variant: ParameterVariant,
112}
113
114impl<El> BoolParameters<El> {
115 pub(crate) fn rlwe_q(&self) -> &CiphertextModulus<El> {
116 &self.rlwe_q
117 }
118
119 pub(crate) fn lwe_q(&self) -> &CiphertextModulus<El> {
120 &self.lwe_q
121 }
122
123 pub(crate) fn br_q(&self) -> &usize {
124 &self.br_q
125 }
126
127 pub(crate) fn rlwe_n(&self) -> &PolynomialSize {
128 &self.rlwe_n
129 }
130
131 pub(crate) fn lwe_n(&self) -> &LweDimension {
132 &self.lwe_n
133 }
134
135 pub(crate) fn g(&self) -> usize {
136 self.g
137 }
138
139 pub(crate) fn w(&self) -> usize {
140 self.w
141 }
142
143 pub(crate) fn rlwe_rgsw_decomposition_base(&self) -> DecompostionLogBase {
144 self.rlrg_decomposer_params.0
145 }
146
147 pub(crate) fn rlwe_rgsw_decomposition_count(&self) -> (DecompositionCount, DecompositionCount) {
148 self.rlrg_decomposer_params.1
149 }
150
151 pub(crate) fn rgsw_rgsw_decomposition_count(&self) -> (DecompositionCount, DecompositionCount) {
152 let params = self.rgrg_decomposer_params.expect(&format!(
153 "Parameter variant {:?} does not support RGSW x RGSW",
154 self.variant
155 ));
156 params.1
157 }
158
159 pub(crate) fn auto_decomposition_base(&self) -> DecompostionLogBase {
160 self.auto_decomposer_params.decomposition_base()
161 }
162
163 pub(crate) fn auto_decomposition_count(&self) -> DecompositionCount {
164 self.auto_decomposer_params.decomposition_count()
165 }
166
167 pub(crate) fn lwe_decomposition_base(&self) -> DecompostionLogBase {
168 self.lwe_decomposer_params.decomposition_base()
169 }
170
171 pub(crate) fn lwe_decomposition_count(&self) -> DecompositionCount {
172 self.lwe_decomposer_params.decomposition_count()
173 }
174
175 pub(crate) fn rgsw_rgsw_decomposer<D: Decomposer<Element = El>>(&self) -> (D, D)
176 where
177 El: Copy,
178 {
179 let params = self.rgrg_decomposer_params.expect(&format!(
180 "Parameter variant {:?} does not support RGSW x RGSW",
181 self.variant
182 ));
183 (
184 // A
185 D::new(
186 self.rlwe_q.0,
187 params.decomposition_base().0,
188 params.decomposition_count_a().0,
189 ),
190 // B
191 D::new(
192 self.rlwe_q.0,
193 params.decomposition_base().0,
194 params.decomposition_count_b().0,
195 ),
196 )
197 }
198
199 pub(crate) fn auto_decomposer<D: Decomposer<Element = El>>(&self) -> D
200 where
201 El: Copy,
202 {
203 D::new(
204 self.rlwe_q.0,
205 self.auto_decomposer_params.decomposition_base().0,
206 self.auto_decomposer_params.decomposition_count().0,
207 )
208 }
209
210 pub(crate) fn lwe_decomposer<D: Decomposer<Element = El>>(&self) -> D
211 where
212 El: Copy,
213 {
214 D::new(
215 self.lwe_q.0,
216 self.lwe_decomposer_params.decomposition_base().0,
217 self.lwe_decomposer_params.decomposition_count().0,
218 )
219 }
220
221 pub(crate) fn rlwe_rgsw_decomposer<D: Decomposer<Element = El>>(&self) -> (D, D)
222 where
223 El: Copy,
224 {
225 (
226 // A
227 D::new(
228 self.rlwe_q.0,
229 self.rlrg_decomposer_params.decomposition_base().0,
230 self.rlrg_decomposer_params.decomposition_count_a().0,
231 ),
232 // B
233 D::new(
234 self.rlwe_q.0,
235 self.rlrg_decomposer_params.decomposition_base().0,
236 self.rlrg_decomposer_params.decomposition_count_b().0,
237 ),
238 )
239 }
240
241 /// Returns dlogs of `g` for which auto keys are required as
242 /// per the parameter. Given that autos are required for [-g, g, g^2, ...,
243 /// g^w] function returns the following [0, 1, 2, ..., w] where `w` is
244 /// the window size. Note that although g^0 = 1, we use 0 for -g.
245 pub(crate) fn auto_element_dlogs(&self) -> Vec<usize> {
246 let mut els = vec![0];
247 (1..self.w + 1).into_iter().for_each(|e| {
248 els.push(e);
249 });
250 els
251 }
252}
253
254#[derive(Clone, Copy, PartialEq)]
255pub(crate) struct DecompostionLogBase(pub(crate) usize);
256impl AsRef<usize> for DecompostionLogBase {
257 fn as_ref(&self) -> &usize {
258 &self.0
259 }
260}
261#[derive(Clone, Copy, PartialEq)]
262pub(crate) struct DecompositionCount(pub(crate) usize);
263impl AsRef<usize> for DecompositionCount {
264 fn as_ref(&self) -> &usize {
265 &self.0
266 }
267}
268#[derive(Clone, Copy, PartialEq)]
269pub(crate) struct LweDimension(pub(crate) usize);
270#[derive(Clone, Copy, PartialEq)]
271pub(crate) struct PolynomialSize(pub(crate) usize);
272#[derive(Clone, Copy, PartialEq, Debug)]
273
274/// T equals modulus when modulus is non-native. Otherwise T equals 0. bool is
275/// true when modulus is native, false otherwise.
276pub struct CiphertextModulus<T>(T, bool);
277
278impl<T: ConstZero> CiphertextModulus<T> {
279 const fn new_native() -> Self {
280 // T::zero is stored only for convenience. It has no use when modulus
281 // is native. That is, either u128,u64,u32,u16
282 Self(T::ZERO, true)
283 }
284
285 const fn new_non_native(q: T) -> Self {
286 Self(q, false)
287 }
288}
289
290impl<T> CiphertextModulus<T>
291where
292 T: PrimInt,
293{
294 pub(crate) fn _bits() -> usize {
295 std::mem::size_of::<T>() as usize * 8
296 }
297
298 fn _native(&self) -> bool {
299 self.1
300 }
301
302 fn _half_q(&self) -> T {
303 if self._native() {
304 T::one() << (Self::_bits() - 1)
305 } else {
306 self.0 >> 1
307 }
308 }
309
310 fn _q(&self) -> Option<T> {
311 if self._native() {
312 None
313 } else {
314 Some(self.0)
315 }
316 }
317}
318
319impl<T> Modulus for CiphertextModulus<T>
320where
321 T: PrimInt + FromPrimitive,
322{
323 type Element = T;
324 fn is_native(&self) -> bool {
325 self._native()
326 }
327 fn largest_unsigned_value(&self) -> Self::Element {
328 if self._native() {
329 T::max_value()
330 } else {
331 self.0 - T::one()
332 }
333 }
334 fn neg_one(&self) -> Self::Element {
335 if self._native() {
336 T::max_value()
337 } else {
338 self.0 - T::one()
339 }
340 }
341 // fn signed_max(&self) -> Self::Element {}
342 // fn signed_min(&self) -> Self::Element {}
343 fn smallest_unsigned_value(&self) -> Self::Element {
344 T::zero()
345 }
346
347 fn map_element_to_i64(&self, v: &Self::Element) -> i64 {
348 if *v > self._half_q() {
349 -((self.largest_unsigned_value() - *v) + T::one())
350 .to_i64()
351 .unwrap()
352 } else {
353 v.to_i64().unwrap()
354 }
355 }
356
357 fn map_element_from_f64(&self, v: f64) -> Self::Element {
358 let v = v.round();
359 if v < 0.0 {
360 self.largest_unsigned_value() - T::from_f64(v.abs()).unwrap() + T::one()
361 } else {
362 T::from_f64(v.abs()).unwrap()
363 }
364 }
365
366 fn map_element_from_i64(&self, v: i64) -> Self::Element {
367 if v < 0 {
368 self.largest_unsigned_value() - T::from_i64(v.abs()).unwrap() + T::one()
369 } else {
370 T::from_i64(v.abs()).unwrap()
371 }
372 }
373
374 fn q(&self) -> Option<Self::Element> {
375 self._q()
376 }
377
378 fn q_as_f64(&self) -> Option<f64> {
379 if self._native() {
380 Some(T::max_value().to_f64().unwrap() + 1.0)
381 } else {
382 self.0.to_f64()
383 }
384 }
385}
386
387pub(crate) const SP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
388 rlwe_q: CiphertextModulus::new_non_native(268369921u64),
389 lwe_q: CiphertextModulus::new_non_native(1 << 16),
390 br_q: 1 << 10,
391 rlwe_n: PolynomialSize(1 << 10),
392 lwe_n: LweDimension(500),
393 lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(4)),
394 rlrg_decomposer_params: (
395 DecompostionLogBase(7),
396 (DecompositionCount(4), DecompositionCount(4)),
397 ),
398 rgrg_decomposer_params: None,
399 auto_decomposer_params: (DecompostionLogBase(7), DecompositionCount(4)),
400 g: 5,
401 w: 5,
402 variant: ParameterVariant::SingleParty,
403};
404
405pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
406 rlwe_q: CiphertextModulus::new_non_native(1152921504606830593),
407 lwe_q: CiphertextModulus::new_non_native(1 << 20),
408 br_q: 1 << 11,
409 rlwe_n: PolynomialSize(1 << 11),
410 lwe_n: LweDimension(500),
411 lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(5)),
412 rlrg_decomposer_params: (
413 DecompostionLogBase(12),
414 (DecompositionCount(5), DecompositionCount(5)),
415 ),
416 rgrg_decomposer_params: Some((
417 DecompostionLogBase(12),
418 (DecompositionCount(5), DecompositionCount(5)),
419 )),
420 auto_decomposer_params: (DecompostionLogBase(12), DecompositionCount(5)),
421 g: 5,
422 w: 10,
423 variant: ParameterVariant::MultiParty,
424};
425
426pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
427 rlwe_q: CiphertextModulus::new_non_native(36028797018820609),
428 lwe_q: CiphertextModulus::new_non_native(1 << 20),
429 br_q: 1 << 11,
430 rlwe_n: PolynomialSize(1 << 11),
431 lwe_n: LweDimension(600),
432 lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(5)),
433 rlrg_decomposer_params: (
434 DecompostionLogBase(11),
435 (DecompositionCount(2), DecompositionCount(1)),
436 ),
437 rgrg_decomposer_params: Some((
438 DecompostionLogBase(11),
439 (DecompositionCount(5), DecompositionCount(4)),
440 )),
441 auto_decomposer_params: (DecompostionLogBase(11), DecompositionCount(2)),
442 g: 5,
443 w: 10,
444 variant: ParameterVariant::MultiParty,
445};
446
447#[cfg(test)]
448mod tests {
449 use crate::utils::generate_prime;
450
451 #[test]
452 fn find_prime() {
453 let bits = 55;
454 let ring_size = 1 << 15;
455 let prime = generate_prime(bits, ring_size * 2, 1 << bits).unwrap();
456 dbg!(prime);
457 }
458}