Skip to main content

ark_ff/biginteger/
mod.rs

1use crate::{
2    bits::{BitIteratorBE, BitIteratorLE},
3    const_for, UniformRand,
4};
5use ark_ff_macros::unroll_for_loops;
6use ark_serialize::{
7    CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
8};
9use ark_std::{
10    borrow::Borrow,
11    // convert::TryFrom,
12    fmt::{Debug, Display, UpperHex},
13    io::{Read, Write},
14    ops::{
15        BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, ShlAssign, Shr,
16        ShrAssign,
17    },
18    rand::{
19        distributions::{Distribution, Standard},
20        Rng,
21    },
22    str::FromStr,
23    vec::Vec,
24    Zero,
25};
26use num_bigint::BigUint;
27use zeroize::Zeroize;
28
29#[macro_use]
30pub mod arithmetic;
31
32#[derive(Copy, Clone, PartialEq, Eq, Hash)]
33#[must_use]
34pub struct BigInt<const N: usize>(pub [u64; N]);
35
36impl<const N: usize> Zeroize for BigInt<N> {
37    #[inline]
38    fn zeroize(&mut self) {
39        self.0.zeroize();
40    }
41}
42
43impl<const N: usize> Default for BigInt<N> {
44    #[inline]
45    fn default() -> Self {
46        Self([0u64; N])
47    }
48}
49
50impl<const N: usize> CanonicalSerialize for BigInt<N> {
51    #[inline]
52    fn serialize_with_mode<W: Write>(
53        &self,
54        writer: W,
55        compress: Compress,
56    ) -> Result<(), SerializationError> {
57        self.0.serialize_with_mode(writer, compress)
58    }
59
60    #[inline]
61    fn serialized_size(&self, compress: Compress) -> usize {
62        self.0.serialized_size(compress)
63    }
64}
65
66impl<const N: usize> Valid for BigInt<N> {
67    const TRIVIAL_CHECK: bool = true;
68
69    #[inline]
70    fn check(&self) -> Result<(), SerializationError> {
71        self.0.check()
72    }
73}
74
75impl<const N: usize> CanonicalDeserialize for BigInt<N> {
76    #[inline]
77    fn deserialize_with_mode<R: Read>(
78        reader: R,
79        compress: Compress,
80        validate: Validate,
81    ) -> Result<Self, SerializationError> {
82        Ok(BigInt(<[u64; N]>::deserialize_with_mode(
83            reader, compress, validate,
84        )?))
85    }
86}
87
88/// Construct a [`struct@BigInt<N>`] element from a literal string.
89///
90/// # Panics
91///
92/// If the integer represented by the string cannot fit in the number
93/// of limbs of the `BigInt`, this macro results in a
94/// * compile-time error if used in a const context
95/// * run-time error otherwise.
96///
97/// # Usage
98/// ```rust
99/// # use ark_ff::BigInt;
100/// const ONE: BigInt<6> = BigInt!("1");
101///
102/// fn check_correctness() {
103///     assert_eq!(ONE, BigInt::from(1u8));
104/// }
105/// ```
106#[macro_export]
107macro_rules! BigInt {
108    ($c0:expr) => {{
109        let (is_positive, limbs) = $crate::ark_ff_macros::to_sign_and_limbs!($c0);
110        assert!(is_positive);
111        let mut integer = $crate::BigInt::zero();
112        assert!(integer.0.len() >= limbs.len());
113        $crate::const_for!((i in 0..(limbs.len())) {
114            integer.0[i] = limbs[i];
115        });
116        integer
117    }};
118}
119
120#[doc(hidden)]
121macro_rules! const_modulo {
122    ($a:expr, $divisor:expr) => {{
123        // Stupid slow base-2 long division taken from
124        // https://en.wikipedia.org/wiki/Division_algorithm
125        assert!(!$divisor.const_is_zero());
126        let mut remainder = Self::new([0u64; N]);
127        let mut i = ($a.num_bits() - 1) as isize;
128        let mut carry;
129        while i >= 0 {
130            (remainder, carry) = remainder.const_mul2_with_carry();
131            remainder.0[0] |= $a.get_bit(i as usize) as u64;
132            if remainder.const_geq($divisor) || carry {
133                let (r, borrow) = remainder.const_sub_with_borrow($divisor);
134                remainder = r;
135                assert!(borrow == carry);
136            }
137            i -= 1;
138        }
139        remainder
140    }};
141}
142
143impl<const N: usize> BigInt<N> {
144    #[inline]
145    pub const fn new(value: [u64; N]) -> Self {
146        Self(value)
147    }
148
149    #[inline]
150    pub const fn zero() -> Self {
151        Self([0u64; N])
152    }
153
154    #[inline]
155    pub const fn one() -> Self {
156        let mut one = Self::zero();
157        one.0[0] = 1;
158        one
159    }
160
161    #[doc(hidden)]
162    #[inline]
163    pub const fn const_is_even(&self) -> bool {
164        self.0[0] % 2 == 0
165    }
166
167    #[doc(hidden)]
168    #[inline]
169    pub const fn const_is_odd(&self) -> bool {
170        self.0[0] % 2 == 1
171    }
172
173    #[doc(hidden)]
174    #[inline]
175    pub const fn mod_4(&self) -> u8 {
176        // To compute n % 4, we need to simply look at the
177        // 2 least significant bits of n, and check their value mod 4.
178        (((self.0[0] << 62) >> 62) % 4) as u8
179    }
180
181    #[doc(hidden)]
182    pub const fn mod_8(&self) -> u8 {
183        // To compute n % 8, we need to simply look at the
184        // 3 least significant bits of n, and check their value mod 8.
185        (((self.0[0] << 61) >> 61) % 8) as u8
186    }
187
188    /// Compute a right shift of `self`
189    /// This is equivalent to a (saturating) division by 2.
190    #[doc(hidden)]
191    #[inline]
192    pub const fn const_shr(&self) -> Self {
193        let mut result = *self;
194        let mut t = 0;
195        crate::const_for!((i in 0..N) {
196            let a = result.0[N - i - 1];
197            let t2 = a << 63;
198            result.0[N - i - 1] >>= 1;
199            result.0[N - i - 1] |= t;
200            t = t2;
201        });
202        result
203    }
204
205    #[inline]
206    const fn const_geq(&self, other: &Self) -> bool {
207        const_for!((i in 0..N) {
208            let a = self.0[N - i - 1];
209            let b = other.0[N - i - 1];
210            if a < b {
211                return false;
212            } else if a > b {
213                return true;
214            }
215        });
216        true
217    }
218
219    /// Compute the largest integer `s` such that `self = 2**s * t + 1` for odd `t`.
220    #[doc(hidden)]
221    #[inline]
222    pub const fn two_adic_valuation(mut self) -> u32 {
223        assert!(self.const_is_odd());
224        let mut two_adicity = 0;
225        // Since `self` is odd, we can always subtract one
226        // without a borrow
227        self.0[0] -= 1;
228        while self.const_is_even() {
229            self = self.const_shr();
230            two_adicity += 1;
231        }
232        two_adicity
233    }
234
235    /// Compute the smallest odd integer `t` such that `self = 2**s * t + 1` for some
236    /// integer `s = self.two_adic_valuation()`.
237    #[doc(hidden)]
238    #[inline]
239    pub const fn two_adic_coefficient(mut self) -> Self {
240        assert!(self.const_is_odd());
241        // Since `self` is odd, we can always subtract one
242        // without a borrow
243        self.0[0] -= 1;
244        while self.const_is_even() {
245            self = self.const_shr();
246        }
247        assert!(self.const_is_odd());
248        self
249    }
250
251    /// Divide `self` by 2, rounding down if necessary.
252    /// That is, if `self.is_odd()`, compute `(self - 1)/2`.
253    /// Else, compute `self/2`.
254    #[doc(hidden)]
255    #[inline]
256    pub const fn divide_by_2_round_down(mut self) -> Self {
257        if self.const_is_odd() {
258            self.0[0] -= 1;
259        }
260        self.const_shr()
261    }
262
263    /// Find the number of bits in the binary decomposition of `self`.
264    #[doc(hidden)]
265    #[inline]
266    pub const fn const_num_bits(self) -> u32 {
267        ((N - 1) * 64) as u32 + (64 - self.0[N - 1].leading_zeros())
268    }
269
270    #[inline]
271    pub(crate) const fn const_sub_with_borrow(mut self, other: &Self) -> (Self, bool) {
272        let mut borrow = 0;
273
274        const_for!((i in 0..N) {
275            borrow = arithmetic::sbb(&mut self.0[i], other.0[i], borrow);
276        });
277
278        (self, borrow != 0)
279    }
280
281    #[inline]
282    pub(crate) const fn const_add_with_carry(mut self, other: &Self) -> (Self, bool) {
283        let mut carry = 0;
284
285        crate::const_for!((i in 0..N) {
286            carry = arithmetic::adc(&mut self.0[i], other.0[i], carry);
287        });
288
289        (self, carry != 0)
290    }
291
292    #[inline]
293    const fn const_mul2_with_carry(mut self) -> (Self, bool) {
294        let mut last = 0;
295        crate::const_for!((i in 0..N) {
296            let a = self.0[i];
297            let tmp = a >> 63;
298            self.0[i] <<= 1;
299            self.0[i] |= last;
300            last = tmp;
301        });
302        (self, last != 0)
303    }
304
305    #[inline]
306    pub(crate) const fn const_is_zero(&self) -> bool {
307        let mut is_zero = true;
308        crate::const_for!((i in 0..N) {
309            is_zero &= self.0[i] == 0;
310        });
311        is_zero
312    }
313
314    /// Computes the Montgomery R constant modulo `self`.
315    #[doc(hidden)]
316    #[inline]
317    pub const fn montgomery_r(&self) -> Self {
318        let two_pow_n_times_64 = crate::const_helpers::RBuffer([0u64; N], 1);
319        const_modulo!(two_pow_n_times_64, self)
320    }
321
322    /// Computes the Montgomery R2 constant modulo `self`.
323    #[doc(hidden)]
324    #[inline]
325    pub const fn montgomery_r2(&self) -> Self {
326        let two_pow_n_times_64_square = crate::const_helpers::R2Buffer([0u64; N], [0u64; N], 1);
327        const_modulo!(two_pow_n_times_64_square, self)
328    }
329}
330
331impl<const N: usize> BigInteger for BigInt<N> {
332    const NUM_LIMBS: usize = N;
333
334    #[unroll_for_loops(6)]
335    #[inline]
336    fn add_with_carry(&mut self, other: &Self) -> bool {
337        let mut carry = 0;
338
339        for i in 0..N {
340            carry = arithmetic::adc_for_add_with_carry(&mut self.0[i], other.0[i], carry);
341        }
342
343        carry != 0
344    }
345
346    #[unroll_for_loops(6)]
347    #[inline]
348    fn sub_with_borrow(&mut self, other: &Self) -> bool {
349        let mut borrow = 0;
350
351        for i in 0..N {
352            borrow = arithmetic::sbb_for_sub_with_borrow(&mut self.0[i], other.0[i], borrow);
353        }
354
355        borrow != 0
356    }
357
358    #[inline]
359    fn mul2(&mut self) -> bool {
360        #[cfg(target_arch = "x86_64")]
361        #[allow(unused_unsafe, unsafe_code)]
362        {
363            let mut carry = 0;
364
365            for i in 0..N {
366                unsafe {
367                    use core::arch::x86_64::_addcarry_u64;
368                    carry = _addcarry_u64(carry, self.0[i], self.0[i], &mut self.0[i])
369                };
370            }
371
372            carry != 0
373        }
374
375        #[cfg(not(target_arch = "x86_64"))]
376        {
377            let mut last = 0;
378            for i in 0..N {
379                let a = &mut self.0[i];
380                let tmp = *a >> 63;
381                *a <<= 1;
382                *a |= last;
383                last = tmp;
384            }
385            last != 0
386        }
387    }
388
389    #[inline]
390    fn muln(&mut self, mut n: u32) {
391        if n >= (64 * N) as u32 {
392            *self = Self::from(0u64);
393            return;
394        }
395
396        while n >= 64 {
397            let mut t = 0;
398            for i in 0..N {
399                core::mem::swap(&mut t, &mut self.0[i]);
400            }
401            n -= 64;
402        }
403
404        if n > 0 {
405            let mut t = 0;
406            for i in 0..N {
407                let a = &mut self.0[i];
408                let t2 = *a >> (64 - n);
409                *a <<= n;
410                *a |= t;
411                t = t2;
412            }
413        }
414    }
415
416    #[inline]
417    fn mul(&self, other: &Self) -> (Self, Self) {
418        if self.is_zero() || other.is_zero() {
419            let zero = Self::zero();
420            return (zero, zero);
421        }
422
423        let mut r = crate::const_helpers::MulBuffer::zeroed();
424
425        let mut carry = 0;
426
427        for i in 0..N {
428            for j in 0..N {
429                r[i + j] = arithmetic::mac_with_carry(r[i + j], self.0[i], other.0[j], &mut carry);
430            }
431            r.b1[i] = carry;
432            carry = 0;
433        }
434
435        (Self(r.b0), Self(r.b1))
436    }
437
438    #[inline]
439    fn mul_low(&self, other: &Self) -> Self {
440        if self.is_zero() || other.is_zero() {
441            return Self::zero();
442        }
443
444        let mut res = Self::zero();
445        let mut carry = 0;
446
447        for i in 0..N {
448            for j in 0..(N - i) {
449                res.0[i + j] =
450                    arithmetic::mac_with_carry(res.0[i + j], self.0[i], other.0[j], &mut carry);
451            }
452            carry = 0;
453        }
454
455        res
456    }
457
458    #[inline]
459    fn mul_high(&self, other: &Self) -> Self {
460        self.mul(other).1
461    }
462
463    #[inline]
464    fn div2(&mut self) {
465        let mut t = 0;
466        for a in self.0.iter_mut().rev() {
467            let t2 = *a << 63;
468            *a >>= 1;
469            *a |= t;
470            t = t2;
471        }
472    }
473
474    #[inline]
475    fn divn(&mut self, mut n: u32) {
476        if n >= (64 * N) as u32 {
477            *self = Self::from(0u64);
478            return;
479        }
480
481        while n >= 64 {
482            let mut t = 0;
483            for i in 0..N {
484                core::mem::swap(&mut t, &mut self.0[N - i - 1]);
485            }
486            n -= 64;
487        }
488
489        if n > 0 {
490            let mut t = 0;
491            for i in 0..N {
492                let a = &mut self.0[N - i - 1];
493                let t2 = *a << (64 - n);
494                *a >>= n;
495                *a |= t;
496                t = t2;
497            }
498        }
499    }
500
501    #[inline]
502    fn is_odd(&self) -> bool {
503        self.0[0] & 1 == 1
504    }
505
506    #[inline]
507    fn is_even(&self) -> bool {
508        !self.is_odd()
509    }
510
511    #[inline]
512    fn is_zero(&self) -> bool {
513        self.0.iter().all(Zero::is_zero)
514    }
515
516    #[inline]
517    fn num_bits(&self) -> u32 {
518        let mut ret = N as u32 * 64;
519        for i in self.0.iter().rev() {
520            let leading = i.leading_zeros();
521            ret -= leading;
522            if leading != 64 {
523                break;
524            }
525        }
526
527        ret
528    }
529
530    #[inline]
531    fn get_bit(&self, i: usize) -> bool {
532        if i >= 64 * N {
533            false
534        } else {
535            let limb = i / 64;
536            let bit = i - (64 * limb);
537            (self.0[limb] & (1 << bit)) != 0
538        }
539    }
540
541    #[inline]
542    fn from_bits_be(bits: &[bool]) -> Self {
543        let mut bits = bits.to_vec();
544        bits.reverse();
545        Self::from_bits_le(&bits)
546    }
547
548    #[inline]
549    fn from_bits_le(bits: &[bool]) -> Self {
550        let mut res = Self::zero();
551        for (bits64, res_i) in bits.chunks(64).zip(&mut res.0) {
552            for (i, bit) in bits64.iter().enumerate() {
553                *res_i |= (*bit as u64) << i;
554            }
555        }
556        res
557    }
558
559    #[inline]
560    fn to_bytes_be(&self) -> Vec<u8> {
561        let mut le_bytes = self.to_bytes_le();
562        le_bytes.reverse();
563        le_bytes
564    }
565
566    #[inline]
567    fn to_bytes_le(&self) -> Vec<u8> {
568        self.0.iter().flat_map(|&limb| limb.to_le_bytes()).collect()
569    }
570}
571
572impl<const N: usize> UpperHex for BigInt<N> {
573    #[inline]
574    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
575        write!(f, "{:016X}", BigUint::from(*self))
576    }
577}
578
579impl<const N: usize> Debug for BigInt<N> {
580    #[inline]
581    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
582        write!(f, "{:?}", BigUint::from(*self))
583    }
584}
585
586impl<const N: usize> Display for BigInt<N> {
587    #[inline]
588    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
589        write!(f, "{}", BigUint::from(*self))
590    }
591}
592
593impl<const N: usize> Ord for BigInt<N> {
594    #[inline]
595    #[cfg_attr(target_arch = "x86_64", unroll_for_loops(12))]
596    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
597        use core::cmp::Ordering;
598        #[cfg(target_arch = "x86_64")]
599        for i in 0..N {
600            let a = &self.0[N - i - 1];
601            let b = &other.0[N - i - 1];
602            match a.cmp(b) {
603                Ordering::Equal => {},
604                order => return order,
605            };
606        }
607        #[cfg(not(target_arch = "x86_64"))]
608        for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
609            if let order @ (Ordering::Less | Ordering::Greater) = a.cmp(b) {
610                return order;
611            }
612        }
613        Ordering::Equal
614    }
615}
616
617impl<const N: usize> PartialOrd for BigInt<N> {
618    #[inline]
619    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
620        Some(self.cmp(other))
621    }
622}
623
624impl<const N: usize> Distribution<BigInt<N>> for Standard {
625    #[inline]
626    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt<N> {
627        BigInt([(); N].map(|_| rng.gen()))
628    }
629}
630
631impl<const N: usize> AsMut<[u64]> for BigInt<N> {
632    #[inline]
633    fn as_mut(&mut self) -> &mut [u64] {
634        &mut self.0
635    }
636}
637
638impl<const N: usize> AsRef<[u64]> for BigInt<N> {
639    #[inline]
640    fn as_ref(&self) -> &[u64] {
641        &self.0
642    }
643}
644
645impl<const N: usize> From<u64> for BigInt<N> {
646    #[inline]
647    fn from(val: u64) -> BigInt<N> {
648        let mut repr = Self::default();
649        repr.0[0] = val;
650        repr
651    }
652}
653
654impl<const N: usize> From<u32> for BigInt<N> {
655    #[inline]
656    fn from(val: u32) -> BigInt<N> {
657        let mut repr = Self::default();
658        repr.0[0] = val.into();
659        repr
660    }
661}
662
663impl<const N: usize> From<u16> for BigInt<N> {
664    #[inline]
665    fn from(val: u16) -> BigInt<N> {
666        let mut repr = Self::default();
667        repr.0[0] = val.into();
668        repr
669    }
670}
671
672impl<const N: usize> From<u8> for BigInt<N> {
673    #[inline]
674    fn from(val: u8) -> BigInt<N> {
675        let mut repr = Self::default();
676        repr.0[0] = val.into();
677        repr
678    }
679}
680
681impl<const N: usize> TryFrom<BigUint> for BigInt<N> {
682    type Error = ();
683
684    /// Returns `Err(())` if the bit size of `val` is more than `N * 64`.
685    #[inline]
686    fn try_from(val: num_bigint::BigUint) -> Result<BigInt<N>, Self::Error> {
687        let bytes = val.to_bytes_le();
688
689        if bytes.len() > N * 8 {
690            Err(())
691        } else {
692            let mut limbs = [0u64; N];
693
694            bytes.chunks(8).enumerate().for_each(|(i, chunk)| {
695                let mut chunk_padded = [0u8; 8];
696                chunk_padded[..chunk.len()].copy_from_slice(chunk);
697                limbs[i] = u64::from_le_bytes(chunk_padded)
698            });
699
700            Ok(Self(limbs))
701        }
702    }
703}
704
705impl<const N: usize> FromStr for BigInt<N> {
706    type Err = ();
707
708    fn from_str(s: &str) -> Result<Self, Self::Err> {
709        let biguint = BigUint::from_str(s).map_err(|_| ())?;
710        Self::try_from(biguint)
711    }
712}
713
714impl<const N: usize> From<BigInt<N>> for BigUint {
715    #[inline]
716    fn from(val: BigInt<N>) -> num_bigint::BigUint {
717        BigUint::from_bytes_le(&val.to_bytes_le())
718    }
719}
720
721impl<const N: usize> From<BigInt<N>> for num_bigint::BigInt {
722    #[inline]
723    fn from(val: BigInt<N>) -> num_bigint::BigInt {
724        use num_bigint::Sign;
725        let sign = if val.is_zero() {
726            Sign::NoSign
727        } else {
728            Sign::Plus
729        };
730        num_bigint::BigInt::from_bytes_le(sign, &val.to_bytes_le())
731    }
732}
733
734impl<B: Borrow<Self>, const N: usize> BitXorAssign<B> for BigInt<N> {
735    #[inline]
736    fn bitxor_assign(&mut self, rhs: B) {
737        (0..N).for_each(|i| self.0[i] ^= rhs.borrow().0[i])
738    }
739}
740
741impl<B: Borrow<Self>, const N: usize> BitXor<B> for BigInt<N> {
742    type Output = Self;
743
744    #[inline]
745    fn bitxor(mut self, rhs: B) -> Self::Output {
746        self ^= rhs;
747        self
748    }
749}
750
751impl<B: Borrow<Self>, const N: usize> BitAndAssign<B> for BigInt<N> {
752    #[inline]
753    fn bitand_assign(&mut self, rhs: B) {
754        (0..N).for_each(|i| self.0[i] &= rhs.borrow().0[i])
755    }
756}
757
758impl<B: Borrow<Self>, const N: usize> BitAnd<B> for BigInt<N> {
759    type Output = Self;
760
761    #[inline]
762    fn bitand(mut self, rhs: B) -> Self::Output {
763        self &= rhs;
764        self
765    }
766}
767
768impl<B: Borrow<Self>, const N: usize> BitOrAssign<B> for BigInt<N> {
769    #[inline]
770    fn bitor_assign(&mut self, rhs: B) {
771        (0..N).for_each(|i| self.0[i] |= rhs.borrow().0[i])
772    }
773}
774
775impl<B: Borrow<Self>, const N: usize> BitOr<B> for BigInt<N> {
776    type Output = Self;
777
778    #[inline]
779    fn bitor(mut self, rhs: B) -> Self::Output {
780        self |= rhs;
781        self
782    }
783}
784
785impl<const N: usize> ShrAssign<u32> for BigInt<N> {
786    /// Computes the bitwise shift right operation in place.
787    ///
788    /// Differently from the built-in numeric types (u8, u32, u64, etc.) this
789    /// operation does *not* return an underflow error if the number of bits
790    /// shifted is larger than N * 64. Instead the result will be saturated to
791    /// zero.
792    #[inline]
793    fn shr_assign(&mut self, mut rhs: u32) {
794        if rhs >= (64 * N) as u32 {
795            *self = Self::from(0u64);
796            return;
797        }
798
799        while rhs >= 64 {
800            let mut t = 0;
801            for limb in self.0.iter_mut().rev() {
802                core::mem::swap(&mut t, limb);
803            }
804            rhs -= 64;
805        }
806
807        if rhs > 0 {
808            let mut t = 0;
809            for a in self.0.iter_mut().rev() {
810                let t2 = *a << (64 - rhs);
811                *a >>= rhs;
812                *a |= t;
813                t = t2;
814            }
815        }
816    }
817}
818
819impl<const N: usize> Shr<u32> for BigInt<N> {
820    type Output = Self;
821
822    /// Computes bitwise shift right operation.
823    ///
824    /// Differently from the built-in numeric types (u8, u32, u64, etc.) this
825    /// operation does *not* return an underflow error if the number of bits
826    /// shifted is larger than N * 64. Instead the result will be saturated to
827    /// zero.
828    #[inline]
829    fn shr(mut self, rhs: u32) -> Self::Output {
830        self >>= rhs;
831        self
832    }
833}
834
835impl<const N: usize> ShlAssign<u32> for BigInt<N> {
836    /// Computes the bitwise shift left operation in place.
837    ///
838    /// Differently from the built-in numeric types (u8, u32, u64, etc.) this
839    /// operation does *not* return an overflow error if the number of bits
840    /// shifted is larger than N * 64. Instead, the overflow will be chopped
841    /// off.
842    #[inline]
843    fn shl_assign(&mut self, mut rhs: u32) {
844        if rhs >= (64 * N) as u32 {
845            *self = Self::from(0u64);
846            return;
847        }
848
849        while rhs >= 64 {
850            let mut t = 0;
851            for i in 0..N {
852                core::mem::swap(&mut t, &mut self.0[i]);
853            }
854            rhs -= 64;
855        }
856
857        if rhs > 0 {
858            let mut t = 0;
859            for i in 0..N {
860                let a = &mut self.0[i];
861                let t2 = *a >> (64 - rhs);
862                *a <<= rhs;
863                *a |= t;
864                t = t2;
865            }
866        }
867    }
868}
869
870impl<const N: usize> Shl<u32> for BigInt<N> {
871    type Output = Self;
872
873    /// Computes the bitwise shift left operation in place.
874    ///
875    /// Differently from the built-in numeric types (u8, u32, u64, etc.) this
876    /// operation does *not* return an overflow error if the number of bits
877    /// shifted is larger than N * 64. Instead, the overflow will be chopped
878    /// off.
879    #[inline]
880    fn shl(mut self, rhs: u32) -> Self::Output {
881        self <<= rhs;
882        self
883    }
884}
885
886impl<const N: usize> Not for BigInt<N> {
887    type Output = Self;
888
889    #[inline]
890    fn not(self) -> Self::Output {
891        let mut result = Self::zero();
892        for i in 0..N {
893            result.0[i] = !self.0[i];
894        }
895        result
896    }
897}
898
899/// Compute the signed modulo operation on a u64 representation, returning the result.
900/// If n % modulus > modulus / 2, return modulus - n
901/// # Example
902/// ```
903/// use ark_ff::signed_mod_reduction;
904/// let res = signed_mod_reduction(6u64, 8u64);
905/// assert_eq!(res, -2i64);
906/// ```
907#[inline]
908pub const fn signed_mod_reduction(n: u64, modulus: u64) -> i64 {
909    let t = (n % modulus) as i64;
910    if t as u64 >= (modulus / 2) {
911        t - (modulus as i64)
912    } else {
913        t
914    }
915}
916
917pub type BigInteger64 = BigInt<1>;
918pub type BigInteger128 = BigInt<2>;
919pub type BigInteger256 = BigInt<4>;
920pub type BigInteger320 = BigInt<5>;
921pub type BigInteger384 = BigInt<6>;
922pub type BigInteger448 = BigInt<7>;
923pub type BigInteger768 = BigInt<12>;
924pub type BigInteger832 = BigInt<13>;
925
926#[cfg(test)]
927mod tests;
928
929/// This defines a `BigInteger`, a smart wrapper around a
930/// sequence of `u64` limbs, least-significant limb first.
931// TODO: get rid of this trait once we can use associated constants in const generics.
932pub trait BigInteger:
933    CanonicalSerialize
934    + CanonicalDeserialize
935    + Copy
936    + Clone
937    + Debug
938    + Default
939    + Display
940    + Eq
941    + Ord
942    + Send
943    + Sized
944    + Sync
945    + 'static
946    + UniformRand
947    + Zeroize
948    + AsMut<[u64]>
949    + AsRef<[u64]>
950    + From<u64>
951    + From<u32>
952    + From<u16>
953    + From<u8>
954    + TryFrom<BigUint, Error = ()>
955    + FromStr
956    + Into<BigUint>
957    + BitXorAssign<Self>
958    + for<'a> BitXorAssign<&'a Self>
959    + BitXor<Self, Output = Self>
960    + for<'a> BitXor<&'a Self, Output = Self>
961    + BitAndAssign<Self>
962    + for<'a> BitAndAssign<&'a Self>
963    + BitAnd<Self, Output = Self>
964    + for<'a> BitAnd<&'a Self, Output = Self>
965    + BitOrAssign<Self>
966    + for<'a> BitOrAssign<&'a Self>
967    + BitOr<Self, Output = Self>
968    + for<'a> BitOr<&'a Self, Output = Self>
969    + Shr<u32, Output = Self>
970    + ShrAssign<u32>
971    + Shl<u32, Output = Self>
972    + ShlAssign<u32>
973{
974    /// Number of 64-bit limbs representing `Self`.
975    const NUM_LIMBS: usize;
976
977    /// Add another [`BigInteger`] to `self`. This method stores the result in `self`,
978    /// and returns a carry bit.
979    ///
980    /// # Example
981    ///
982    /// ```
983    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
984    ///
985    /// // Basic
986    /// let (mut one, mut x) = (B::from(1u64), B::from(2u64));
987    /// let carry = x.add_with_carry(&one);
988    /// assert_eq!(x, B::from(3u64));
989    /// assert_eq!(carry, false);
990    ///
991    /// // Edge-Case
992    /// let mut x = B::from(u64::MAX);
993    /// let carry = x.add_with_carry(&one);
994    /// assert_eq!(x, B::from(0u64));
995    /// assert_eq!(carry, true)
996    /// ```
997    fn add_with_carry(&mut self, other: &Self) -> bool;
998
999    /// Subtract another [`BigInteger`] from this one. This method stores the result in
1000    /// `self`, and returns a borrow.
1001    ///
1002    /// # Example
1003    ///
1004    /// ```
1005    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1006    ///
1007    /// // Basic
1008    /// let (mut one_sub, two, mut three_sub) = (B::from(1u64), B::from(2u64), B::from(3u64));
1009    /// let borrow = three_sub.sub_with_borrow(&two);
1010    /// assert_eq!(three_sub, one_sub);
1011    /// assert_eq!(borrow, false);
1012    ///
1013    /// // Edge-Case
1014    /// let borrow = one_sub.sub_with_borrow(&two);
1015    /// assert_eq!(one_sub, B::from(u64::MAX));
1016    /// assert_eq!(borrow, true);
1017    /// ```
1018    fn sub_with_borrow(&mut self, other: &Self) -> bool;
1019
1020    /// Performs a leftwise bitshift of this number, effectively multiplying
1021    /// it by 2. Overflow is ignored.
1022    /// # Example
1023    ///
1024    /// ```
1025    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1026    ///
1027    /// // Basic
1028    /// let mut two_mul = B::from(2u64);
1029    /// two_mul.mul2();
1030    /// assert_eq!(two_mul, B::from(4u64));
1031    ///
1032    /// // Edge-Cases
1033    /// let mut zero = B::from(0u64);
1034    /// zero.mul2();
1035    /// assert_eq!(zero, B::from(0u64));
1036    ///
1037    /// let mut arr: [bool; 64] = [false; 64];
1038    /// arr[0] = true;
1039    /// let mut mul = B::from_bits_be(&arr);
1040    /// mul.mul2();
1041    /// assert_eq!(mul, B::from(0u64));
1042    /// ```
1043    fn mul2(&mut self) -> bool;
1044
1045    /// Performs a leftwise bitshift of this number by n bits, effectively multiplying
1046    /// it by 2^n. Overflow is ignored.
1047    /// # Example
1048    ///
1049    /// ```
1050    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1051    ///
1052    /// // Basic
1053    /// let mut one_mul = B::from(1u64);
1054    /// one_mul.muln(5);
1055    /// assert_eq!(one_mul, B::from(32u64));
1056    ///
1057    /// // Edge-Case
1058    /// let mut zero = B::from(0u64);
1059    /// zero.muln(5);
1060    /// assert_eq!(zero, B::from(0u64));
1061    ///
1062    /// let mut arr: [bool; 64] = [false; 64];
1063    /// arr[4] = true;
1064    /// let mut mul = B::from_bits_be(&arr);
1065    /// mul.muln(5);
1066    /// assert_eq!(mul, B::from(0u64));
1067    /// ```
1068    #[deprecated(since = "0.4.2", note = "please use the operator `<<` instead")]
1069    fn muln(&mut self, amt: u32);
1070
1071    /// Multiplies this [`BigInteger`] by another `BigInteger`, storing the result in `self`.
1072    /// Overflow is ignored.
1073    ///
1074    /// # Example
1075    ///
1076    /// ```
1077    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1078    ///
1079    /// // Basic
1080    /// let mut a = B::from(42u64);
1081    /// let b = B::from(3u64);
1082    /// assert_eq!(a.mul_low(&b), B::from(126u64));
1083    ///
1084    /// // Edge-Case
1085    /// let mut zero = B::from(0u64);
1086    /// assert_eq!(zero.mul_low(&B::from(5u64)), B::from(0u64));
1087    /// ```
1088    fn mul_low(&self, other: &Self) -> Self;
1089
1090    /// Multiplies this [`BigInteger`] by another `BigInteger`, returning the high bits of the result.
1091    ///
1092    /// # Example
1093    ///
1094    /// ```
1095    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1096    ///
1097    /// // Basic
1098    /// let (one, x) = (B::from(1u64), B::from(2u64));
1099    /// let r = x.mul_high(&one);
1100    /// assert_eq!(r, B::from(0u64));
1101    ///
1102    /// // Edge-Case
1103    /// let mut x = B::from(u64::MAX);
1104    /// let r = x.mul_high(&B::from(2u64));
1105    /// assert_eq!(r, B::from(1u64))
1106    /// ```
1107    fn mul_high(&self, other: &Self) -> Self;
1108
1109    /// Multiplies this [`BigInteger`] by another `BigInteger`, returning both low and high bits of the result.
1110    ///
1111    /// # Example
1112    ///
1113    /// ```
1114    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1115    ///
1116    /// // Basic
1117    /// let mut a = B::from(42u64);
1118    /// let b = B::from(3u64);
1119    /// let (low_bits, high_bits) = a.mul(&b);
1120    /// assert_eq!(low_bits, B::from(126u64));
1121    /// assert_eq!(high_bits, B::from(0u64));
1122    ///
1123    /// // Edge-Case
1124    /// let mut x = B::from(u64::MAX);
1125    /// let mut max_plus_max = x;
1126    /// max_plus_max.add_with_carry(&x);
1127    /// let (low_bits, high_bits) = x.mul(&B::from(2u64));
1128    /// assert_eq!(low_bits, max_plus_max);
1129    /// assert_eq!(high_bits, B::from(1u64));
1130    /// ```
1131    fn mul(&self, other: &Self) -> (Self, Self);
1132
1133    /// Performs a rightwise bitshift of this number, effectively dividing
1134    /// it by 2.
1135    /// # Example
1136    ///
1137    /// ```
1138    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1139    ///
1140    /// // Basic
1141    /// let (mut two, mut four_div) = (B::from(2u64), B::from(4u64));
1142    /// four_div.div2();
1143    /// assert_eq!(two, four_div);
1144    ///
1145    /// // Edge-Case
1146    /// let mut zero = B::from(0u64);
1147    /// zero.div2();
1148    /// assert_eq!(zero, B::from(0u64));
1149    ///
1150    /// let mut one = B::from(1u64);
1151    /// one.div2();
1152    /// assert_eq!(one, B::from(0u64));
1153    /// ```
1154    fn div2(&mut self);
1155
1156    /// Performs a rightwise bitshift of this number by some amount.
1157    /// # Example
1158    ///
1159    /// ```
1160    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1161    ///
1162    /// // Basic
1163    /// let (mut one, mut thirty_two_div) = (B::from(1u64), B::from(32u64));
1164    /// thirty_two_div.divn(5);
1165    /// assert_eq!(one, thirty_two_div);
1166    ///
1167    /// // Edge-Case
1168    /// let mut arr: [bool; 64] = [false; 64];
1169    /// arr[4] = true;
1170    /// let mut div = B::from_bits_le(&arr);
1171    /// div.divn(5);
1172    /// assert_eq!(div, B::from(0u64));
1173    /// ```
1174    #[deprecated(since = "0.4.2", note = "please use the operator `>>` instead")]
1175    fn divn(&mut self, amt: u32);
1176
1177    /// Returns true iff this number is odd.
1178    /// # Example
1179    ///
1180    /// ```
1181    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1182    ///
1183    /// let mut one = B::from(1u64);
1184    /// assert!(one.is_odd());
1185    /// ```
1186    fn is_odd(&self) -> bool;
1187
1188    /// Returns true iff this number is even.
1189    /// # Example
1190    ///
1191    /// ```
1192    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1193    ///
1194    /// let mut two = B::from(2u64);
1195    /// assert!(two.is_even());
1196    /// ```
1197    fn is_even(&self) -> bool;
1198
1199    /// Returns true iff this number is zero.
1200    /// # Example
1201    ///
1202    /// ```
1203    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1204    ///
1205    /// let mut zero = B::from(0u64);
1206    /// assert!(zero.is_zero());
1207    /// ```
1208    fn is_zero(&self) -> bool;
1209
1210    /// Compute the minimum number of bits needed to encode this number.
1211    /// # Example
1212    /// ```
1213    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1214    ///
1215    /// let zero = B::from(0u64);
1216    /// assert_eq!(zero.num_bits(), 0);
1217    /// let one = B::from(1u64);
1218    /// assert_eq!(one.num_bits(), 1);
1219    /// let max = B::from(u64::MAX);
1220    /// assert_eq!(max.num_bits(), 64);
1221    /// let u32_max = B::from(u32::MAX as u64);
1222    /// assert_eq!(u32_max.num_bits(), 32);
1223    /// ```
1224    fn num_bits(&self) -> u32;
1225
1226    /// Compute the `i`-th bit of `self`.
1227    /// # Example
1228    ///
1229    /// ```
1230    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1231    ///
1232    /// let mut one = B::from(1u64);
1233    /// assert!(one.get_bit(0));
1234    /// assert!(!one.get_bit(1));
1235    /// ```
1236    fn get_bit(&self, i: usize) -> bool;
1237
1238    /// Returns the big integer representation of a given big endian boolean
1239    /// array.
1240    /// # Example
1241    ///
1242    /// ```
1243    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1244    ///
1245    /// let mut arr: [bool; 64] = [false; 64];
1246    /// arr[63] = true;
1247    /// let mut one = B::from(1u64);
1248    /// assert_eq!(B::from_bits_be(&arr), one);
1249    /// ```
1250    fn from_bits_be(bits: &[bool]) -> Self;
1251
1252    /// Returns the big integer representation of a given little endian boolean
1253    /// array.
1254    /// # Example
1255    ///
1256    /// ```
1257    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1258    ///
1259    /// let mut arr: [bool; 64] = [false; 64];
1260    /// arr[0] = true;
1261    /// let mut one = B::from(1u64);
1262    /// assert_eq!(B::from_bits_le(&arr), one);
1263    /// ```
1264    fn from_bits_le(bits: &[bool]) -> Self;
1265
1266    /// Returns the bit representation in a big endian boolean array,
1267    /// with leading zeroes.
1268    /// # Example
1269    ///
1270    /// ```
1271    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1272    ///
1273    /// let one = B::from(1u64);
1274    /// let arr = one.to_bits_be();
1275    /// let mut vec = vec![false; 64];
1276    /// vec[63] = true;
1277    /// assert_eq!(arr, vec);
1278    /// ```
1279    #[inline]
1280    fn to_bits_be(&self) -> Vec<bool> {
1281        BitIteratorBE::new(self).collect()
1282    }
1283
1284    /// Returns the bit representation in a little endian boolean array,
1285    /// with trailing zeroes.
1286    /// # Example
1287    ///
1288    /// ```
1289    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1290    ///
1291    /// let one = B::from(1u64);
1292    /// let arr = one.to_bits_le();
1293    /// let mut vec = vec![false; 64];
1294    /// vec[0] = true;
1295    /// assert_eq!(arr, vec);
1296    /// ```
1297    #[inline]
1298    fn to_bits_le(&self) -> Vec<bool> {
1299        BitIteratorLE::new(self).collect()
1300    }
1301
1302    /// Returns the byte representation in a big endian byte array,
1303    /// with leading zeros.
1304    /// # Example
1305    ///
1306    /// ```
1307    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1308    ///
1309    /// let one = B::from(1u64);
1310    /// let arr = one.to_bytes_be();
1311    /// let mut vec = vec![0; 8];
1312    /// vec[7] = 1;
1313    /// assert_eq!(arr, vec);
1314    /// ```
1315    fn to_bytes_be(&self) -> Vec<u8>;
1316
1317    /// Returns the byte representation in a little endian byte array,
1318    /// with trailing zeros.
1319    /// # Example
1320    ///
1321    /// ```
1322    /// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
1323    ///
1324    /// let one = B::from(1u64);
1325    /// let arr = one.to_bytes_le();
1326    /// let mut vec = vec![0; 8];
1327    /// vec[0] = 1;
1328    /// assert_eq!(arr, vec);
1329    /// ```
1330    fn to_bytes_le(&self) -> Vec<u8>;
1331
1332    /// Returns the windowed non-adjacent form of `self`, for a window of size `w`.
1333    #[inline]
1334    fn find_wnaf(&self, w: usize) -> Option<Vec<i64>> {
1335        // w > 2 due to definition of wNAF, and w < 64 to make sure that `i64`
1336        // can fit each signed digit
1337        if (2..64).contains(&w) {
1338            let mut res = Vec::new();
1339            let mut e = *self;
1340
1341            while !e.is_zero() {
1342                let z: i64;
1343                if e.is_odd() {
1344                    z = signed_mod_reduction(e.as_ref()[0], 1 << w);
1345                    if z >= 0 {
1346                        e.sub_with_borrow(&Self::from(z as u64));
1347                    } else {
1348                        e.add_with_carry(&Self::from((-z) as u64));
1349                    }
1350                } else {
1351                    z = 0;
1352                }
1353                res.push(z);
1354                e.div2();
1355            }
1356
1357            Some(res)
1358        } else {
1359            None
1360        }
1361    }
1362}