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