Skip to main content

primitives/algebra/field/mersenne/
m107.rs

1use std::{
2    iter::{Product, Sum},
3    ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
4};
5
6use crypto_bigint::rand_core::RngCore;
7use ff::{Field, PrimeField};
8use hybrid_array::Array;
9use rand::Rng;
10use serde::{Deserialize, Serialize};
11use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
12use typenum::{U1, U14, U16};
13use wincode::{SchemaRead, SchemaWrite};
14
15use crate::{
16    algebra::{
17        field::{
18            exponentiation::{pow2_minus_1, pow2_pow},
19            FieldExtension,
20        },
21        ops::{AccReduce, ReduceWide},
22        uniform_bytes::FromUniformBytes,
23    },
24    random::{CryptoRngCore, Random},
25    types::{HeapArray, Positive},
26};
27
28mod ff_impl {
29    use ff::PrimeField;
30    use serde::{Deserialize, Serialize};
31
32    #[derive(PrimeField, Serialize, Deserialize)]
33    #[PrimeFieldModulus = "162259276829213363391578010288127"]
34    #[PrimeFieldGenerator = "3"]
35    #[PrimeFieldReprEndianness = "little"]
36    pub struct Mersenne107FF([u64; 2]);
37}
38
39#[derive(
40    Copy, Clone, Default, Debug, SchemaRead, SchemaWrite, PartialEq, Eq, Hash, Ord, PartialOrd,
41)]
42#[repr(C)]
43pub struct Mersenne107(pub(super) u128);
44
45impl Serialize for Mersenne107 {
46    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47    where
48        S: serde::Serializer,
49    {
50        self.as_le_array().serialize(serializer)
51    }
52}
53
54impl<'de> Deserialize<'de> for Mersenne107 {
55    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
56    where
57        D: serde::Deserializer<'de>,
58    {
59        let arr = <[u8; 14]>::deserialize(deserializer)?;
60        Self::from_canonical_bytes(&arr).ok_or_else(|| {
61            serde::de::Error::custom("Invalid Mersenne107 canonical byte representation")
62        })
63    }
64}
65
66impl Mersenne107 {
67    pub const NUM_BITS: usize = 107;
68    pub const MODULUS: u128 = (1u128 << Self::NUM_BITS) - 1;
69    pub const MAX: u128 = Self::MODULUS - 1;
70
71    fn as_le_array(&self) -> [u8; 14] {
72        let mut arr = [0u8; 14];
73        arr[..14].copy_from_slice(&self.0.to_le_bytes()[..14]);
74        arr
75    }
76
77    fn from_canonical_bytes(arr: &[u8; 14]) -> Option<Self> {
78        let mut tmp = [0u8; 16];
79        tmp[..14].copy_from_slice(arr);
80        let val = u128::from_le_bytes(tmp);
81        (val < Self::MODULUS).then_some(Self(val))
82    }
83}
84
85///////////////////////////////////////////////////////////////////////////////////////////////////
86// Arithmetic ops - multiplication
87///////////////////////////////////////////////////////////////////////////////////////////////////
88
89#[macros::op_variants(owned)]
90impl<'a> MulAssign<&'a Mersenne107> for Mersenne107 {
91    #[inline]
92    fn mul_assign(&mut self, rhs: &'a Mersenne107) {
93        self.0 = super::m107_ops::mul(self.0, rhs.0);
94    }
95}
96
97#[macros::op_variants(owned)]
98impl<'a> Mul<&'a Mersenne107> for Mersenne107 {
99    type Output = Self;
100    #[inline]
101    fn mul(self, rhs: &'a Mersenne107) -> Self::Output {
102        let mut res = self;
103        res.mul_assign(rhs);
104        res
105    }
106}
107
108///////////////////////////////////////////////////////////////////////////////////////////////////
109// Arithmetic ops - addition
110///////////////////////////////////////////////////////////////////////////////////////////////////
111
112#[macros::op_variants(owned)]
113impl<'a> AddAssign<&'a Mersenne107> for Mersenne107 {
114    #[inline]
115    fn add_assign(&mut self, rhs: &'a Mersenne107) {
116        self.0 += rhs.0;
117        super::m107_ops::reduce_mod_1bit_inplace(&mut self.0);
118    }
119}
120#[macros::op_variants(owned)]
121impl<'a> Add<&'a Mersenne107> for Mersenne107 {
122    type Output = Self;
123
124    #[inline]
125    fn add(self, rhs: &'a Mersenne107) -> Self::Output {
126        let mut res = self;
127        res.add_assign(rhs);
128        res
129    }
130}
131
132///////////////////////////////////////////////////////////////////////////////////////////////////
133// Arithmetic ops - substraction
134///////////////////////////////////////////////////////////////////////////////////////////////////
135
136#[macros::op_variants(owned)]
137impl<'a> SubAssign<&'a Mersenne107> for Mersenne107 {
138    #[inline]
139    fn sub_assign(&mut self, rhs: &'a Mersenne107) {
140        self.0 += Self::MODULUS - rhs.0;
141        super::m107_ops::reduce_mod_1bit_inplace(&mut self.0);
142    }
143}
144
145#[macros::op_variants(owned)]
146impl<'a> Sub<&'a Mersenne107> for Mersenne107 {
147    type Output = Self;
148
149    #[inline]
150    fn sub(mut self, rhs: &'a Mersenne107) -> Self::Output {
151        self.sub_assign(rhs);
152        self
153    }
154}
155
156///////////////////////////////////////////////////////////////////////////////////////////////////
157// Arithmetic ops - negation
158///////////////////////////////////////////////////////////////////////////////////////////////////
159
160#[macros::op_variants(borrowed)]
161impl Neg for Mersenne107 {
162    type Output = Mersenne107;
163
164    fn neg(self) -> Self::Output {
165        Self(super::m107_ops::reduce_mod_1bit(Self::MODULUS - self.0))
166    }
167}
168
169///////////////////////////////////////////////////////////////////////////////////////////////////
170// Constant time
171///////////////////////////////////////////////////////////////////////////////////////////////////
172
173impl ConditionallySelectable for Mersenne107 {
174    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
175        Self(u128::conditional_select(&a.0, &b.0, choice))
176    }
177}
178
179impl ConstantTimeEq for Mersenne107 {
180    fn ct_eq(&self, other: &Self) -> Choice {
181        self.0.ct_eq(&other.0)
182    }
183}
184
185///////////////////////////////////////////////////////////////////////////////////////////////////
186// Iterator operations
187///////////////////////////////////////////////////////////////////////////////////////////////////
188
189impl Sum for Mersenne107 {
190    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
191        let t = iter.fold(<Self as AccReduce>::zero_wide(), |mut acc, x| {
192            Self::acc(&mut acc, &x);
193            acc
194        });
195        Self::reduce_mod_order(t)
196    }
197}
198
199impl<'a> Sum<&'a Self> for Mersenne107 {
200    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
201        let t = iter.fold(<Self as AccReduce>::zero_wide(), |mut acc, x| {
202            Self::acc(&mut acc, x);
203            acc
204        });
205        Self::reduce_mod_order(t)
206    }
207}
208
209impl<'a> Product<&'a Self> for Mersenne107 {
210    fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
211        iter.fold(Self::ONE, |acc, x| acc * x)
212    }
213}
214
215impl Product for Mersenne107 {
216    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
217        iter.fold(Self::ONE, |acc, x| acc * x)
218    }
219}
220
221///////////////////////////////////////////////////////////////////////////////////////////////////
222// Field trait
223///////////////////////////////////////////////////////////////////////////////////////////////////
224
225impl Field for Mersenne107 {
226    const ZERO: Self = Mersenne107(0);
227    const ONE: Self = Mersenne107(1);
228
229    fn random(mut rng: impl RngCore) -> Self {
230        let tmp = rng.gen::<u128>();
231        Self(super::m107_ops::reduce_mod(tmp)) // the probability is skewed because M107 modulus
232                                               // does not
233                                               // divide 2^128 exactly
234    }
235
236    fn square(&self) -> Self {
237        *self * self // TODO: optimize ?
238    }
239
240    fn double(&self) -> Self {
241        Self(super::m107_ops::reduce_mod_1bit(self.0 << 1))
242    }
243
244    fn invert(&self) -> CtOption<Self> {
245        // Fallback to ff implementation
246        // TODO: see if we can optimize this without ff
247        let val: ff_impl::Mersenne107FF = self.into();
248        let inv = val.invert();
249        inv.map(|v| v.into())
250    }
251
252    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
253        // p = 2^107 - 1 ≡ 3 (mod 4), so sqrt(num/div) has the closed form
254        //     y = num·div·(num·div³)^((p-3)/4)
255        // computed with a single fixed exponentiation and no modular inversion (unlike the generic
256        // Tonelli–Shanks `sqrt_ratio`). `y` is a true square root of num/div iff y²·div == num. The
257        // exponent (p-3)/4 = 2^105 - 1.
258        let uv = *num * div;
259        let uv3 = div.square() * uv;
260        let y = uv * pow2_minus_1(uv3, 105);
261        let is_qr = (y.square() * div).ct_eq(num);
262        (is_qr, y)
263    }
264
265    fn sqrt(&self) -> CtOption<Self> {
266        // p ≡ 3 (mod 4): sqrt(a) = a^((p+1)/4) = a^(2^105), i.e. 105 repeated squarings. The result
267        // is a valid square root iff it squares back to `a` (rejects non-residues; zero maps to
268        // zero).
269        let root = pow2_pow(*self, 105);
270        CtOption::new(root, root.square().ct_eq(self))
271    }
272}
273
274///////////////////////////////////////////////////////////////////////////////////////////////////
275// Field extension trait
276///////////////////////////////////////////////////////////////////////////////////////////////////
277
278impl FieldExtension for Mersenne107 {
279    type Subfield = Self;
280    type Degree = U1;
281    type FieldBitSize = typenum::U<{ Mersenne107::NUM_BITS }>;
282    type FieldBytesSize = U14;
283
284    fn to_subfield_elements(&self) -> Array<Self::Subfield, Self::Degree> {
285        Array([*self])
286    }
287
288    fn from_subfield_elements(elems: Array<Self::Subfield, Self::Degree>) -> Self {
289        elems[0]
290    }
291
292    fn to_le_bytes(&self) -> Array<u8, Self::FieldBytesSize> {
293        self.as_le_array().into()
294    }
295
296    fn from_le_bytes(bytes: &[u8]) -> Option<Self> {
297        if bytes.len() == 14 {
298            let arr: &[u8; 14] = bytes.try_into().expect("This should never fail");
299            Self::from_canonical_bytes(arr)
300        } else {
301            None
302        }
303    }
304
305    fn mul_by_subfield(&self, other: &Self::Subfield) -> Self {
306        *self * other
307    }
308
309    fn generator() -> Self {
310        Self(3u128) // 3^(2^107-2) == 1 mod 2^107-1
311    }
312}
313
314impl Random for Mersenne107 {
315    fn random(mut rng: impl CryptoRngCore) -> Self {
316        let tmp = rng.gen::<u128>();
317        Self(super::m107_ops::reduce_mod(tmp))
318    }
319
320    fn random_array<M: Positive>(mut rng: impl CryptoRngCore) -> HeapArray<Self, M> {
321        let mut buf = HeapArray::<Self, M>::default().into_box_bytes();
322        rng.fill_bytes(&mut buf);
323        let mut tmp = HeapArray::from_box_bytes(buf);
324        tmp.iter_mut()
325            .for_each(|v: &mut Self| super::m107_ops::reduce_mod_inplace(&mut v.0));
326        tmp
327    }
328}
329
330unsafe impl bytemuck::Zeroable for Mersenne107 {}
331unsafe impl bytemuck::Pod for Mersenne107 {}
332
333impl FromUniformBytes for Mersenne107 {
334    type UniformBytes = U16;
335    fn from_uniform_bytes(bytes: &hybrid_array::Array<u8, Self::UniformBytes>) -> Self {
336        let mut val = u128::from_le_bytes(bytes.0);
337        super::m107_ops::reduce_mod_inplace(&mut val);
338        Self(val)
339    }
340}
341
342impl From<u64> for Mersenne107 {
343    fn from(val: u64) -> Self {
344        Self(val as u128)
345    }
346}
347
348impl From<u128> for Mersenne107 {
349    fn from(val: u128) -> Self {
350        Self(super::m107_ops::reduce_mod(val))
351    }
352}
353
354impl From<ff_impl::Mersenne107FF> for Mersenne107 {
355    fn from(val: ff_impl::Mersenne107FF) -> Self {
356        Self::from_le_bytes(&val.to_repr().as_ref()[..14]).unwrap()
357    }
358}
359
360impl<'a> From<&'a Mersenne107> for ff_impl::Mersenne107FF {
361    fn from(val: &'a Mersenne107) -> Self {
362        Self::from_repr(ff_impl::Mersenne107FFRepr(val.0.to_le_bytes())).unwrap()
363    }
364}
365
366#[cfg(test)]
367mod test {
368    use ff::Field;
369    use num_bigint::BigInt;
370    use typenum::Unsigned;
371
372    use crate::{
373        algebra::field::{
374            mersenne::{m107::Mersenne107, test::bigint_to_m107},
375            FieldExtension,
376        },
377        random::test_rng,
378    };
379
380    type M = typenum::U1000;
381
382    #[test]
383    fn test_neg() {
384        fn test_internal(a: Mersenne107) {
385            let exp = bigint_to_m107(-BigInt::from(a.0));
386            let act = -a;
387            assert_eq!(exp, act, "a = {a:?}");
388        }
389
390        let mut rng = test_rng();
391        for _ in 0..M::to_usize() {
392            let a = Mersenne107::random(&mut rng);
393            test_internal(a);
394        }
395
396        // Corner cases
397        test_internal(Mersenne107::ZERO);
398        test_internal(Mersenne107::ONE);
399        test_internal(Mersenne107(Mersenne107::MAX));
400    }
401
402    #[test]
403    fn test_invert() {
404        fn test_internal(a: Mersenne107) {
405            let a_inv = a.invert().unwrap();
406            let act = a * a_inv;
407            assert_eq!(Mersenne107::ONE, act, "a = {a:?}");
408        }
409
410        let mut rng = test_rng();
411        for _ in 0..M::to_usize() {
412            let a = Mersenne107::random(&mut rng);
413            if a == Mersenne107::ZERO {
414                continue;
415            }
416            test_internal(a);
417        }
418
419        // Corner cases
420        test_internal(Mersenne107::ONE);
421        test_internal(Mersenne107(Mersenne107::MAX));
422    }
423
424    #[test]
425    fn test_sqrt() {
426        fn test_internal(a: Mersenne107) {
427            let a_sqrt = a.sqrt();
428            if a_sqrt.into_option().is_none() {
429                return;
430            }
431
432            let a_sqrt = a_sqrt.unwrap();
433            let act = a_sqrt * a_sqrt;
434            assert_eq!(a, act, "a = {a:?}");
435        }
436
437        let mut rng = test_rng();
438        for _ in 0..M::to_usize() {
439            let a = Mersenne107::random(&mut rng);
440            test_internal(a);
441        }
442
443        // Corner cases
444        test_internal(Mersenne107::ZERO);
445        test_internal(Mersenne107::ONE);
446        test_internal(Mersenne107(Mersenne107::MAX));
447    }
448
449    #[test]
450    fn test_sqrt_ratio() {
451        fn test_internal(num: Mersenne107, div: Mersenne107) {
452            let (is_qr, y) = Mersenne107::sqrt_ratio(&num, &div);
453
454            // QR-ness must agree with the generic ff reference implementation.
455            let num_ff: super::ff_impl::Mersenne107FF = (&num).into();
456            let div_ff: super::ff_impl::Mersenne107FF = (&div).into();
457            let (is_qr_ref, _) = super::ff_impl::Mersenne107FF::sqrt_ratio(&num_ff, &div_ff);
458            assert_eq!(
459                bool::from(is_qr),
460                bool::from(is_qr_ref),
461                "QR mismatch for num={num:?} div={div:?}"
462            );
463
464            // When num/div is a square, y must satisfy y² · div == num.
465            if bool::from(is_qr) {
466                assert_eq!(
467                    y.square() * div,
468                    num,
469                    "wrong root for num={num:?} div={div:?}"
470                );
471            }
472        }
473
474        let mut rng = test_rng();
475        for _ in 0..M::to_usize() {
476            let num = Mersenne107::random(&mut rng);
477            let div = Mersenne107::random(&mut rng);
478            if div == Mersenne107::ZERO {
479                continue;
480            }
481            test_internal(num, div);
482            // The daBits use case: inverse square root sqrt_ratio(1, y) == y^{-1/2}.
483            test_internal(Mersenne107::ONE, div);
484        }
485
486        // Corner cases
487        test_internal(Mersenne107::ONE, Mersenne107::ONE);
488        test_internal(Mersenne107::ZERO, Mersenne107::ONE);
489        test_internal(Mersenne107(Mersenne107::MAX), Mersenne107::ONE);
490    }
491
492    #[test]
493    fn test_canonical_bytes_decoding() {
494        let value = Mersenne107::from(123456789u64);
495        let bytes = value.to_le_bytes();
496        assert_eq!(Mersenne107::from_le_bytes(&bytes), Some(value));
497
498        // Encoding of the modulus p = 2^107 - 1 is non-canonical and must be rejected.
499        let modulus_bytes = [
500            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
501        ];
502        assert_eq!(Mersenne107::from_le_bytes(&modulus_bytes), None);
503    }
504
505    macro_rules! test_op {
506        ($op:tt) => {
507                fn test_internal(a: Mersenne107, b: Mersenne107) {
508                    let exp = bigint_to_m107(BigInt::from(a.0) $op BigInt::from(b.0));
509                    let act = a $op b;
510                    assert_eq!(exp, act, "a = {a:?}, b = {b:?}");
511                }
512
513                let mut rng = test_rng();
514                for _ in 0..M::to_usize() {
515                    let a = Mersenne107::random(&mut rng);
516                    let b = Mersenne107::random(&mut rng);
517                    test_internal(a, b);
518                }
519
520                // Corner cases
521                test_internal(Mersenne107::ZERO, Mersenne107::ZERO);
522                test_internal(Mersenne107::ZERO, Mersenne107::ONE);
523                test_internal(Mersenne107::ONE, Mersenne107::ZERO);
524                test_internal(Mersenne107::ONE, Mersenne107::ONE);
525                test_internal(Mersenne107::ZERO, Mersenne107(Mersenne107::MAX));
526                test_internal(Mersenne107::ONE, Mersenne107(Mersenne107::MAX));
527                test_internal(Mersenne107(Mersenne107::MAX), Mersenne107::ZERO);
528                test_internal(Mersenne107(Mersenne107::MAX), Mersenne107::ONE);
529                test_internal(Mersenne107(Mersenne107::MAX), Mersenne107(Mersenne107::MAX));
530            }
531    }
532
533    #[test]
534    fn test_mul() {
535        test_op!(*);
536    }
537    #[test]
538    fn test_add() {
539        test_op!(+);
540    }
541    #[test]
542    fn test_sub() {
543        test_op!(-);
544    }
545}