phantom-zone/src/bool/parameters.rs
src/bool/parameters.rsRaw
1use num_traits::{ConstZero, FromPrimitive, PrimInt, ToPrimitive, Zero};
2
3use crate::{backend::Modulus, decomposer::Decomposer};
4
5#[derive(Clone, PartialEq)]
6pub(super) 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
150#[derive(Clone, Copy, PartialEq)]
151pub(crate) struct DecompostionLogBase(pub(crate) usize);
152impl AsRef<usize> for DecompostionLogBase {
153 fn as_ref(&self) -> &usize {
154 &self.0
155 }
156}
157#[derive(Clone, Copy, PartialEq)]
158pub(crate) struct DecompositionCount(pub(crate) usize);
159impl AsRef<usize> for DecompositionCount {
160 fn as_ref(&self) -> &usize {
161 &self.0
162 }
163}
164#[derive(Clone, Copy, PartialEq)]
165pub(crate) struct LweDimension(pub(crate) usize);
166#[derive(Clone, Copy, PartialEq)]
167pub(crate) struct PolynomialSize(pub(crate) usize);
168#[derive(Clone, Copy, PartialEq)]
169
170/// T eqauls modulus when modulus is non-native. Otherwise T equals 0. bool is
171/// true when modulus is native, false otherwise.
172pub(crate) struct CiphertextModulus<T>(T, bool);
173
174impl<T: ConstZero> CiphertextModulus<T> {
175 const fn new_native() -> Self {
176 // T::zero is stored only for convenience. It has no use when modulus
177 // is native. That is, either u128,u64,u32,u16
178 Self(T::ZERO, true)
179 }
180
181 const fn new_non_native(q: T) -> Self {
182 Self(q, false)
183 }
184}
185
186impl<T> CiphertextModulus<T>
187where
188 T: PrimInt,
189{
190 pub(crate) fn _bits() -> usize {
191 std::mem::size_of::<T>() as usize * 8
192 }
193
194 fn _native(&self) -> bool {
195 self.1
196 }
197
198 fn _half_q(&self) -> T {
199 if self._native() {
200 T::one() << (Self::_bits() - 1)
201 } else {
202 self.0 >> 1
203 }
204 }
205
206 fn _q(&self) -> Option<T> {
207 if self._native() {
208 None
209 } else {
210 Some(self.0)
211 }
212 }
213}
214
215impl<T> Modulus for CiphertextModulus<T>
216where
217 T: PrimInt + FromPrimitive,
218{
219 type Element = T;
220 fn is_native(&self) -> bool {
221 self._native()
222 }
223 fn largest_unsigned_value(&self) -> Self::Element {
224 if self._native() {
225 T::max_value()
226 } else {
227 self.0 - T::one()
228 }
229 }
230 fn neg_one(&self) -> Self::Element {
231 if self._native() {
232 T::max_value()
233 } else {
234 self.0 - T::one()
235 }
236 }
237 // fn signed_max(&self) -> Self::Element {}
238 // fn signed_min(&self) -> Self::Element {}
239 fn smallest_unsigned_value(&self) -> Self::Element {
240 T::zero()
241 }
242
243 fn map_element_to_i64(&self, v: &Self::Element) -> i64 {
244 if *v > self._half_q() {
245 -((self.largest_unsigned_value() - *v) + T::one())
246 .to_i64()
247 .unwrap()
248 } else {
249 v.to_i64().unwrap()
250 }
251 }
252
253 fn map_element_from_f64(&self, v: f64) -> Self::Element {
254 let v = v.round();
255 if v < 0.0 {
256 self.largest_unsigned_value() - T::from_f64(v.abs()).unwrap() + T::one()
257 } else {
258 T::from_f64(v.abs()).unwrap()
259 }
260 }
261
262 fn map_element_from_i64(&self, v: i64) -> Self::Element {
263 if v < 0 {
264 self.largest_unsigned_value() - T::from_i64(v.abs()).unwrap() + T::one()
265 } else {
266 T::from_i64(v.abs()).unwrap()
267 }
268 }
269
270 fn q(&self) -> Option<Self::Element> {
271 self._q()
272 }
273
274 fn q_as_f64(&self) -> Option<f64> {
275 if self._native() {
276 Some(T::max_value().to_f64().unwrap() + 1.0)
277 } else {
278 self.0.to_f64()
279 }
280 }
281}
282
283pub(super) const SP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
284 rlwe_q: CiphertextModulus::new_non_native(268369921u64),
285 lwe_q: CiphertextModulus::new_non_native(1 << 16),
286 br_q: 1 << 10,
287 rlwe_n: PolynomialSize(1 << 10),
288 lwe_n: LweDimension(493),
289 lwe_decomposer_base: DecompostionLogBase(4),
290 lwe_decomposer_count: DecompositionCount(4),
291 rlrg_decomposer_base: DecompostionLogBase(7),
292 rlrg_decomposer_count: (DecompositionCount(4), DecompositionCount(4)),
293 rgrg_decomposer_base: DecompostionLogBase(7),
294 rgrg_decomposer_count: (DecompositionCount(4), DecompositionCount(4)),
295 auto_decomposer_base: DecompostionLogBase(7),
296 auto_decomposer_count: DecompositionCount(4),
297 g: 5,
298 w: 1,
299};
300
301pub(super) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
302 rlwe_q: CiphertextModulus::new_non_native(1152921504606830593),
303 lwe_q: CiphertextModulus::new_non_native(1 << 20),
304 br_q: 1 << 10,
305 rlwe_n: PolynomialSize(1 << 11),
306 lwe_n: LweDimension(500),
307 lwe_decomposer_base: DecompostionLogBase(4),
308 lwe_decomposer_count: DecompositionCount(5),
309 rlrg_decomposer_base: DecompostionLogBase(12),
310 rlrg_decomposer_count: (DecompositionCount(5), DecompositionCount(5)),
311 rgrg_decomposer_base: DecompostionLogBase(12),
312 rgrg_decomposer_count: (DecompositionCount(5), DecompositionCount(5)),
313 auto_decomposer_base: DecompostionLogBase(12),
314 auto_decomposer_count: DecompositionCount(5),
315 g: 5,
316 w: 1,
317};
318
319#[cfg(test)]
320mod tests {
321 use crate::utils::generate_prime;
322
323 #[test]
324 fn find_prime() {
325 let bits = 61;
326 let ring_size = 1 << 11;
327 let prime = generate_prime(bits, ring_size * 2, 1 << bits).unwrap();
328 dbg!(prime);
329 }
330}