arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
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 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 equals 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(crate) 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 << 8,
287    rlwe_n: PolynomialSize(1 << 8),
288    lwe_n: LweDimension(10),
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 << 11,
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(2), DecompositionCount(2)),
311    rgrg_decomposer_base: DecompostionLogBase(12),
312    rgrg_decomposer_count: (DecompositionCount(5), DecompositionCount(4)),
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}