Skip to main content

sapling_crypto_ce/alt_babyjubjub/
fs.rs

1use byteorder::{ByteOrder, LittleEndian};
2use bellman::pairing::ff::{adc, sbb, mac_with_carry};
3use bellman::pairing::ff::{BitIterator, Field, PrimeField, SqrtField, PrimeFieldRepr, PrimeFieldDecodingError, LegendreSymbol};
4use bellman::pairing::ff::LegendreSymbol::*;
5use super::ToUniform;
6
7// s = 2736030358979909402780800718157159386076813972158567259200215660948447373041
8const MODULUS: FsRepr = FsRepr([
9    0x677297dc392126f1,
10    0xab3eedb83920ee0a,
11    0x370a08b6d0302b0b,
12    0x060c89ce5c263405,
13]);
14
15// The number of bits needed to represent the modulus.
16const MODULUS_BITS: u32 = 251;
17
18// The number of bits that must be shaved from the beginning of
19// the representation when randomly sampling.
20const REPR_SHAVE_BITS: u32 = 5;
21
22// R = 2**256 % s
23const R: FsRepr = FsRepr([
24    0x073315dea08f9c76,
25    0xe7acffc6a098f24b,
26    0xf85a9201d818f015,
27    0x01f16424e1bb7724,
28]);
29
30// R2 = R^2 % s
31const R2: FsRepr = FsRepr([
32    0x35e44abee7ecb21e,
33    0x74646cacf5f84ec4,
34    0xe472df203faa158f,
35    0x0445b524f1ba50a8,
36]);
37
38// INV = -(s^{-1} mod 2^64) mod s
39const INV: u64 = 0x532ce5aebc48f5ef;
40
41// GENERATOR = 7 (multiplicative generator of r-1 order, that is also quadratic nonresidue)
42const GENERATOR: FsRepr = FsRepr([
43    0x6380695df1aaf958,
44    0xff3d22fdf1ecc3f8,
45    0x5c65ec9f484e3a81,
46    0x0180a96573d3d9f8,
47]);
48
49// 2^S * t = MODULUS - 1 with t odd
50const S: u32 = 4;
51
52// 2^S root of unity computed by GENERATOR^t
53const ROOT_OF_UNITY: FsRepr = FsRepr([
54    0xa13885692e7afcb0,
55    0xb789766cd18573ca,
56    0xd5468c0174efc3b9,
57    0x03534b612b0b6f7a,
58]);
59
60// -((2**256) mod s) mod s
61const NEGATIVE_ONE: Fs = Fs(FsRepr([
62    0x603f81fd98918a7b,
63    0xc391edf19887fbbf,
64    0x3eaf76b4f8173af5,
65    0x041b25a97a6abce0,
66]));
67
68/// This is the underlying representation of an element of `Fs`.
69#[derive(Copy, Clone, PartialEq, Eq, Default, Debug, Hash)]
70pub struct FsRepr(pub [u64; 4]);
71
72impl ::rand::Rand for FsRepr {
73    #[inline(always)]
74    fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
75        FsRepr(rng.gen())
76    }
77}
78
79impl ::std::fmt::Display for FsRepr
80{
81    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
82        write!(f, "0x")?;
83        for i in self.0.iter().rev() {
84            write!(f, "{:016x}", *i)?;
85        }
86
87        Ok(())
88    }
89}
90
91impl AsRef<[u64]> for FsRepr {
92    #[inline(always)]
93    fn as_ref(&self) -> &[u64] {
94        &self.0
95    }
96}
97
98impl AsMut<[u64]> for FsRepr {
99    #[inline(always)]
100    fn as_mut(&mut self) -> &mut [u64] {
101        &mut self.0
102    }
103}
104
105impl From<u64> for FsRepr {
106    #[inline(always)]
107    fn from(val: u64) -> FsRepr {
108        let mut repr = Self::default();
109        repr.0[0] = val;
110        repr
111    }
112}
113
114impl Ord for FsRepr {
115    #[inline(always)]
116    fn cmp(&self, other: &FsRepr) -> ::std::cmp::Ordering {
117        for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
118            if a < b {
119                return ::std::cmp::Ordering::Less
120            } else if a > b {
121                return ::std::cmp::Ordering::Greater
122            }
123        }
124
125        ::std::cmp::Ordering::Equal
126    }
127}
128
129impl PartialOrd for FsRepr {
130    #[inline(always)]
131    fn partial_cmp(&self, other: &FsRepr) -> Option<::std::cmp::Ordering> {
132        Some(self.cmp(other))
133    }
134}
135
136impl PrimeFieldRepr for FsRepr {
137    #[inline(always)]
138    fn is_odd(&self) -> bool {
139        self.0[0] & 1 == 1
140    }
141
142    #[inline(always)]
143    fn is_even(&self) -> bool {
144        !self.is_odd()
145    }
146
147    #[inline(always)]
148    fn is_zero(&self) -> bool {
149        self.0.iter().all(|&e| e == 0)
150    }
151
152    #[inline(always)]
153    fn shr(&mut self, mut n: u32) {
154        if n >= 64 * 4 {
155            *self = Self::from(0);
156            return;
157        }
158
159        while n >= 64 {
160            let mut t = 0;
161            for i in self.0.iter_mut().rev() {
162                ::std::mem::swap(&mut t, i);
163            }
164            n -= 64;
165        }
166
167        if n > 0 {
168            let mut t = 0;
169            for i in self.0.iter_mut().rev() {
170                let t2 = *i << (64 - n);
171                *i >>= n;
172                *i |= t;
173                t = t2;
174            }
175        }
176    }
177
178    #[inline(always)]
179    fn div2(&mut self) {
180        let mut t = 0;
181        for i in self.0.iter_mut().rev() {
182            let t2 = *i << 63;
183            *i >>= 1;
184            *i |= t;
185            t = t2;
186        }
187    }
188
189    #[inline(always)]
190    fn mul2(&mut self) {
191        let mut last = 0;
192        for i in &mut self.0 {
193            let tmp = *i >> 63;
194            *i <<= 1;
195            *i |= last;
196            last = tmp;
197        }
198    }
199
200    #[inline(always)]
201    fn shl(&mut self, mut n: u32) {
202        if n >= 64 * 4 {
203            *self = Self::from(0);
204            return;
205        }
206
207        while n >= 64 {
208            let mut t = 0;
209            for i in &mut self.0 {
210                ::std::mem::swap(&mut t, i);
211            }
212            n -= 64;
213        }
214
215        if n > 0 {
216            let mut t = 0;
217            for i in &mut self.0 {
218                let t2 = *i >> (64 - n);
219                *i <<= n;
220                *i |= t;
221                t = t2;
222            }
223        }
224    }
225
226    #[inline(always)]
227    fn num_bits(&self) -> u32 {
228        let mut ret = (4 as u32) * 64;
229        for i in self.0.iter().rev() {
230            let leading = i.leading_zeros();
231            ret -= leading;
232            if leading != 64 {
233                break;
234            }
235        }
236
237        ret
238    }
239
240    #[inline(always)]
241    fn add_nocarry(&mut self, other: &FsRepr) {
242        let mut carry = 0;
243
244        for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
245            *a = adc(*a, *b, &mut carry);
246        }
247    }
248
249    #[inline(always)]
250    fn sub_noborrow(&mut self, other: &FsRepr) {
251        let mut borrow = 0;
252
253        for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
254            *a = sbb(*a, *b, &mut borrow);
255        }
256    }
257}
258
259/// This is an element of the scalar field of the Jubjub curve.
260#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
261pub struct Fs(FsRepr);
262
263impl ::std::fmt::Display for Fs
264{
265    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
266        write!(f, "Fs({})", self.into_repr())
267    }
268}
269
270impl ::rand::Rand for Fs {
271    fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
272        loop {
273            let mut tmp = Fs(FsRepr::rand(rng));
274
275            // Mask away the unused bits at the beginning.
276            tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
277
278            if tmp.is_valid() {
279                return tmp
280            }
281        }
282    }
283}
284
285impl From<Fs> for FsRepr {
286    fn from(e: Fs) -> FsRepr {
287        e.into_repr()
288    }
289}
290
291impl PrimeField for Fs {
292    type Repr = FsRepr;
293
294    fn from_repr(r: FsRepr) -> Result<Fs, PrimeFieldDecodingError> {
295        let mut r = Fs(r);
296        if r.is_valid() {
297            r.mul_assign(&Fs(R2));
298
299            Ok(r)
300        } else {
301            Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0)))
302        }
303    }
304
305    fn from_raw_repr(r: FsRepr) -> Result<Fs, PrimeFieldDecodingError> {
306        let r = Fs(r);
307        if r.is_valid() {
308            Ok(r)
309        } else {
310            Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0)))
311        }
312    }
313
314    fn into_repr(&self) -> FsRepr {
315        let mut r = *self;
316        r.mont_reduce((self.0).0[0], (self.0).0[1],
317                      (self.0).0[2], (self.0).0[3],
318                      0, 0, 0, 0);
319        r.0
320    }
321
322    fn into_raw_repr(&self) -> FsRepr {
323        let r = *self;
324        r.0
325    }
326
327    fn char() -> FsRepr {
328        MODULUS
329    }
330
331    const NUM_BITS: u32 = MODULUS_BITS;
332
333    const CAPACITY: u32 = Self::NUM_BITS - 1;
334
335    fn multiplicative_generator() -> Self {
336        Fs(GENERATOR)
337    }
338
339    const S: u32 = S;
340
341    fn root_of_unity() -> Self {
342        Fs(ROOT_OF_UNITY)
343    }
344}
345
346impl Field for Fs {
347    #[inline]
348    fn zero() -> Self {
349        Fs(FsRepr::from(0))
350    }
351
352    #[inline]
353    fn one() -> Self {
354        Fs(R)
355    }
356
357    #[inline]
358    fn is_zero(&self) -> bool {
359        self.0.is_zero()
360    }
361
362    #[inline]
363    fn add_assign(&mut self, other: &Fs) {
364        // This cannot exceed the backing capacity.
365        self.0.add_nocarry(&other.0);
366
367        // However, it may need to be reduced.
368        self.reduce();
369    }
370
371    #[inline]
372    fn double(&mut self) {
373        // This cannot exceed the backing capacity.
374        self.0.mul2();
375
376        // However, it may need to be reduced.
377        self.reduce();
378    }
379
380    #[inline]
381    fn sub_assign(&mut self, other: &Fs) {
382        // If `other` is larger than `self`, we'll need to add the modulus to self first.
383        if other.0 > self.0 {
384            self.0.add_nocarry(&MODULUS);
385        }
386
387        self.0.sub_noborrow(&other.0);
388    }
389
390    #[inline]
391    fn negate(&mut self) {
392        if !self.is_zero() {
393            let mut tmp = MODULUS;
394            tmp.sub_noborrow(&self.0);
395            self.0 = tmp;
396        }
397    }
398
399    fn inverse(&self) -> Option<Self> {
400        if self.is_zero() {
401            None
402        } else {
403            // Guajardo Kumar Paar Pelzl
404            // Efficient Software-Implementation of Finite Fields with Applications to Cryptography
405            // Algorithm 16 (BEA for Inversion in Fp)
406
407            let one = FsRepr::from(1);
408
409            let mut u = self.0;
410            let mut v = MODULUS;
411            let mut b = Fs(R2); // Avoids unnecessary reduction step.
412            let mut c = Self::zero();
413
414            while u != one && v != one {
415                while u.is_even() {
416                    u.div2();
417
418                    if b.0.is_even() {
419                        b.0.div2();
420                    } else {
421                        b.0.add_nocarry(&MODULUS);
422                        b.0.div2();
423                    }
424                }
425
426                while v.is_even() {
427                    v.div2();
428
429                    if c.0.is_even() {
430                        c.0.div2();
431                    } else {
432                        c.0.add_nocarry(&MODULUS);
433                        c.0.div2();
434                    }
435                }
436
437                if v < u {
438                    u.sub_noborrow(&v);
439                    b.sub_assign(&c);
440                } else {
441                    v.sub_noborrow(&u);
442                    c.sub_assign(&b);
443                }
444            }
445
446            if u == one {
447                Some(b)
448            } else {
449                Some(c)
450            }
451        }
452    }
453
454    #[inline(always)]
455    fn frobenius_map(&mut self, _: usize) {
456        // This has no effect in a prime field.
457    }
458
459    #[inline]
460    fn mul_assign(&mut self, other: &Fs)
461    {
462        let mut carry = 0;
463        let r0 = mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry);
464        let r1 = mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry);
465        let r2 = mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry);
466        let r3 = mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry);
467        let r4 = carry;
468        let mut carry = 0;
469        let r1 = mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry);
470        let r2 = mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry);
471        let r3 = mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry);
472        let r4 = mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry);
473        let r5 = carry;
474        let mut carry = 0;
475        let r2 = mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry);
476        let r3 = mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry);
477        let r4 = mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry);
478        let r5 = mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry);
479        let r6 = carry;
480        let mut carry = 0;
481        let r3 = mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry);
482        let r4 = mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry);
483        let r5 = mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry);
484        let r6 = mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry);
485        let r7 = carry;
486        self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7);
487    }
488
489    #[inline]
490    fn square(&mut self)
491    {
492        let mut carry = 0;
493        let r1 = mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry);
494        let r2 = mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry);
495        let r3 = mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry);
496        let r4 = carry;
497        let mut carry = 0;
498        let r3 = mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry);
499        let r4 = mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry);
500        let r5 = carry;
501        let mut carry = 0;
502        let r5 = mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry);
503        let r6 = carry;
504
505        let r7 = r6 >> 63;
506        let r6 = (r6 << 1) | (r5 >> 63);
507        let r5 = (r5 << 1) | (r4 >> 63);
508        let r4 = (r4 << 1) | (r3 >> 63);
509        let r3 = (r3 << 1) | (r2 >> 63);
510        let r2 = (r2 << 1) | (r1 >> 63);
511        let r1 = r1 << 1;
512
513        let mut carry = 0;
514        let r0 = mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry);
515        let r1 = adc(r1, 0, &mut carry);
516        let r2 = mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry);
517        let r3 = adc(r3, 0, &mut carry);
518        let r4 = mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry);
519        let r5 = adc(r5, 0, &mut carry);
520        let r6 = mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry);
521        let r7 = adc(r7, 0, &mut carry);
522        self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7);
523    }
524}
525
526impl Fs {
527    /// Determines if the element is really in the field. This is only used
528    /// internally.
529    #[inline(always)]
530    fn is_valid(&self) -> bool {
531        self.0 < MODULUS
532    }
533
534    /// Subtracts the modulus from this element if this element is not in the
535    /// field. Only used internally.
536    #[inline(always)]
537    fn reduce(&mut self) {
538        if !self.is_valid() {
539            self.0.sub_noborrow(&MODULUS);
540        }
541    }
542
543    #[inline(always)]
544    fn mont_reduce(
545        &mut self,
546        r0: u64,
547        mut r1: u64,
548        mut r2: u64,
549        mut r3: u64,
550        mut r4: u64,
551        mut r5: u64,
552        mut r6: u64,
553        mut r7: u64
554    )
555    {
556        // The Montgomery reduction here is based on Algorithm 14.32 in
557        // Handbook of Applied Cryptography
558        // <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
559
560        let k = r0.wrapping_mul(INV);
561        let mut carry = 0;
562        mac_with_carry(r0, k, MODULUS.0[0], &mut carry);
563        r1 = mac_with_carry(r1, k, MODULUS.0[1], &mut carry);
564        r2 = mac_with_carry(r2, k, MODULUS.0[2], &mut carry);
565        r3 = mac_with_carry(r3, k, MODULUS.0[3], &mut carry);
566        r4 = adc(r4, 0, &mut carry);
567        let carry2 = carry;
568        let k = r1.wrapping_mul(INV);
569        let mut carry = 0;
570        mac_with_carry(r1, k, MODULUS.0[0], &mut carry);
571        r2 = mac_with_carry(r2, k, MODULUS.0[1], &mut carry);
572        r3 = mac_with_carry(r3, k, MODULUS.0[2], &mut carry);
573        r4 = mac_with_carry(r4, k, MODULUS.0[3], &mut carry);
574        r5 = adc(r5, carry2, &mut carry);
575        let carry2 = carry;
576        let k = r2.wrapping_mul(INV);
577        let mut carry = 0;
578        mac_with_carry(r2, k, MODULUS.0[0], &mut carry);
579        r3 = mac_with_carry(r3, k, MODULUS.0[1], &mut carry);
580        r4 = mac_with_carry(r4, k, MODULUS.0[2], &mut carry);
581        r5 = mac_with_carry(r5, k, MODULUS.0[3], &mut carry);
582        r6 = adc(r6, carry2, &mut carry);
583        let carry2 = carry;
584        let k = r3.wrapping_mul(INV);
585        let mut carry = 0;
586        mac_with_carry(r3, k, MODULUS.0[0], &mut carry);
587        r4 = mac_with_carry(r4, k, MODULUS.0[1], &mut carry);
588        r5 = mac_with_carry(r5, k, MODULUS.0[2], &mut carry);
589        r6 = mac_with_carry(r6, k, MODULUS.0[3], &mut carry);
590        r7 = adc(r7, carry2, &mut carry);
591        (self.0).0[0] = r4;
592        (self.0).0[1] = r5;
593        (self.0).0[2] = r6;
594        (self.0).0[3] = r7;
595        self.reduce();
596    }
597
598    fn mul_bits<S: AsRef<[u64]>>(&self, bits: BitIterator<S>) -> Self {
599        let mut res = Self::zero();
600        for bit in bits {
601            res.double();
602
603            if bit {
604                res.add_assign(self)
605            }
606        }
607        res
608    }
609}
610
611impl ToUniform for Fs {
612    /// Convert a little endian byte string into a uniform
613    /// field element. The number is reduced mod s. The caller
614    /// is responsible for ensuring the input is 64 bytes of
615    /// Random Oracle output.
616    fn to_uniform(digest: &[u8]) -> Self {
617        assert_eq!(digest.len(), 64);
618        let mut repr: [u64; 8] = [0; 8];
619        LittleEndian::read_u64_into(digest, &mut repr);
620        Self::one().mul_bits(BitIterator::new(repr))
621    }
622
623    /// Convert a little endian byte string into a uniform
624    /// field element. The number is reduced mod s. The caller
625    /// is responsible for ensuring the input is 32 bytes of
626    /// Random Oracle output.
627    fn to_uniform_32(digest: &[u8]) -> Self {
628        assert_eq!(digest.len(), 32);
629        let mut repr: [u64; 4] = [0; 4];
630        LittleEndian::read_u64_into(digest, &mut repr);
631        Self::one().mul_bits(BitIterator::new(repr))
632    }
633}
634
635impl SqrtField for Fs {
636
637    fn legendre(&self) -> LegendreSymbol {
638        // s = self^((s - 1) // 2)
639        let s = self.pow([
640                0x33b94bee1c909378,
641                0xd59f76dc1c907705,
642                0x9b85045b68181585,
643                0x030644e72e131a02,
644            ]);
645        if s == Self::zero() { Zero }
646        else if s == Self::one() { QuadraticResidue }
647        else { QuadraticNonResidue }
648    }
649
650    fn sqrt(&self) -> Option<Self> {
651        None
652
653        // F**k
654        // s mod 4 == 1
655
656        // // Shank's algorithm for s mod 4 = 3
657        // // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2)
658
659        // // a1 = self^((s - 3) // 4)
660        // let mut a1 = self.pow([0xb425c397b5bdcb2d, 0x299a0824f3320420, 0x4199cec0404d0ec0, 0x39f6d3a994cebea]);
661        // let mut a0 = a1;
662        // a0.square();
663        // a0.mul_assign(self);
664
665        // if a0 == NEGATIVE_ONE
666        // {
667        //     None
668        // }
669        // else
670        // {
671        //     a1.mul_assign(self);
672        //     Some(a1)
673        // }
674    }
675}
676
677
678#[test]
679fn test_neg_one() {
680    let mut o = Fs::one();
681    o.negate();
682
683    assert_eq!(NEGATIVE_ONE, o);
684}
685
686#[cfg(test)]
687use rand::{SeedableRng, XorShiftRng, Rand};
688
689#[test]
690fn test_fs_repr_ordering() {
691    fn assert_equality(a: FsRepr, b: FsRepr) {
692        assert_eq!(a, b);
693        assert!(a.cmp(&b) == ::std::cmp::Ordering::Equal);
694    }
695
696    fn assert_lt(a: FsRepr, b: FsRepr) {
697        assert!(a < b);
698        assert!(b > a);
699    }
700
701    assert_equality(FsRepr([9999, 9999, 9999, 9999]), FsRepr([9999, 9999, 9999, 9999]));
702    assert_equality(FsRepr([9999, 9998, 9999, 9999]), FsRepr([9999, 9998, 9999, 9999]));
703    assert_equality(FsRepr([9999, 9999, 9999, 9997]), FsRepr([9999, 9999, 9999, 9997]));
704    assert_lt(FsRepr([9999, 9997, 9999, 9998]), FsRepr([9999, 9997, 9999, 9999]));
705    assert_lt(FsRepr([9999, 9997, 9998, 9999]), FsRepr([9999, 9997, 9999, 9999]));
706    assert_lt(FsRepr([9, 9999, 9999, 9997]), FsRepr([9999, 9999, 9999, 9997]));
707}
708
709#[test]
710fn test_fs_repr_from() {
711    assert_eq!(FsRepr::from(100), FsRepr([100, 0, 0, 0]));
712}
713
714#[test]
715fn test_fs_repr_is_odd() {
716    assert!(!FsRepr::from(0).is_odd());
717    assert!(FsRepr::from(0).is_even());
718    assert!(FsRepr::from(1).is_odd());
719    assert!(!FsRepr::from(1).is_even());
720    assert!(!FsRepr::from(324834872).is_odd());
721    assert!(FsRepr::from(324834872).is_even());
722    assert!(FsRepr::from(324834873).is_odd());
723    assert!(!FsRepr::from(324834873).is_even());
724}
725
726#[test]
727fn test_fs_repr_is_zero() {
728    assert!(FsRepr::from(0).is_zero());
729    assert!(!FsRepr::from(1).is_zero());
730    assert!(!FsRepr([0, 0, 1, 0]).is_zero());
731}
732
733#[test]
734fn test_fs_repr_div2() {
735    let mut a = FsRepr([0xbd2920b19c972321, 0x174ed0466a3be37e, 0xd468d5e3b551f0b5, 0xcb67c072733beefc]);
736    a.div2();
737    assert_eq!(a, FsRepr([0x5e949058ce4b9190, 0x8ba76823351df1bf, 0x6a346af1daa8f85a, 0x65b3e039399df77e]));
738    for _ in 0..10 {
739        a.div2();
740    }
741    assert_eq!(a, FsRepr([0x6fd7a524163392e4, 0x16a2e9da08cd477c, 0xdf9a8d1abc76aa3e, 0x196cf80e4e677d]));
742    for _ in 0..200 {
743        a.div2();
744    }
745    assert_eq!(a, FsRepr([0x196cf80e4e67, 0x0, 0x0, 0x0]));
746    for _ in 0..40 {
747        a.div2();
748    }
749    assert_eq!(a, FsRepr([0x19, 0x0, 0x0, 0x0]));
750    for _ in 0..4 {
751        a.div2();
752    }
753    assert_eq!(a, FsRepr([0x1, 0x0, 0x0, 0x0]));
754    a.div2();
755    assert!(a.is_zero());
756}
757
758#[test]
759fn test_fs_repr_shr() {
760    let mut a = FsRepr([0xb33fbaec482a283f, 0x997de0d3a88cb3df, 0x9af62d2a9a0e5525, 0x36003ab08de70da1]);
761    a.shr(0);
762    assert_eq!(
763        a,
764        FsRepr([0xb33fbaec482a283f, 0x997de0d3a88cb3df, 0x9af62d2a9a0e5525, 0x36003ab08de70da1])
765    );
766    a.shr(1);
767    assert_eq!(
768        a,
769        FsRepr([0xd99fdd762415141f, 0xccbef069d44659ef, 0xcd7b16954d072a92, 0x1b001d5846f386d0])
770    );
771    a.shr(50);
772    assert_eq!(
773        a,
774        FsRepr([0xbc1a7511967bf667, 0xc5a55341caa4b32f, 0x75611bce1b4335e, 0x6c0])
775    );
776    a.shr(130);
777    assert_eq!(
778        a,
779        FsRepr([0x1d5846f386d0cd7, 0x1b0, 0x0, 0x0])
780    );
781    a.shr(64);
782    assert_eq!(
783        a,
784        FsRepr([0x1b0, 0x0, 0x0, 0x0])
785    );
786}
787
788#[test]
789fn test_fs_repr_mul2() {
790    let mut a = FsRepr::from(23712937547);
791    a.mul2();
792    assert_eq!(a, FsRepr([0xb0acd6c96, 0x0, 0x0, 0x0]));
793    for _ in 0..60 {
794        a.mul2();
795    }
796    assert_eq!(a, FsRepr([0x6000000000000000, 0xb0acd6c9, 0x0, 0x0]));
797    for _ in 0..128 {
798        a.mul2();
799    }
800    assert_eq!(a, FsRepr([0x0, 0x0, 0x6000000000000000, 0xb0acd6c9]));
801    for _ in 0..60 {
802        a.mul2();
803    }
804    assert_eq!(a, FsRepr([0x0, 0x0, 0x0, 0x9600000000000000]));
805    for _ in 0..7 {
806        a.mul2();
807    }
808    assert!(a.is_zero());
809}
810
811#[test]
812fn test_fs_repr_num_bits() {
813    let mut a = FsRepr::from(0);
814    assert_eq!(0, a.num_bits());
815    a = FsRepr::from(1);
816    for i in 1..257 {
817        assert_eq!(i, a.num_bits());
818        a.mul2();
819    }
820    assert_eq!(0, a.num_bits());
821}
822
823#[test]
824fn test_fs_repr_sub_noborrow() {
825    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
826
827    // let mut t = FsRepr([0x8e62a7e85264e2c3, 0xb23d34c1941d3ca, 0x5976930b7502dd15, 0x600f3fb517bf5495]);
828    // t.sub_noborrow(&FsRepr([0xd64f669809cbc6a4, 0xfa76cb9d90cf7637, 0xfefb0df9038d43b3, 0x298a30c744b31acf]));
829    // assert!(t == FsRepr([0xb813415048991c1f, 0x10ad07ae88725d92, 0x5a7b851271759961, 0x36850eedd30c39c5]));
830
831    for _ in 0..1000 {
832        let mut a = FsRepr::rand(&mut rng);
833        a.0[3] >>= 30;
834        let mut b = a;
835        for _ in 0..10 {
836            b.mul2();
837        }
838        let mut c = b;
839        for _ in 0..10 {
840            c.mul2();
841        }
842
843        assert!(a < b);
844        assert!(b < c);
845
846        let mut csub_ba = c;
847        csub_ba.sub_noborrow(&b);
848        csub_ba.sub_noborrow(&a);
849
850        let mut csub_ab = c;
851        csub_ab.sub_noborrow(&a);
852        csub_ab.sub_noborrow(&b);
853
854        assert_eq!(csub_ab, csub_ba);
855    }
856}
857
858#[test]
859fn test_fs_legendre() {
860    assert_eq!(QuadraticResidue, Fs::one().legendre());
861    assert_eq!(Zero, Fs::zero().legendre());
862
863    let e = FsRepr([0x8385eec23df1f88e, 0x9a01fb412b2dba16, 0x4c928edcdd6c22f, 0x9f2df7ef69ecef9]);
864    assert_eq!(QuadraticResidue, Fs::from_repr(e).unwrap().legendre());
865    let e = FsRepr([0xe8ed9f299da78568, 0x35efdebc88b2209, 0xc82125cb1f916dbe, 0x6813d2b38c39bd0]);
866    assert_eq!(QuadraticNonResidue, Fs::from_repr(e).unwrap().legendre());
867}
868
869#[test]
870fn test_fr_repr_add_nocarry() {
871    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
872
873    // let mut t = FsRepr([0xd64f669809cbc6a4, 0xfa76cb9d90cf7637, 0xfefb0df9038d43b3, 0x298a30c744b31acf]);
874    // t.add_nocarry(&FsRepr([0x8e62a7e85264e2c3, 0xb23d34c1941d3ca, 0x5976930b7502dd15, 0x600f3fb517bf5495]));
875    // assert_eq!(t, FsRepr([0x64b20e805c30a967, 0x59a9ee9aa114a02, 0x5871a104789020c9, 0x8999707c5c726f65]));
876
877    // Test for the associativity of addition.
878    for _ in 0..1000 {
879        let mut a = FsRepr::rand(&mut rng);
880        let mut b = FsRepr::rand(&mut rng);
881        let mut c = FsRepr::rand(&mut rng);
882
883        // Unset the first few bits, so that overflow won't occur.
884        a.0[3] >>= 3;
885        b.0[3] >>= 3;
886        c.0[3] >>= 3;
887
888        let mut abc = a;
889        abc.add_nocarry(&b);
890        abc.add_nocarry(&c);
891
892        let mut acb = a;
893        acb.add_nocarry(&c);
894        acb.add_nocarry(&b);
895
896        let mut bac = b;
897        bac.add_nocarry(&a);
898        bac.add_nocarry(&c);
899
900        let mut bca = b;
901        bca.add_nocarry(&c);
902        bca.add_nocarry(&a);
903
904        let mut cab = c;
905        cab.add_nocarry(&a);
906        cab.add_nocarry(&b);
907
908        let mut cba = c;
909        cba.add_nocarry(&b);
910        cba.add_nocarry(&a);
911
912        assert_eq!(abc, acb);
913        assert_eq!(abc, bac);
914        assert_eq!(abc, bca);
915        assert_eq!(abc, cab);
916        assert_eq!(abc, cba);
917    }
918}
919
920#[test]
921fn test_fs_is_valid() {
922    let mut a = Fs(MODULUS);
923    assert!(!a.is_valid());
924    a.0.sub_noborrow(&FsRepr::from(1));
925    assert!(a.is_valid());
926    assert!(Fs(FsRepr::from(0)).is_valid());
927    // assert!(Fs(FsRepr([0xd0970e5ed6f72cb6, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9])).is_valid());
928    assert!(!Fs(FsRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])).is_valid());
929
930    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
931
932    for _ in 0..1000 {
933        let a = Fs::rand(&mut rng);
934        assert!(a.is_valid());
935    }
936}
937
938#[test]
939fn test_fs_add_assign() {
940    // {
941    //     // Random number
942    //     let mut tmp = Fs::from_str("4577408157467272683998459759522778614363623736323078995109579213719612604198").unwrap();
943    //     assert!(tmp.is_valid());
944    //     // Test that adding zero has no effect.
945    //     tmp.add_assign(&Fs(FsRepr::from(0)));
946    //     assert_eq!(tmp, Fs(FsRepr([0x8e6bfff4722d6e67, 0x5643da5c892044f9, 0x9465f4b281921a69, 0x25f752d3edd7162])));
947    //     // Add one and test for the result.
948    //     tmp.add_assign(&Fs(FsRepr::from(1)));
949    //     assert_eq!(tmp, Fs(FsRepr([0x8e6bfff4722d6e68, 0x5643da5c892044f9, 0x9465f4b281921a69, 0x25f752d3edd7162])));
950    //     // Add another random number that exercises the reduction.
951    //     tmp.add_assign(&Fs(FsRepr([0xb634d07bc42d4a70, 0xf724f0c008411f5f, 0x456d4053d865af34, 0x24ce814e8c63027])));
952    //     assert_eq!(tmp, Fs(FsRepr([0x44a0d070365ab8d8, 0x4d68cb1c91616459, 0xd9d3350659f7c99e, 0x4ac5d4227a3a189])));
953    //     // Add one to (s - 1) and test for the result.
954    //     tmp = Fs(FsRepr([0xd0970e5ed6f72cb6, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9]));
955    //     tmp.add_assign(&Fs(FsRepr::from(1)));
956    //     assert!(tmp.0.is_zero());
957    //     // Add a random number to another one such that the result is s - 1
958    //     tmp = Fs(FsRepr([0xa11fda5950ce3636, 0x922e0dbccfe0ca0e, 0xacebb6e215b82d4a, 0x97ffb8cdc3aee93]));
959    //     tmp.add_assign(&Fs(FsRepr([0x2f7734058628f680, 0x143a12d6fce74674, 0x597b841eeb7c0db6, 0x4fdb95d88f8c115])));
960    //     assert_eq!(tmp, Fs(FsRepr([0xd0970e5ed6f72cb6, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9])));
961    //     // Add one to the result and test for it.
962    //     tmp.add_assign(&Fs(FsRepr::from(1)));
963    //     assert!(tmp.0.is_zero());
964    // }
965
966    // Test associativity
967
968    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
969
970    for _ in 0..1000 {
971        // Generate a, b, c and ensure (a + b) + c == a + (b + c).
972        let a = Fs::rand(&mut rng);
973        let b = Fs::rand(&mut rng);
974        let c = Fs::rand(&mut rng);
975
976        let mut tmp1 = a;
977        tmp1.add_assign(&b);
978        tmp1.add_assign(&c);
979
980        let mut tmp2 = b;
981        tmp2.add_assign(&c);
982        tmp2.add_assign(&a);
983
984        assert!(tmp1.is_valid());
985        assert!(tmp2.is_valid());
986        assert_eq!(tmp1, tmp2);
987    }
988}
989
990#[test]
991fn test_fs_sub_assign() {
992    // {
993    //     // Test arbitrary subtraction that tests reduction.
994    //     let mut tmp = Fs(FsRepr([0xb384d9f6877afd99, 0x4442513958e1a1c1, 0x352c4b8a95eccc3f, 0x2db62dee4b0f2]));
995    //     tmp.sub_assign(&Fs(FsRepr([0xec5bd2d13ed6b05a, 0x2adc0ab3a39b5fa, 0x82d3360a493e637e, 0x53ccff4a64d6679])));
996    //     assert_eq!(tmp, Fs(FsRepr([0x97c015841f9b79f6, 0xe7fcb121eb6ffc49, 0xb8c050814de2a3c1, 0x943c0589dcafa21])));
997
998    //     // Test the opposite subtraction which doesn't test reduction.
999    //     tmp = Fs(FsRepr([0xec5bd2d13ed6b05a, 0x2adc0ab3a39b5fa, 0x82d3360a493e637e, 0x53ccff4a64d6679]));
1000    //     tmp.sub_assign(&Fs(FsRepr([0xb384d9f6877afd99, 0x4442513958e1a1c1, 0x352c4b8a95eccc3f, 0x2db62dee4b0f2])));
1001    //     assert_eq!(tmp, Fs(FsRepr([0x38d6f8dab75bb2c1, 0xbe6b6f71e1581439, 0x4da6ea7fb351973e, 0x539f491c768b587])));
1002
1003    //     // Test for sensible results with zero
1004    //     tmp = Fs(FsRepr::from(0));
1005    //     tmp.sub_assign(&Fs(FsRepr::from(0)));
1006    //     assert!(tmp.is_zero());
1007
1008    //     tmp = Fs(FsRepr([0x361e16aef5cce835, 0x55bbde2536e274c1, 0x4dc77a63fd15ee75, 0x1e14bb37c14f230]));
1009    //     tmp.sub_assign(&Fs(FsRepr::from(0)));
1010    //     assert_eq!(tmp, Fs(FsRepr([0x361e16aef5cce835, 0x55bbde2536e274c1, 0x4dc77a63fd15ee75, 0x1e14bb37c14f230])));
1011    // }
1012
1013    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1014
1015    for _ in 0..1000 {
1016        // Ensure that (a - b) + (b - a) = 0.
1017        let a = Fs::rand(&mut rng);
1018        let b = Fs::rand(&mut rng);
1019
1020        let mut tmp1 = a;
1021        tmp1.sub_assign(&b);
1022
1023        let mut tmp2 = b;
1024        tmp2.sub_assign(&a);
1025
1026        tmp1.add_assign(&tmp2);
1027        assert!(tmp1.is_zero());
1028    }
1029}
1030
1031#[test]
1032fn test_fs_mul_assign() {
1033    // let mut tmp = Fs(FsRepr([0xb433b01287f71744, 0x4eafb86728c4d108, 0xfdd52c14b9dfbe65, 0x2ff1f3434821118]));
1034    // tmp.mul_assign(&Fs(FsRepr([0xdae00fc63c9fa90f, 0x5a5ed89b96ce21ce, 0x913cd26101bd6f58, 0x3f0822831697fe9])));
1035    // assert!(tmp == Fs(FsRepr([0xb68ecb61d54d2992, 0x5ff95874defce6a6, 0x3590eb053894657d, 0x53823a118515933])));
1036
1037    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1038
1039    for _ in 0..1000000 {
1040        // Ensure that (a * b) * c = a * (b * c)
1041        let a = Fs::rand(&mut rng);
1042        let b = Fs::rand(&mut rng);
1043        let c = Fs::rand(&mut rng);
1044
1045        let mut tmp1 = a;
1046        tmp1.mul_assign(&b);
1047        tmp1.mul_assign(&c);
1048
1049        let mut tmp2 = b;
1050        tmp2.mul_assign(&c);
1051        tmp2.mul_assign(&a);
1052
1053        assert_eq!(tmp1, tmp2);
1054    }
1055
1056    for _ in 0..1000000 {
1057        // Ensure that r * (a + b + c) = r*a + r*b + r*c
1058
1059        let r = Fs::rand(&mut rng);
1060        let mut a = Fs::rand(&mut rng);
1061        let mut b = Fs::rand(&mut rng);
1062        let mut c = Fs::rand(&mut rng);
1063
1064        let mut tmp1 = a;
1065        tmp1.add_assign(&b);
1066        tmp1.add_assign(&c);
1067        tmp1.mul_assign(&r);
1068
1069        a.mul_assign(&r);
1070        b.mul_assign(&r);
1071        c.mul_assign(&r);
1072
1073        a.add_assign(&b);
1074        a.add_assign(&c);
1075
1076        assert_eq!(tmp1, a);
1077    }
1078}
1079
1080#[test]
1081fn test_fr_squaring() {
1082    // let mut a = Fs(FsRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xe7db4ea6533afa8]));
1083    // assert!(a.is_valid());
1084    // a.square();
1085    // assert_eq!(a, Fs::from_repr(FsRepr([0x12c7f55cbc52fbaa, 0xdedc98a0b5e6ce9e, 0xad2892726a5396a, 0x9fe82af8fee77b3])).unwrap());
1086
1087    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1088
1089    for _ in 0..1000000 {
1090        // Ensure that (a * a) = a^2
1091        let a = Fs::rand(&mut rng);
1092
1093        let mut tmp = a;
1094        tmp.square();
1095
1096        let mut tmp2 = a;
1097        tmp2.mul_assign(&a);
1098
1099        assert_eq!(tmp, tmp2);
1100    }
1101}
1102
1103#[test]
1104fn test_fs_inverse() {
1105    assert!(Fs::zero().inverse().is_none());
1106
1107    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1108
1109    let one = Fs::one();
1110
1111    for _ in 0..1000 {
1112        // Ensure that a * a^-1 = 1
1113        let mut a = Fs::rand(&mut rng);
1114        let ainv = a.inverse().unwrap();
1115        a.mul_assign(&ainv);
1116        assert_eq!(a, one);
1117    }
1118}
1119
1120#[test]
1121fn test_fs_double() {
1122    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1123
1124    for _ in 0..1000 {
1125        // Ensure doubling a is equivalent to adding a to itself.
1126        let mut a = Fs::rand(&mut rng);
1127        let mut b = a;
1128        b.add_assign(&a);
1129        a.double();
1130        assert_eq!(a, b);
1131    }
1132}
1133
1134#[test]
1135fn test_fs_negate() {
1136    {
1137        let mut a = Fs::zero();
1138        a.negate();
1139
1140        assert!(a.is_zero());
1141    }
1142
1143    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1144
1145    for _ in 0..1000 {
1146        // Ensure (a - (-a)) = 0.
1147        let mut a = Fs::rand(&mut rng);
1148        let mut b = a;
1149        b.negate();
1150        a.add_assign(&b);
1151
1152        assert!(a.is_zero());
1153    }
1154}
1155
1156#[test]
1157fn test_fs_pow() {
1158    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1159
1160    for i in 0..1000 {
1161        // Exponentiate by various small numbers and ensure it consists with repeated
1162        // multiplication.
1163        let a = Fs::rand(&mut rng);
1164        let target = a.pow(&[i]);
1165        let mut c = Fs::one();
1166        for _ in 0..i {
1167            c.mul_assign(&a);
1168        }
1169        assert_eq!(c, target);
1170    }
1171
1172    for _ in 0..1000 {
1173        // Exponentiating by the modulus should have no effect in a prime field.
1174        let a = Fs::rand(&mut rng);
1175
1176        assert_eq!(a, a.pow(Fs::char()));
1177    }
1178}
1179
1180#[test]
1181fn test_fs_sqrt() {
1182    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1183
1184    assert_eq!(Fs::zero().sqrt().unwrap(), Fs::zero());
1185
1186    for _ in 0..1000 {
1187        // Ensure sqrt(a^2) = a or -a
1188        let a = Fs::rand(&mut rng);
1189        let mut nega = a;
1190        nega.negate();
1191        let mut b = a;
1192        b.square();
1193
1194        let b = b.sqrt().unwrap();
1195
1196        assert!(a == b || nega == b);
1197    }
1198
1199    for _ in 0..1000 {
1200        // Ensure sqrt(a)^2 = a for random a
1201        let a = Fs::rand(&mut rng);
1202
1203        if let Some(mut tmp) = a.sqrt() {
1204            tmp.square();
1205
1206            assert_eq!(a, tmp);
1207        }
1208    }
1209}
1210
1211#[test]
1212fn test_fs_from_into_repr() {
1213    // r + 1 should not be in the field
1214    assert!(Fs::from_repr(FsRepr([0xd0970e5ed6f72cb8, 0xa6682093ccc81082, 0x6673b0101343b00, 0xe7db4ea6533afa9])).is_err());
1215
1216    // r should not be in the field
1217    assert!(Fs::from_repr(Fs::char()).is_err());
1218
1219    // Multiply some arbitrary representations to see if the result is as expected.
1220    let a = FsRepr([0x5f2d0c05d0337b71, 0xa1df2b0f8a20479, 0xad73785e71bb863, 0x504a00480c9acec]);
1221    let mut a_fs = Fs::from_repr(a).unwrap();
1222    let b = FsRepr([0x66356ff51e477562, 0x60a92ab55cf7603, 0x8e4273c7364dd192, 0x36df8844a344dc5]);
1223    let b_fs = Fs::from_repr(b).unwrap();
1224    let c = FsRepr([0x7eef61708f4f2868, 0x747a7e6cf52946fb, 0x83dd75d7c9120017, 0x762f5177f0f3df7]);
1225    a_fs.mul_assign(&b_fs);
1226    assert_eq!(a_fs.into_repr(), c);
1227
1228    // Zero should be in the field.
1229    assert!(Fs::from_repr(FsRepr::from(0)).unwrap().is_zero());
1230
1231    let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1232
1233    for _ in 0..1000 {
1234        // Try to turn Fs elements into representations and back again, and compare.
1235        let a = Fs::rand(&mut rng);
1236        let a_repr = a.into_repr();
1237        let b_repr = FsRepr::from(a);
1238        assert_eq!(a_repr, b_repr);
1239        let a_again = Fs::from_repr(a_repr).unwrap();
1240
1241        assert_eq!(a, a_again);
1242    }
1243}
1244
1245#[test]
1246fn test_fs_repr_display() {
1247    assert_eq!(
1248        format!("{}", FsRepr([0xa296db59787359df, 0x8d3e33077430d318, 0xd1abf5c606102eb7, 0xcbc33ee28108f0])),
1249        "0x00cbc33ee28108f0d1abf5c606102eb78d3e33077430d318a296db59787359df".to_string()
1250    );
1251    assert_eq!(
1252        format!("{}", FsRepr([0x14cb03535054a620, 0x312aa2bf2d1dff52, 0x970fe98746ab9361, 0xc1e18acf82711e6])),
1253        "0x0c1e18acf82711e6970fe98746ab9361312aa2bf2d1dff5214cb03535054a620".to_string()
1254    );
1255    assert_eq!(
1256        format!("{}", FsRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])),
1257        "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string()
1258    );
1259    assert_eq!(
1260        format!("{}", FsRepr([0, 0, 0, 0])),
1261        "0x0000000000000000000000000000000000000000000000000000000000000000".to_string()
1262    );
1263}
1264
1265#[test]
1266fn test_fs_display() {
1267    assert_eq!(
1268        format!("{}", Fs::from_repr(FsRepr([0x5528efb9998a01a3, 0x5bd2add5cb357089, 0xc061fa6adb491f98, 0x70db9d143db03d9])).unwrap()),
1269        "Fs(0x070db9d143db03d9c061fa6adb491f985bd2add5cb3570895528efb9998a01a3)".to_string()
1270    );
1271    assert_eq!(
1272        format!("{}", Fs::from_repr(FsRepr([0xd674745e2717999e, 0xbeb1f52d3e96f338, 0x9c7ae147549482b9, 0x999706024530d22])).unwrap()),
1273        "Fs(0x0999706024530d229c7ae147549482b9beb1f52d3e96f338d674745e2717999e)".to_string()
1274    );
1275}
1276
1277#[test]
1278fn test_fs_num_bits() {
1279    assert_eq!(Fs::NUM_BITS, 251);
1280    assert_eq!(Fs::CAPACITY, 250);
1281}
1282
1283#[test]
1284fn test_fs_root_of_unity() {
1285    // assert_eq!(Fs::S, 1);
1286    assert_eq!(Fs::multiplicative_generator(), Fs::from_repr(FsRepr::from(7)).unwrap());
1287    assert_eq!(
1288        Fs::multiplicative_generator().pow([
1289            0xa677297dc392126f,
1290            0xbab3eedb83920ee0,
1291            0x5370a08b6d0302b0,
1292            0x0060c89ce5c26340,
1293        ]),
1294        Fs::root_of_unity()
1295    );
1296    assert_eq!(
1297        Fs::root_of_unity().pow([1 << Fs::S]),
1298        Fs::one()
1299    );
1300    assert!(Fs::multiplicative_generator().sqrt().is_none());
1301}