pairing_plus/bls12_381/
fr.rs

1use digest::generic_array::{typenum::U48, GenericArray};
2use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
3use hash_to_field::BaseFromRO;
4use std::io::{Cursor, Read};
5
6#[derive(PrimeField, Zeroize)]
7#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
8#[PrimeFieldGenerator = "7"]
9pub struct Fr(FrRepr);
10
11/// set the default value for Fr to 0
12impl ::std::default::Default for Fr {
13    fn default() -> Self {
14        Fr::zero()
15    }
16}
17
18/// # Safety
19pub const unsafe fn transmute(r: FrRepr) -> Fr {
20    Fr(r)
21}
22
23impl BaseFromRO for Fr {
24    type BaseLength = U48;
25
26    fn from_okm(okm: &GenericArray<u8, U48>) -> Fr {
27        const F_2_192: Fr = Fr(FrRepr([
28            0x59476ebc41b4528fu64,
29            0xc5a30cb243fcc152u64,
30            0x2b34e63940ccbd72u64,
31            0x1e179025ca247088u64,
32        ]));
33
34        // unwraps are safe here: we only use 24 bytes at a time, which is strictly less than p
35        let mut repr = FrRepr::default();
36        repr.read_be(Cursor::new([0; 8]).chain(Cursor::new(&okm[..24])))
37            .unwrap();
38        let mut elm = Fr::from_repr(repr).unwrap();
39        elm.mul_assign(&F_2_192);
40
41        repr.read_be(Cursor::new([0; 8]).chain(Cursor::new(&okm[24..])))
42            .unwrap();
43        elm.add_assign(&Fr::from_repr(repr).unwrap());
44        elm
45    }
46}
47
48#[cfg(test)]
49use rand_core::SeedableRng;
50
51#[test]
52fn test_fr_repr_ordering() {
53    fn assert_equality(a: FrRepr, b: FrRepr) {
54        assert_eq!(a, b);
55        assert!(a.cmp(&b) == ::std::cmp::Ordering::Equal);
56    }
57
58    fn assert_lt(a: FrRepr, b: FrRepr) {
59        assert!(a < b);
60        assert!(b > a);
61    }
62
63    assert_equality(
64        FrRepr([9999, 9999, 9999, 9999]),
65        FrRepr([9999, 9999, 9999, 9999]),
66    );
67    assert_equality(
68        FrRepr([9999, 9998, 9999, 9999]),
69        FrRepr([9999, 9998, 9999, 9999]),
70    );
71    assert_equality(
72        FrRepr([9999, 9999, 9999, 9997]),
73        FrRepr([9999, 9999, 9999, 9997]),
74    );
75    assert_lt(
76        FrRepr([9999, 9997, 9999, 9998]),
77        FrRepr([9999, 9997, 9999, 9999]),
78    );
79    assert_lt(
80        FrRepr([9999, 9997, 9998, 9999]),
81        FrRepr([9999, 9997, 9999, 9999]),
82    );
83    assert_lt(
84        FrRepr([9, 9999, 9999, 9997]),
85        FrRepr([9999, 9999, 9999, 9997]),
86    );
87}
88
89#[test]
90fn test_fr_repr_from() {
91    assert_eq!(FrRepr::from(100), FrRepr([100, 0, 0, 0]));
92}
93
94#[test]
95fn test_fr_repr_is_odd() {
96    assert!(!FrRepr::from(0).is_odd());
97    assert!(FrRepr::from(0).is_even());
98    assert!(FrRepr::from(1).is_odd());
99    assert!(!FrRepr::from(1).is_even());
100    assert!(!FrRepr::from(324834872).is_odd());
101    assert!(FrRepr::from(324834872).is_even());
102    assert!(FrRepr::from(324834873).is_odd());
103    assert!(!FrRepr::from(324834873).is_even());
104}
105
106#[test]
107fn test_fr_repr_is_zero() {
108    assert!(FrRepr::from(0).is_zero());
109    assert!(!FrRepr::from(1).is_zero());
110    assert!(!FrRepr([0, 0, 1, 0]).is_zero());
111}
112
113#[test]
114fn test_fr_repr_div2() {
115    let mut a = FrRepr([
116        0xbd2920b19c972321,
117        0x174ed0466a3be37e,
118        0xd468d5e3b551f0b5,
119        0xcb67c072733beefc,
120    ]);
121    a.div2();
122    assert_eq!(
123        a,
124        FrRepr([
125            0x5e949058ce4b9190,
126            0x8ba76823351df1bf,
127            0x6a346af1daa8f85a,
128            0x65b3e039399df77e
129        ])
130    );
131    for _ in 0..10 {
132        a.div2();
133    }
134    assert_eq!(
135        a,
136        FrRepr([
137            0x6fd7a524163392e4,
138            0x16a2e9da08cd477c,
139            0xdf9a8d1abc76aa3e,
140            0x196cf80e4e677d
141        ])
142    );
143    for _ in 0..200 {
144        a.div2();
145    }
146    assert_eq!(a, FrRepr([0x196cf80e4e67, 0x0, 0x0, 0x0]));
147    for _ in 0..40 {
148        a.div2();
149    }
150    assert_eq!(a, FrRepr([0x19, 0x0, 0x0, 0x0]));
151    for _ in 0..4 {
152        a.div2();
153    }
154    assert_eq!(a, FrRepr([0x1, 0x0, 0x0, 0x0]));
155    a.div2();
156    assert!(a.is_zero());
157}
158
159#[test]
160fn test_fr_repr_shr() {
161    let mut a = FrRepr([
162        0xb33fbaec482a283f,
163        0x997de0d3a88cb3df,
164        0x9af62d2a9a0e5525,
165        0x36003ab08de70da1,
166    ]);
167    a.shr(0);
168    assert_eq!(
169        a,
170        FrRepr([
171            0xb33fbaec482a283f,
172            0x997de0d3a88cb3df,
173            0x9af62d2a9a0e5525,
174            0x36003ab08de70da1
175        ])
176    );
177    a.shr(1);
178    assert_eq!(
179        a,
180        FrRepr([
181            0xd99fdd762415141f,
182            0xccbef069d44659ef,
183            0xcd7b16954d072a92,
184            0x1b001d5846f386d0
185        ])
186    );
187    a.shr(50);
188    assert_eq!(
189        a,
190        FrRepr([
191            0xbc1a7511967bf667,
192            0xc5a55341caa4b32f,
193            0x75611bce1b4335e,
194            0x6c0
195        ])
196    );
197    a.shr(130);
198    assert_eq!(a, FrRepr([0x1d5846f386d0cd7, 0x1b0, 0x0, 0x0]));
199    a.shr(64);
200    assert_eq!(a, FrRepr([0x1b0, 0x0, 0x0, 0x0]));
201}
202
203#[test]
204fn test_fr_repr_mul2() {
205    let mut a = FrRepr::from(23712937547);
206    a.mul2();
207    assert_eq!(a, FrRepr([0xb0acd6c96, 0x0, 0x0, 0x0]));
208    for _ in 0..60 {
209        a.mul2();
210    }
211    assert_eq!(a, FrRepr([0x6000000000000000, 0xb0acd6c9, 0x0, 0x0]));
212    for _ in 0..128 {
213        a.mul2();
214    }
215    assert_eq!(a, FrRepr([0x0, 0x0, 0x6000000000000000, 0xb0acd6c9]));
216    for _ in 0..60 {
217        a.mul2();
218    }
219    assert_eq!(a, FrRepr([0x0, 0x0, 0x0, 0x9600000000000000]));
220    for _ in 0..7 {
221        a.mul2();
222    }
223    assert!(a.is_zero());
224}
225
226#[test]
227fn test_fr_repr_num_bits() {
228    let mut a = FrRepr::from(0);
229    assert_eq!(0, a.num_bits());
230    a = FrRepr::from(1);
231    for i in 1..257 {
232        assert_eq!(i, a.num_bits());
233        a.mul2();
234    }
235    assert_eq!(0, a.num_bits());
236}
237
238#[test]
239fn test_fr_repr_sub_noborrow() {
240    let mut rng = rand_xorshift::XorShiftRng::from_seed([
241        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
242        0xe5,
243    ]);
244    let mut t = FrRepr([
245        0x8e62a7e85264e2c3,
246        0xb23d34c1941d3ca,
247        0x5976930b7502dd15,
248        0x600f3fb517bf5495,
249    ]);
250    t.sub_noborrow(&FrRepr([
251        0xd64f669809cbc6a4,
252        0xfa76cb9d90cf7637,
253        0xfefb0df9038d43b3,
254        0x298a30c744b31acf,
255    ]));
256    assert!(
257        t == FrRepr([
258            0xb813415048991c1f,
259            0x10ad07ae88725d92,
260            0x5a7b851271759961,
261            0x36850eedd30c39c5
262        ])
263    );
264
265    for _ in 0..1000 {
266        let mut a = Fr::random(&mut rng).into_repr();
267        a.0[3] >>= 30;
268        let mut b = a;
269        for _ in 0..10 {
270            b.mul2();
271        }
272        let mut c = b;
273        for _ in 0..10 {
274            c.mul2();
275        }
276
277        assert!(a < b);
278        assert!(b < c);
279
280        let mut csub_ba = c;
281        csub_ba.sub_noborrow(&b);
282        csub_ba.sub_noborrow(&a);
283
284        let mut csub_ab = c;
285        csub_ab.sub_noborrow(&a);
286        csub_ab.sub_noborrow(&b);
287
288        assert_eq!(csub_ab, csub_ba);
289    }
290
291    // Subtracting r+1 from r should produce -1 (mod 2**256)
292    let mut qplusone = FrRepr([
293        0xffffffff00000001,
294        0x53bda402fffe5bfe,
295        0x3339d80809a1d805,
296        0x73eda753299d7d48,
297    ]);
298    qplusone.sub_noborrow(&FrRepr([
299        0xffffffff00000002,
300        0x53bda402fffe5bfe,
301        0x3339d80809a1d805,
302        0x73eda753299d7d48,
303    ]));
304    assert_eq!(
305        qplusone,
306        FrRepr([
307            0xffffffffffffffff,
308            0xffffffffffffffff,
309            0xffffffffffffffff,
310            0xffffffffffffffff
311        ])
312    );
313}
314
315#[test]
316fn test_fr_legendre() {
317    use ff::LegendreSymbol::*;
318    use ff::SqrtField;
319
320    assert_eq!(QuadraticResidue, Fr::one().legendre());
321    assert_eq!(Zero, Fr::zero().legendre());
322
323    let e = FrRepr([
324        0x0dbc5349cd5664da,
325        0x8ac5b6296e3ae29d,
326        0x127cb819feceaa3b,
327        0x3a6b21fb03867191,
328    ]);
329    assert_eq!(QuadraticResidue, Fr::from_repr(e).unwrap().legendre());
330    let e = FrRepr([
331        0x96341aefd047c045,
332        0x9b5f4254500a4d65,
333        0x1ee08223b68ac240,
334        0x31d9cd545c0ec7c6,
335    ]);
336    assert_eq!(QuadraticNonResidue, Fr::from_repr(e).unwrap().legendre());
337}
338
339#[test]
340fn test_fr_repr_add_nocarry() {
341    let mut rng = rand_xorshift::XorShiftRng::from_seed([
342        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
343        0xe5,
344    ]);
345    let mut t = FrRepr([
346        0xd64f669809cbc6a4,
347        0xfa76cb9d90cf7637,
348        0xfefb0df9038d43b3,
349        0x298a30c744b31acf,
350    ]);
351    t.add_nocarry(&FrRepr([
352        0x8e62a7e85264e2c3,
353        0xb23d34c1941d3ca,
354        0x5976930b7502dd15,
355        0x600f3fb517bf5495,
356    ]));
357    assert_eq!(
358        t,
359        FrRepr([
360            0x64b20e805c30a967,
361            0x59a9ee9aa114a02,
362            0x5871a104789020c9,
363            0x8999707c5c726f65
364        ])
365    );
366
367    // Test for the associativity of addition.
368    for _ in 0..1000 {
369        let mut a = Fr::random(&mut rng).into_repr();
370        let mut b = Fr::random(&mut rng).into_repr();
371        let mut c = Fr::random(&mut rng).into_repr();
372
373        // Unset the first few bits, so that overflow won't occur.
374        a.0[3] >>= 3;
375        b.0[3] >>= 3;
376        c.0[3] >>= 3;
377
378        let mut abc = a;
379        abc.add_nocarry(&b);
380        abc.add_nocarry(&c);
381
382        let mut acb = a;
383        acb.add_nocarry(&c);
384        acb.add_nocarry(&b);
385
386        let mut bac = b;
387        bac.add_nocarry(&a);
388        bac.add_nocarry(&c);
389
390        let mut bca = b;
391        bca.add_nocarry(&c);
392        bca.add_nocarry(&a);
393
394        let mut cab = c;
395        cab.add_nocarry(&a);
396        cab.add_nocarry(&b);
397
398        let mut cba = c;
399        cba.add_nocarry(&b);
400        cba.add_nocarry(&a);
401
402        assert_eq!(abc, acb);
403        assert_eq!(abc, bac);
404        assert_eq!(abc, bca);
405        assert_eq!(abc, cab);
406        assert_eq!(abc, cba);
407    }
408
409    // Adding 1 to (2^256 - 1) should produce zero
410    let mut x = FrRepr([
411        0xffffffffffffffff,
412        0xffffffffffffffff,
413        0xffffffffffffffff,
414        0xffffffffffffffff,
415    ]);
416    x.add_nocarry(&FrRepr::from(1));
417    assert!(x.is_zero());
418}
419
420#[test]
421fn test_fr_is_valid() {
422    let mut a = Fr(MODULUS);
423    assert!(!a.is_valid());
424    a.0.sub_noborrow(&FrRepr::from(1));
425    assert!(a.is_valid());
426    assert!(Fr(FrRepr::from(0)).is_valid());
427    assert!(Fr(FrRepr([
428        0xffffffff00000000,
429        0x53bda402fffe5bfe,
430        0x3339d80809a1d805,
431        0x73eda753299d7d48
432    ]))
433    .is_valid());
434    assert!(!Fr(FrRepr([
435        0xffffffffffffffff,
436        0xffffffffffffffff,
437        0xffffffffffffffff,
438        0xffffffffffffffff
439    ]))
440    .is_valid());
441
442    let mut rng = rand_xorshift::XorShiftRng::from_seed([
443        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
444        0xe5,
445    ]);
446    for _ in 0..1000 {
447        let a = Fr::random(&mut rng);
448        assert!(a.is_valid());
449    }
450}
451
452#[test]
453fn test_fr_add_assign() {
454    {
455        // Random number
456        let mut tmp = Fr(FrRepr([
457            0x437ce7616d580765,
458            0xd42d1ccb29d1235b,
459            0xed8f753821bd1423,
460            0x4eede1c9c89528ca,
461        ]));
462        assert!(tmp.is_valid());
463        // Test that adding zero has no effect.
464        tmp.add_assign(&Fr(FrRepr::from(0)));
465        assert_eq!(
466            tmp,
467            Fr(FrRepr([
468                0x437ce7616d580765,
469                0xd42d1ccb29d1235b,
470                0xed8f753821bd1423,
471                0x4eede1c9c89528ca
472            ]))
473        );
474        // Add one and test for the result.
475        tmp.add_assign(&Fr(FrRepr::from(1)));
476        assert_eq!(
477            tmp,
478            Fr(FrRepr([
479                0x437ce7616d580766,
480                0xd42d1ccb29d1235b,
481                0xed8f753821bd1423,
482                0x4eede1c9c89528ca
483            ]))
484        );
485        // Add another random number that exercises the reduction.
486        tmp.add_assign(&Fr(FrRepr([
487            0x946f435944f7dc79,
488            0xb55e7ee6533a9b9b,
489            0x1e43b84c2f6194ca,
490            0x58717ab525463496,
491        ])));
492        assert_eq!(
493            tmp,
494            Fr(FrRepr([
495                0xd7ec2abbb24fe3de,
496                0x35cdf7ae7d0d62f7,
497                0xd899557c477cd0e9,
498                0x3371b52bc43de018
499            ]))
500        );
501        // Add one to (r - 1) and test for the result.
502        tmp = Fr(FrRepr([
503            0xffffffff00000000,
504            0x53bda402fffe5bfe,
505            0x3339d80809a1d805,
506            0x73eda753299d7d48,
507        ]));
508        tmp.add_assign(&Fr(FrRepr::from(1)));
509        assert!(tmp.0.is_zero());
510        // Add a random number to another one such that the result is r - 1
511        tmp = Fr(FrRepr([
512            0xade5adacdccb6190,
513            0xaa21ee0f27db3ccd,
514            0x2550f4704ae39086,
515            0x591d1902e7c5ba27,
516        ]));
517        tmp.add_assign(&Fr(FrRepr([
518            0x521a525223349e70,
519            0xa99bb5f3d8231f31,
520            0xde8e397bebe477e,
521            0x1ad08e5041d7c321,
522        ])));
523        assert_eq!(
524            tmp,
525            Fr(FrRepr([
526                0xffffffff00000000,
527                0x53bda402fffe5bfe,
528                0x3339d80809a1d805,
529                0x73eda753299d7d48
530            ]))
531        );
532        // Add one to the result and test for it.
533        tmp.add_assign(&Fr(FrRepr::from(1)));
534        assert!(tmp.0.is_zero());
535    }
536
537    // Test associativity
538    let mut rng = rand_xorshift::XorShiftRng::from_seed([
539        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
540        0xe5,
541    ]);
542    for _ in 0..1000 {
543        // Generate a, b, c and ensure (a + b) + c == a + (b + c).
544        let a = Fr::random(&mut rng);
545        let b = Fr::random(&mut rng);
546        let c = Fr::random(&mut rng);
547
548        let mut tmp1 = a;
549        tmp1.add_assign(&b);
550        tmp1.add_assign(&c);
551
552        let mut tmp2 = b;
553        tmp2.add_assign(&c);
554        tmp2.add_assign(&a);
555
556        assert!(tmp1.is_valid());
557        assert!(tmp2.is_valid());
558        assert_eq!(tmp1, tmp2);
559    }
560}
561
562#[test]
563fn test_fr_sub_assign() {
564    {
565        // Test arbitrary subtraction that tests reduction.
566        let mut tmp = Fr(FrRepr([
567            0x6a68c64b6f735a2b,
568            0xd5f4d143fe0a1972,
569            0x37c17f3829267c62,
570            0xa2f37391f30915c,
571        ]));
572        tmp.sub_assign(&Fr(FrRepr([
573            0xade5adacdccb6190,
574            0xaa21ee0f27db3ccd,
575            0x2550f4704ae39086,
576            0x591d1902e7c5ba27,
577        ])));
578        assert_eq!(
579            tmp,
580            Fr(FrRepr([
581                0xbc83189d92a7f89c,
582                0x7f908737d62d38a3,
583                0x45aa62cfe7e4c3e1,
584                0x24ffc5896108547d
585            ]))
586        );
587
588        // Test the opposite subtraction which doesn't test reduction.
589        tmp = Fr(FrRepr([
590            0xade5adacdccb6190,
591            0xaa21ee0f27db3ccd,
592            0x2550f4704ae39086,
593            0x591d1902e7c5ba27,
594        ]));
595        tmp.sub_assign(&Fr(FrRepr([
596            0x6a68c64b6f735a2b,
597            0xd5f4d143fe0a1972,
598            0x37c17f3829267c62,
599            0xa2f37391f30915c,
600        ])));
601        assert_eq!(
602            tmp,
603            Fr(FrRepr([
604                0x437ce7616d580765,
605                0xd42d1ccb29d1235b,
606                0xed8f753821bd1423,
607                0x4eede1c9c89528ca
608            ]))
609        );
610
611        // Test for sensible results with zero
612        tmp = Fr(FrRepr::from(0));
613        tmp.sub_assign(&Fr(FrRepr::from(0)));
614        assert!(tmp.is_zero());
615
616        tmp = Fr(FrRepr([
617            0x437ce7616d580765,
618            0xd42d1ccb29d1235b,
619            0xed8f753821bd1423,
620            0x4eede1c9c89528ca,
621        ]));
622        tmp.sub_assign(&Fr(FrRepr::from(0)));
623        assert_eq!(
624            tmp,
625            Fr(FrRepr([
626                0x437ce7616d580765,
627                0xd42d1ccb29d1235b,
628                0xed8f753821bd1423,
629                0x4eede1c9c89528ca
630            ]))
631        );
632    }
633
634    let mut rng = rand_xorshift::XorShiftRng::from_seed([
635        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
636        0xe5,
637    ]);
638    for _ in 0..1000 {
639        // Ensure that (a - b) + (b - a) = 0.
640        let a = Fr::random(&mut rng);
641        let b = Fr::random(&mut rng);
642
643        let mut tmp1 = a;
644        tmp1.sub_assign(&b);
645
646        let mut tmp2 = b;
647        tmp2.sub_assign(&a);
648
649        tmp1.add_assign(&tmp2);
650        assert!(tmp1.is_zero());
651    }
652}
653
654#[test]
655fn test_fr_mul_assign() {
656    let mut tmp = Fr(FrRepr([
657        0x6b7e9b8faeefc81a,
658        0xe30a8463f348ba42,
659        0xeff3cb67a8279c9c,
660        0x3d303651bd7c774d,
661    ]));
662    tmp.mul_assign(&Fr(FrRepr([
663        0x13ae28e3bc35ebeb,
664        0xa10f4488075cae2c,
665        0x8160e95a853c3b5d,
666        0x5ae3f03b561a841d,
667    ])));
668    assert!(
669        tmp == Fr(FrRepr([
670            0x23717213ce710f71,
671            0xdbee1fe53a16e1af,
672            0xf565d3e1c2a48000,
673            0x4426507ee75df9d7
674        ]))
675    );
676
677    let mut rng = rand_xorshift::XorShiftRng::from_seed([
678        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
679        0xe5,
680    ]);
681    for _ in 0..1000000 {
682        // Ensure that (a * b) * c = a * (b * c)
683        let a = Fr::random(&mut rng);
684        let b = Fr::random(&mut rng);
685        let c = Fr::random(&mut rng);
686
687        let mut tmp1 = a;
688        tmp1.mul_assign(&b);
689        tmp1.mul_assign(&c);
690
691        let mut tmp2 = b;
692        tmp2.mul_assign(&c);
693        tmp2.mul_assign(&a);
694
695        assert_eq!(tmp1, tmp2);
696    }
697
698    for _ in 0..1000000 {
699        // Ensure that r * (a + b + c) = r*a + r*b + r*c
700
701        let r = Fr::random(&mut rng);
702        let mut a = Fr::random(&mut rng);
703        let mut b = Fr::random(&mut rng);
704        let mut c = Fr::random(&mut rng);
705
706        let mut tmp1 = a;
707        tmp1.add_assign(&b);
708        tmp1.add_assign(&c);
709        tmp1.mul_assign(&r);
710
711        a.mul_assign(&r);
712        b.mul_assign(&r);
713        c.mul_assign(&r);
714
715        a.add_assign(&b);
716        a.add_assign(&c);
717
718        assert_eq!(tmp1, a);
719    }
720}
721
722#[test]
723fn test_fr_squaring() {
724    let mut a = Fr(FrRepr([
725        0xffffffffffffffff,
726        0xffffffffffffffff,
727        0xffffffffffffffff,
728        0x73eda753299d7d47,
729    ]));
730    assert!(a.is_valid());
731    a.square();
732    assert_eq!(
733        a,
734        Fr::from_repr(FrRepr([
735            0xc0d698e7bde077b8,
736            0xb79a310579e76ec2,
737            0xac1da8d0a9af4e5f,
738            0x13f629c49bf23e97
739        ]))
740        .unwrap()
741    );
742
743    let mut rng = rand_xorshift::XorShiftRng::from_seed([
744        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
745        0xe5,
746    ]);
747    for _ in 0..1000000 {
748        // Ensure that (a * a) = a^2
749        let a = Fr::random(&mut rng);
750
751        let mut tmp = a;
752        tmp.square();
753
754        let mut tmp2 = a;
755        tmp2.mul_assign(&a);
756
757        assert_eq!(tmp, tmp2);
758    }
759}
760
761#[test]
762fn test_fr_inverse() {
763    assert!(Fr::zero().inverse().is_none());
764    let mut rng = rand_xorshift::XorShiftRng::from_seed([
765        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
766        0xe5,
767    ]);
768    let one = Fr::one();
769
770    for _ in 0..1000 {
771        // Ensure that a * a^-1 = 1
772        let mut a = Fr::random(&mut rng);
773        let ainv = a.inverse().unwrap();
774        a.mul_assign(&ainv);
775        assert_eq!(a, one);
776    }
777}
778
779#[test]
780fn test_fr_double() {
781    let mut rng = rand_xorshift::XorShiftRng::from_seed([
782        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
783        0xe5,
784    ]);
785    for _ in 0..1000 {
786        // Ensure doubling a is equivalent to adding a to itself.
787        let mut a = Fr::random(&mut rng);
788        let mut b = a;
789        b.add_assign(&a);
790        a.double();
791        assert_eq!(a, b);
792    }
793}
794
795#[test]
796fn test_fr_negate() {
797    {
798        let mut a = Fr::zero();
799        a.negate();
800
801        assert!(a.is_zero());
802    }
803    let mut rng = rand_xorshift::XorShiftRng::from_seed([
804        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
805        0xe5,
806    ]);
807    for _ in 0..1000 {
808        // Ensure (a - (-a)) = 0.
809        let mut a = Fr::random(&mut rng);
810        let mut b = a;
811        b.negate();
812        a.add_assign(&b);
813
814        assert!(a.is_zero());
815    }
816}
817
818#[test]
819fn test_fr_pow() {
820    let mut rng = rand_xorshift::XorShiftRng::from_seed([
821        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
822        0xe5,
823    ]);
824    for i in 0..1000 {
825        // Exponentiate by various small numbers and ensure it consists with repeated
826        // multiplication.
827        let a = Fr::random(&mut rng);
828        let target = a.pow(&[i]);
829        let mut c = Fr::one();
830        for _ in 0..i {
831            c.mul_assign(&a);
832        }
833        assert_eq!(c, target);
834    }
835
836    for _ in 0..1000 {
837        // Exponentiating by the modulus should have no effect in a prime field.
838        let a = Fr::random(&mut rng);
839
840        assert_eq!(a, a.pow(Fr::char()));
841    }
842}
843
844#[test]
845fn test_fr_sqrt() {
846    use ff::SqrtField;
847    let mut rng = rand_xorshift::XorShiftRng::from_seed([
848        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
849        0xe5,
850    ]);
851    assert_eq!(Fr::zero().sqrt().unwrap(), Fr::zero());
852
853    for _ in 0..1000 {
854        // Ensure sqrt(a^2) = a or -a
855        let a = Fr::random(&mut rng);
856        let mut nega = a;
857        nega.negate();
858        let mut b = a;
859        b.square();
860
861        let b = b.sqrt().unwrap();
862
863        assert!(a == b || nega == b);
864    }
865
866    for _ in 0..1000 {
867        // Ensure sqrt(a)^2 = a for random a
868        let a = Fr::random(&mut rng);
869
870        if let Some(mut tmp) = a.sqrt() {
871            tmp.square();
872
873            assert_eq!(a, tmp);
874        }
875    }
876}
877
878#[test]
879fn test_fr_from_into_repr() {
880    // r + 1 should not be in the field
881    assert!(Fr::from_repr(FrRepr([
882        0xffffffff00000002,
883        0x53bda402fffe5bfe,
884        0x3339d80809a1d805,
885        0x73eda753299d7d48
886    ]))
887    .is_err());
888
889    // r should not be in the field
890    assert!(Fr::from_repr(Fr::char()).is_err());
891
892    // Multiply some arbitrary representations to see if the result is as expected.
893    let a = FrRepr([
894        0x25ebe3a3ad3c0c6a,
895        0x6990e39d092e817c,
896        0x941f900d42f5658e,
897        0x44f8a103b38a71e0,
898    ]);
899    let mut a_fr = Fr::from_repr(a).unwrap();
900    let b = FrRepr([
901        0x264e9454885e2475,
902        0x46f7746bb0308370,
903        0x4683ef5347411f9,
904        0x58838d7f208d4492,
905    ]);
906    let b_fr = Fr::from_repr(b).unwrap();
907    let c = FrRepr([
908        0x48a09ab93cfc740d,
909        0x3a6600fbfc7a671,
910        0x838567017501d767,
911        0x7161d6da77745512,
912    ]);
913    a_fr.mul_assign(&b_fr);
914    assert_eq!(a_fr.into_repr(), c);
915
916    // Zero should be in the field.
917    assert!(Fr::from_repr(FrRepr::from(0)).unwrap().is_zero());
918    let mut rng = rand_xorshift::XorShiftRng::from_seed([
919        0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
920        0xe5,
921    ]);
922    for _ in 0..1000 {
923        // Try to turn Fr elements into representations and back again, and compare.
924        let a = Fr::random(&mut rng);
925        let a_repr = a.into_repr();
926        let b_repr = FrRepr::from(a);
927        assert_eq!(a_repr, b_repr);
928        let a_again = Fr::from_repr(a_repr).unwrap();
929
930        assert_eq!(a, a_again);
931    }
932}
933
934#[test]
935fn test_fr_repr_display() {
936    assert_eq!(
937        format!(
938            "{}",
939            FrRepr([
940                0x2829c242fa826143,
941                0x1f32cf4dd4330917,
942                0x932e4e479d168cd9,
943                0x513c77587f563f64
944            ])
945        ),
946        "0x513c77587f563f64932e4e479d168cd91f32cf4dd43309172829c242fa826143".to_string()
947    );
948    assert_eq!(
949        format!(
950            "{}",
951            FrRepr([
952                0x25ebe3a3ad3c0c6a,
953                0x6990e39d092e817c,
954                0x941f900d42f5658e,
955                0x44f8a103b38a71e0
956            ])
957        ),
958        "0x44f8a103b38a71e0941f900d42f5658e6990e39d092e817c25ebe3a3ad3c0c6a".to_string()
959    );
960    assert_eq!(
961        format!(
962            "{}",
963            FrRepr([
964                0xffffffffffffffff,
965                0xffffffffffffffff,
966                0xffffffffffffffff,
967                0xffffffffffffffff
968            ])
969        ),
970        "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string()
971    );
972    assert_eq!(
973        format!("{}", FrRepr([0, 0, 0, 0])),
974        "0x0000000000000000000000000000000000000000000000000000000000000000".to_string()
975    );
976}
977
978#[test]
979fn test_fr_display() {
980    assert_eq!(
981        format!(
982            "{}",
983            Fr::from_repr(FrRepr([
984                0xc3cae746a3b5ecc7,
985                0x185ec8eb3f5b5aee,
986                0x684499ffe4b9dd99,
987                0x7c9bba7afb68faa
988            ]))
989            .unwrap()
990        ),
991        "Fr(0x07c9bba7afb68faa684499ffe4b9dd99185ec8eb3f5b5aeec3cae746a3b5ecc7)".to_string()
992    );
993    assert_eq!(
994        format!(
995            "{}",
996            Fr::from_repr(FrRepr([
997                0x44c71298ff198106,
998                0xb0ad10817df79b6a,
999                0xd034a80a2b74132b,
1000                0x41cf9a1336f50719
1001            ]))
1002            .unwrap()
1003        ),
1004        "Fr(0x41cf9a1336f50719d034a80a2b74132bb0ad10817df79b6a44c71298ff198106)".to_string()
1005    );
1006}
1007
1008#[test]
1009fn test_fr_num_bits() {
1010    assert_eq!(Fr::NUM_BITS, 255);
1011    assert_eq!(Fr::CAPACITY, 254);
1012}
1013
1014#[test]
1015fn test_fr_root_of_unity() {
1016    use ff::SqrtField;
1017
1018    assert_eq!(Fr::S, 32);
1019    assert_eq!(
1020        Fr::multiplicative_generator(),
1021        Fr::from_repr(FrRepr::from(7)).unwrap()
1022    );
1023    assert_eq!(
1024        Fr::multiplicative_generator().pow([
1025            0xfffe5bfeffffffff,
1026            0x9a1d80553bda402,
1027            0x299d7d483339d808,
1028            0x73eda753
1029        ]),
1030        Fr::root_of_unity()
1031    );
1032    assert_eq!(Fr::root_of_unity().pow([1 << Fr::S]), Fr::one());
1033    assert!(Fr::multiplicative_generator().sqrt().is_none());
1034}
1035
1036#[test]
1037fn fr_field_tests() {
1038    ::tests::field::random_field_tests::<Fr>();
1039    ::tests::field::random_sqrt_tests::<Fr>();
1040    ::tests::field::random_frobenius_tests::<Fr, _>(Fr::char(), 13);
1041    ::tests::field::from_str_tests::<Fr>();
1042}
1043
1044#[test]
1045fn fr_repr_tests() {
1046    ::tests::repr::random_repr_tests::<Fr, FrRepr>();
1047}