witnet_bn/
arith.rs

1use core::cmp::Ordering;
2use rand::Rng;
3
4use byteorder::{BigEndian, ByteOrder};
5#[cfg(feature = "rustc-serialize")]
6use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
7
8/// 256-bit, stack allocated biginteger for use in prime field
9/// arithmetic.
10#[derive(Copy, Clone, Debug, PartialEq, Eq)]
11#[repr(C)]
12pub struct U256(pub [u128; 2]);
13
14impl From<[u64; 4]> for U256 {
15    fn from(d: [u64; 4]) -> Self {
16        let mut a = [0u128; 2];
17        a[0] = (d[1] as u128) << 64 | d[0] as u128;
18        a[1] = (d[3] as u128) << 64 | d[2] as u128;
19        U256(a)
20    }
21}
22
23impl From<u64> for U256 {
24    fn from(d: u64) -> Self {
25        U256::from([d, 0, 0, 0])
26    }
27}
28
29/// 512-bit, stack allocated biginteger for use in extension
30/// field serialization and scalar interpretation.
31#[derive(Copy, Clone, Debug, PartialEq, Eq)]
32#[repr(C)]
33pub struct U512(pub [u128; 4]);
34
35impl From<[u64; 8]> for U512 {
36    fn from(d: [u64; 8]) -> Self {
37        let mut a = [0u128; 4];
38        a[0] = (d[1] as u128) << 64 | d[0] as u128;
39        a[1] = (d[3] as u128) << 64 | d[2] as u128;
40        a[2] = (d[5] as u128) << 64 | d[4] as u128;
41        a[3] = (d[7] as u128) << 64 | d[6] as u128;
42        U512(a)
43    }
44}
45
46impl U512 {
47    /// Multiplies c1 by modulo, adds c0.
48    pub fn new(c1: &U256, c0: &U256, modulo: &U256) -> U512 {
49        let mut res = [0; 4];
50
51        debug_assert_eq!(c1.0.len(), 2);
52        unroll! {
53            for i in 0..2 {
54                mac_digit(i, &mut res, &modulo.0, c1.0[i]);
55            }
56        }
57
58        let mut carry = 0;
59
60        debug_assert_eq!(res.len(), 4);
61        unroll! {
62            for i in 0..2 {
63                res[i] = adc(res[i], c0.0[i], &mut carry);
64            }
65        }
66
67        unroll! {
68            for i in 0..2 {
69                let (a1, a0) = split_u128(res[i + 2]);
70                let (c, r0) = split_u128(a0 + carry);
71                let (c, r1) = split_u128(a1 + c);
72                carry = c;
73
74                res[i + 2] = combine_u128(r1, r0);
75            }
76        }
77
78        debug_assert!(0 == carry);
79
80        U512(res)
81    }
82
83    pub fn from_slice(s: &[u8]) -> Result<U512, Error> {
84        if s.len() != 64 {
85            return Err(Error::InvalidLength {
86                expected: 32,
87                actual: s.len(),
88            });
89        }
90
91        let mut n = [0; 4];
92        for (l, i) in (0..4).rev().zip((0..4).map(|i| i * 16)) {
93            n[l] = BigEndian::read_u128(&s[i..]);
94        }
95
96        Ok(U512(n))
97    }
98
99    /// Get a random U512
100    pub fn random<R: Rng>(rng: &mut R) -> U512 {
101        U512(rng.random())
102    }
103
104    pub fn get_bit(&self, n: usize) -> Option<bool> {
105        if n >= 512 {
106            None
107        } else {
108            let part = n / 128;
109            let bit = n - (128 * part);
110
111            Some(self.0[part] & (1 << bit) > 0)
112        }
113    }
114
115    /// Divides self by modulo, returning remainder and, if
116    /// possible, a quotient smaller than the modulus.
117    pub fn divrem(&self, modulo: &U256) -> (Option<U256>, U256) {
118        let mut q = Some(U256::zero());
119        let mut r = U256::zero();
120
121        for i in (0..512).rev() {
122            // NB: modulo's first two bits are always unset
123            // so this will never destroy information
124            mul2(&mut r.0);
125            assert!(r.set_bit(0, self.get_bit(i).unwrap()));
126            if &r >= modulo {
127                sub_noborrow(&mut r.0, &modulo.0);
128                if q.is_some() && !q.as_mut().unwrap().set_bit(i, true) {
129                    q = None
130                }
131            }
132        }
133
134        if q.is_some() && (q.as_ref().unwrap() >= modulo) {
135            (None, r)
136        } else {
137            (q, r)
138        }
139    }
140
141    pub fn interpret(buf: &[u8; 64]) -> U512 {
142        let mut n = [0; 4];
143        for (l, i) in (0..4).rev().zip((0..4).map(|i| i * 16)) {
144            n[l] = BigEndian::read_u128(&buf[i..]);
145        }
146
147        U512(n)
148    }
149}
150
151#[cfg(feature = "rustc-serialize")]
152impl Encodable for U512 {
153    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
154        let mut buf = [0; (4 * 16)];
155
156        for (l, i) in (0..4).rev().zip((0..4).map(|i| i * 16)) {
157            BigEndian::write_u128(&mut buf[i..], self.0[l]);
158        }
159
160        for i in 0..(4 * 16) {
161            s.emit_u8(buf[i])?;
162        }
163
164        Ok(())
165    }
166}
167
168#[cfg(feature = "rustc-serialize")]
169impl Decodable for U512 {
170    fn decode<S: Decoder>(s: &mut S) -> Result<U512, S::Error> {
171        let mut buf = [0; (4 * 16)];
172
173        for i in 0..(4 * 16) {
174            buf[i] = s.read_u8()?;
175        }
176
177        Ok(U512::interpret(&buf))
178    }
179}
180
181#[cfg(feature = "rustc-serialize")]
182impl Encodable for U256 {
183    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
184        let mut buf = [0; (2 * 16)];
185
186        for (l, i) in (0..2).rev().zip((0..2).map(|i| i * 16)) {
187            BigEndian::write_u128(&mut buf[i..], self.0[l]);
188        }
189
190        for i in 0..(2 * 16) {
191            s.emit_u8(buf[i])?;
192        }
193
194        Ok(())
195    }
196}
197
198#[cfg(feature = "rustc-serialize")]
199impl Decodable for U256 {
200    fn decode<S: Decoder>(s: &mut S) -> Result<U256, S::Error> {
201        let mut buf = [0; (2 * 16)];
202
203        for i in 0..(2 * 16) {
204            buf[i] = s.read_u8()?;
205        }
206
207        U256::from_slice(&buf).map_err(|_| s.error("Invalid input length; Also unreachable;"))
208    }
209}
210
211impl Ord for U512 {
212    #[inline]
213    fn cmp(&self, other: &U512) -> Ordering {
214        for (a, b) in self.0.iter().zip(other.0.iter()).rev() {
215            if *a < *b {
216                return Ordering::Less;
217            } else if *a > *b {
218                return Ordering::Greater;
219            }
220        }
221
222        Ordering::Equal
223    }
224}
225
226impl PartialOrd for U512 {
227    #[inline]
228    fn partial_cmp(&self, other: &U512) -> Option<Ordering> {
229        Some(self.cmp(other))
230    }
231}
232
233impl Ord for U256 {
234    #[inline]
235    fn cmp(&self, other: &U256) -> Ordering {
236        for (a, b) in self.0.iter().zip(other.0.iter()).rev() {
237            if *a < *b {
238                return Ordering::Less;
239            } else if *a > *b {
240                return Ordering::Greater;
241            }
242        }
243
244        Ordering::Equal
245    }
246}
247
248impl PartialOrd for U256 {
249    #[inline]
250    fn partial_cmp(&self, other: &U256) -> Option<Ordering> {
251        Some(self.cmp(other))
252    }
253}
254
255/// U256/U512 errors
256#[derive(Debug)]
257pub enum Error {
258    InvalidLength { expected: usize, actual: usize },
259}
260
261impl U256 {
262    /// Initialize U256 from slice of bytes (big endian)
263    pub fn from_slice(s: &[u8]) -> Result<U256, Error> {
264        if s.len() != 32 {
265            return Err(Error::InvalidLength {
266                expected: 32,
267                actual: s.len(),
268            });
269        }
270
271        let mut n = [0; 2];
272        for (l, i) in (0..2).rev().zip((0..2).map(|i| i * 16)) {
273            n[l] = BigEndian::read_u128(&s[i..]);
274        }
275
276        Ok(U256(n))
277    }
278
279    pub fn to_big_endian(&self, s: &mut [u8]) -> Result<(), Error> {
280        if s.len() != 32 {
281            return Err(Error::InvalidLength {
282                expected: 32,
283                actual: s.len(),
284            });
285        }
286
287        for (l, i) in (0..2).rev().zip((0..2).map(|i| i * 16)) {
288            BigEndian::write_u128(&mut s[i..], self.0[l]);
289        }
290
291        Ok(())
292    }
293
294    #[inline]
295    pub fn zero() -> U256 {
296        U256([0, 0])
297    }
298
299    #[inline]
300    pub fn one() -> U256 {
301        U256([1, 0])
302    }
303
304    /// Produce a random number (mod `modulo`)
305    pub fn random<R: Rng>(rng: &mut R, modulo: &U256) -> U256 {
306        U512::random(rng).divrem(modulo).1
307    }
308
309    pub fn is_zero(&self) -> bool {
310        self.0[0] == 0 && self.0[1] == 0
311    }
312
313    pub fn set_bit(&mut self, n: usize, to: bool) -> bool {
314        if n >= 256 {
315            false
316        } else {
317            let part = n / 128;
318            let bit = n - (128 * part);
319
320            if to {
321                self.0[part] |= 1 << bit;
322            } else {
323                self.0[part] &= !(1 << bit);
324            }
325
326            true
327        }
328    }
329
330    pub fn get_bit(&self, n: usize) -> Option<bool> {
331        if n >= 256 {
332            None
333        } else {
334            let part = n / 128;
335            let bit = n - (128 * part);
336
337            Some(self.0[part] & (1 << bit) > 0)
338        }
339    }
340
341    /// Add `other` to `self` (mod `modulo`)
342    pub fn add(&mut self, other: &U256, modulo: &U256) {
343        add_nocarry(&mut self.0, &other.0);
344
345        if *self >= *modulo {
346            sub_noborrow(&mut self.0, &modulo.0);
347        }
348    }
349
350    /// Subtract `other` from `self` (mod `modulo`)
351    pub fn sub(&mut self, other: &U256, modulo: &U256) {
352        if *self < *other {
353            add_nocarry(&mut self.0, &modulo.0);
354        }
355
356        sub_noborrow(&mut self.0, &other.0);
357    }
358
359    /// Multiply `self` by `other` (mod `modulo`) via the Montgomery
360    /// multiplication method.
361    pub fn mul(&mut self, other: &U256, modulo: &U256, inv: u128) {
362        mul_reduce(&mut self.0, &other.0, &modulo.0, inv);
363
364        if *self >= *modulo {
365            sub_noborrow(&mut self.0, &modulo.0);
366        }
367    }
368
369    /// Turn `self` into its additive inverse (mod `modulo`)
370    pub fn neg(&mut self, modulo: &U256) {
371        if *self > Self::zero() {
372            let mut tmp = modulo.0;
373            sub_noborrow(&mut tmp, &self.0);
374
375            self.0 = tmp;
376        }
377    }
378
379    #[inline]
380    pub fn is_even(&self) -> bool {
381        self.0[0] & 1 == 0
382    }
383
384    /// Turn `self` into its multiplicative inverse (mod `modulo`)
385    pub fn invert(&mut self, modulo: &U256) {
386        // Guajardo Kumar Paar Pelzl
387        // Efficient Software-Implementation of Finite Fields with Applications to Cryptography
388        // Algorithm 16 (BEA for Inversion in Fp)
389
390        let mut u = *self;
391        let mut v = *modulo;
392        let mut b = U256::one();
393        let mut c = U256::zero();
394
395        while u != U256::one() && v != U256::one() {
396            while u.is_even() {
397                div2(&mut u.0);
398
399                if b.is_even() {
400                    div2(&mut b.0);
401                } else {
402                    add_nocarry(&mut b.0, &modulo.0);
403                    div2(&mut b.0);
404                }
405            }
406            while v.is_even() {
407                div2(&mut v.0);
408
409                if c.is_even() {
410                    div2(&mut c.0);
411                } else {
412                    add_nocarry(&mut c.0, &modulo.0);
413                    div2(&mut c.0);
414                }
415            }
416
417            if u >= v {
418                sub_noborrow(&mut u.0, &v.0);
419                b.sub(&c, modulo);
420            } else {
421                sub_noborrow(&mut v.0, &u.0);
422                c.sub(&b, modulo);
423            }
424        }
425
426        if u == U256::one() {
427            self.0 = b.0;
428        } else {
429            self.0 = c.0;
430        }
431    }
432
433    /// Return an Iterator<Item=bool> over all bits from
434    /// MSB to LSB.
435    pub fn bits(&self) -> BitIterator {
436        BitIterator { int: self, n: 256 }
437    }
438}
439
440pub struct BitIterator<'a> {
441    int: &'a U256,
442    n: usize,
443}
444
445impl<'a> Iterator for BitIterator<'a> {
446    type Item = bool;
447
448    fn next(&mut self) -> Option<bool> {
449        if self.n == 0 {
450            None
451        } else {
452            self.n -= 1;
453
454            self.int.get_bit(self.n)
455        }
456    }
457}
458
459/// Divide by two
460#[inline]
461fn div2(a: &mut [u128; 2]) {
462    let tmp = a[1] << 127;
463    a[1] >>= 1;
464    a[0] >>= 1;
465    a[0] |= tmp;
466}
467
468/// Multiply by two
469#[inline]
470fn mul2(a: &mut [u128; 2]) {
471    let tmp = a[0] >> 127;
472    a[0] <<= 1;
473    a[1] <<= 1;
474    a[1] |= tmp;
475}
476
477#[inline(always)]
478fn split_u128(i: u128) -> (u128, u128) {
479    (i >> 64, i & 0xFFFFFFFFFFFFFFFF)
480}
481
482#[inline(always)]
483fn combine_u128(hi: u128, lo: u128) -> u128 {
484    (hi << 64) | lo
485}
486
487#[inline]
488fn adc(a: u128, b: u128, carry: &mut u128) -> u128 {
489    let (a1, a0) = split_u128(a);
490    let (b1, b0) = split_u128(b);
491    let (c, r0) = split_u128(a0 + b0 + *carry);
492    let (c, r1) = split_u128(a1 + b1 + c);
493    *carry = c;
494
495    combine_u128(r1, r0)
496}
497
498#[inline]
499fn add_nocarry(a: &mut [u128; 2], b: &[u128; 2]) {
500    let mut carry = 0;
501
502    for (a, b) in a.iter_mut().zip(b.iter()) {
503        *a = adc(*a, *b, &mut carry);
504    }
505
506    debug_assert!(0 == carry);
507}
508
509#[inline]
510fn sub_noborrow(a: &mut [u128; 2], b: &[u128; 2]) {
511    #[inline]
512    fn sbb(a: u128, b: u128, borrow: &mut u128) -> u128 {
513        let (a1, a0) = split_u128(a);
514        let (b1, b0) = split_u128(b);
515        let (b, r0) = split_u128((1 << 64) + a0 - b0 - *borrow);
516        let (b, r1) = split_u128((1 << 64) + a1 - b1 - ((b == 0) as u128));
517
518        *borrow = (b == 0) as u128;
519
520        combine_u128(r1, r0)
521    }
522
523    let mut borrow = 0;
524
525    for (a, b) in a.iter_mut().zip(b.iter()) {
526        *a = sbb(*a, *b, &mut borrow);
527    }
528
529    debug_assert!(0 == borrow);
530}
531
532// TODO: Make `from_index` a const param
533#[inline(always)]
534fn mac_digit(from_index: usize, acc: &mut [u128; 4], b: &[u128; 2], c: u128) {
535    #[inline]
536    fn mac_with_carry(a: u128, b: u128, c: u128, carry: &mut u128) -> u128 {
537        let (b_hi, b_lo) = split_u128(b);
538        let (c_hi, c_lo) = split_u128(c);
539
540        let (a_hi, a_lo) = split_u128(a);
541        let (carry_hi, carry_lo) = split_u128(*carry);
542        let (x_hi, x_lo) = split_u128(b_lo * c_lo + a_lo + carry_lo);
543        let (y_hi, y_lo) = split_u128(b_lo * c_hi);
544        let (z_hi, z_lo) = split_u128(b_hi * c_lo);
545        // Brackets to allow better ILP
546        let (r_hi, r_lo) = split_u128((x_hi + y_lo) + (z_lo + a_hi) + carry_hi);
547
548        *carry = (b_hi * c_hi) + r_hi + y_hi + z_hi;
549
550        combine_u128(r_lo, x_lo)
551    }
552
553    if c == 0 {
554        return;
555    }
556
557    let mut carry = 0;
558
559    debug_assert_eq!(acc.len(), 4);
560    unroll! {
561        for i in 0..2 {
562            let a_index = i + from_index;
563            acc[a_index] = mac_with_carry(acc[a_index], b[i], c, &mut carry);
564        }
565    }
566    unroll! {
567        for i in 0..2 {
568            let a_index = i + from_index + 2;
569            if a_index < 4 {
570                let (a_hi, a_lo) = split_u128(acc[a_index]);
571                let (carry_hi, carry_lo) = split_u128(carry);
572                let (x_hi, x_lo) = split_u128(a_lo + carry_lo);
573                let (r_hi, r_lo) = split_u128(x_hi + a_hi + carry_hi);
574
575                carry = r_hi;
576
577                acc[a_index] = combine_u128(r_lo, x_lo);
578            }
579        }
580    }
581
582    debug_assert!(carry == 0);
583}
584
585#[inline]
586fn mul_reduce(this: &mut [u128; 2], by: &[u128; 2], modulus: &[u128; 2], inv: u128) {
587    // The Montgomery reduction here is based on Algorithm 14.32 in
588    // Handbook of Applied Cryptography
589    // <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
590
591    let mut res = [0; 2 * 2];
592    unroll! {
593        for i in 0..2 {
594            mac_digit(i, &mut res, by, this[i]);
595        }
596    }
597
598    unroll! {
599        for i in 0..2 {
600            let k = inv.wrapping_mul(res[i]);
601            mac_digit(i, &mut res, modulus, k);
602        }
603    }
604
605    this.copy_from_slice(&res[2..]);
606}
607
608#[test]
609fn setting_bits() {
610    let rng = &mut ::rand::rng();
611    let modulo = U256::from([0xffffffffffffffff; 4]);
612
613    let a = U256::random(rng, &modulo);
614    let mut e = U256::zero();
615    for (i, b) in a.bits().enumerate() {
616        assert!(e.set_bit(255 - i, b));
617    }
618
619    assert_eq!(a, e);
620}
621
622#[test]
623fn from_slice() {
624    let tst = U256::one();
625    let mut s = [0u8; 32];
626    s[31] = 1;
627
628    let num =
629        U256::from_slice(&s).expect("U256 should initialize ok from slice in `from_slice` test");
630    assert_eq!(num, tst);
631}
632
633#[test]
634fn to_big_endian() {
635    let num = U256::one();
636    let mut s = [0u8; 32];
637
638    num.to_big_endian(&mut s)
639        .expect("U256 should convert to bytes ok in `to_big_endian` test");
640    assert_eq!(
641        s,
642        [
643            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
644            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
645        ]
646    );
647}
648
649#[test]
650fn testing_divrem() {
651    let rng = &mut ::rand::rng();
652
653    let modulo = U256::from([
654        0x3c208c16d87cfd47,
655        0x97816a916871ca8d,
656        0xb85045b68181585d,
657        0x30644e72e131a029,
658    ]);
659
660    for _ in 0..100 {
661        let c0 = U256::random(rng, &modulo);
662        let c1 = U256::random(rng, &modulo);
663
664        let c1q_plus_c0 = U512::new(&c1, &c0, &modulo);
665
666        let (new_c1, new_c0) = c1q_plus_c0.divrem(&modulo);
667
668        assert!(c1 == new_c1.unwrap());
669        assert!(c0 == new_c0);
670    }
671
672    {
673        // Modulus should become 1*q + 0
674        let a = U512::from([
675            0x3c208c16d87cfd47,
676            0x97816a916871ca8d,
677            0xb85045b68181585d,
678            0x30644e72e131a029,
679            0,
680            0,
681            0,
682            0,
683        ]);
684
685        let (c1, c0) = a.divrem(&modulo);
686        assert_eq!(c1.unwrap(), U256::one());
687        assert_eq!(c0, U256::zero());
688    }
689
690    {
691        // Modulus squared minus 1 should be (q-1) q + q-1
692        let a = U512::from([
693            0x3b5458a2275d69b0,
694            0xa602072d09eac101,
695            0x4a50189c6d96cadc,
696            0x04689e957a1242c8,
697            0x26edfa5c34c6b38d,
698            0xb00b855116375606,
699            0x599a6f7c0348d21c,
700            0x0925c4b8763cbf9c,
701        ]);
702
703        let (c1, c0) = a.divrem(&modulo);
704        assert_eq!(
705            c1.unwrap(),
706            U256::from([
707                0x3c208c16d87cfd46,
708                0x97816a916871ca8d,
709                0xb85045b68181585d,
710                0x30644e72e131a029
711            ])
712        );
713        assert_eq!(
714            c0,
715            U256::from([
716                0x3c208c16d87cfd46,
717                0x97816a916871ca8d,
718                0xb85045b68181585d,
719                0x30644e72e131a029
720            ])
721        );
722    }
723
724    {
725        // Modulus squared minus 2 should be (q-1) q + q-2
726        let a = U512::from([
727            0x3b5458a2275d69af,
728            0xa602072d09eac101,
729            0x4a50189c6d96cadc,
730            0x04689e957a1242c8,
731            0x26edfa5c34c6b38d,
732            0xb00b855116375606,
733            0x599a6f7c0348d21c,
734            0x0925c4b8763cbf9c,
735        ]);
736
737        let (c1, c0) = a.divrem(&modulo);
738
739        assert_eq!(
740            c1.unwrap(),
741            U256::from([
742                0x3c208c16d87cfd46,
743                0x97816a916871ca8d,
744                0xb85045b68181585d,
745                0x30644e72e131a029
746            ])
747        );
748        assert_eq!(
749            c0,
750            U256::from([
751                0x3c208c16d87cfd45,
752                0x97816a916871ca8d,
753                0xb85045b68181585d,
754                0x30644e72e131a029
755            ])
756        );
757    }
758
759    {
760        // Ridiculously large number should fail
761        let a = U512::from([
762            0xffffffffffffffff,
763            0xffffffffffffffff,
764            0xffffffffffffffff,
765            0xffffffffffffffff,
766            0xffffffffffffffff,
767            0xffffffffffffffff,
768            0xffffffffffffffff,
769            0xffffffffffffffff,
770        ]);
771
772        let (c1, c0) = a.divrem(&modulo);
773        assert!(c1.is_none());
774        assert_eq!(
775            c0,
776            U256::from([
777                0xf32cfc5b538afa88,
778                0xb5e71911d44501fb,
779                0x47ab1eff0a417ff6,
780                0x06d89f71cab8351f
781            ])
782        );
783    }
784
785    {
786        // Modulus squared should fail
787        let a = U512::from([
788            0x3b5458a2275d69b1,
789            0xa602072d09eac101,
790            0x4a50189c6d96cadc,
791            0x04689e957a1242c8,
792            0x26edfa5c34c6b38d,
793            0xb00b855116375606,
794            0x599a6f7c0348d21c,
795            0x0925c4b8763cbf9c,
796        ]);
797
798        let (c1, c0) = a.divrem(&modulo);
799        assert!(c1.is_none());
800        assert_eq!(c0, U256::zero());
801    }
802
803    {
804        // Modulus squared plus one should fail
805        let a = U512::from([
806            0x3b5458a2275d69b2,
807            0xa602072d09eac101,
808            0x4a50189c6d96cadc,
809            0x04689e957a1242c8,
810            0x26edfa5c34c6b38d,
811            0xb00b855116375606,
812            0x599a6f7c0348d21c,
813            0x0925c4b8763cbf9c,
814        ]);
815
816        let (c1, c0) = a.divrem(&modulo);
817        assert!(c1.is_none());
818        assert_eq!(c0, U256::one());
819    }
820
821    {
822        let modulo = U256::from([
823            0x43e1f593f0000001,
824            0x2833e84879b97091,
825            0xb85045b68181585d,
826            0x30644e72e131a029,
827        ]);
828
829        // Fr modulus masked off is valid
830        let a = U512::from([
831            0xffffffffffffffff,
832            0xffffffffffffffff,
833            0xffffffffffffffff,
834            0xffffffffffffffff,
835            0xffffffffffffffff,
836            0xffffffffffffffff,
837            0xffffffffffffffff,
838            0x07ffffffffffffff,
839        ]);
840
841        let (c1, c0) = a.divrem(&modulo);
842
843        assert!(c1.unwrap() < modulo);
844        assert!(c0 < modulo);
845    }
846}