arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
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 << 11;
357        let prime = generate_prime(bits, ring_size * 2, 1 << bits).unwrap();
358        dbg!(prime);
359    }
360}