pairing_ce/bls12_381/
fr.rs

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