Skip to main content

malachite_bigint/
bigint.rs

1// Copyright © 2026 Steve Shi
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use alloc::string::String;
10use alloc::vec::Vec;
11use core::{
12    cmp::Ordering,
13    fmt::Debug,
14    iter::{Product, Sum},
15    ops::{
16        Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
17        DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
18        SubAssign,
19    },
20    str::FromStr,
21};
22use malachite_base::{
23    num::{
24        arithmetic::traits::{
25            Abs, DivEuclidean, DivExact, DivMod, DivModEuclidean, DivRem, DivRound, DivisibleBy,
26            Mod, ModEuclidean, Parity, Sign as _, UnsignedAbs,
27        },
28        basic::traits::{One as _, Zero as _},
29        conversion::traits::{RoundingInto, ToStringBase},
30        logic::traits::{BitAccess, NotAssign},
31    },
32    rounding_modes::RoundingMode,
33};
34use malachite_nz::integer::Integer;
35use malachite_nz::platform::SignedLimb;
36use num_integer::Roots;
37use num_traits::{
38    CheckedAdd, CheckedDiv, CheckedEuclid, CheckedMul, CheckedSub, Euclid, FromPrimitive, Num, One,
39    Pow, Signed, ToPrimitive, Zero,
40};
41use paste::paste;
42
43use crate::{
44    BigUint, ParseBigIntError,
45    Sign::{Minus, NoSign, Plus},
46    ToBigUint, TryFromBigIntError, U32Digits, U64Digits,
47};
48
49pub trait ToBigInt {
50    fn to_bigint(&self) -> Option<BigInt>;
51}
52
53apply_to_primitives!(impl_primitive_convert{BigInt, _});
54impl_primitive_convert!(BigInt, f32);
55impl_primitive_convert!(BigInt, f64);
56
57#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)]
58pub enum Sign {
59    Minus,
60    NoSign,
61    Plus,
62}
63
64impl Neg for Sign {
65    type Output = Self;
66
67    #[inline]
68    fn neg(self) -> Self::Output {
69        match self {
70            Minus => Plus,
71            NoSign => NoSign,
72            Plus => Minus,
73        }
74    }
75}
76
77#[repr(transparent)]
78#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
79pub struct BigInt(Integer);
80
81apply_to_primitives!(forward_from{BigInt, _});
82apply_to_primitives!(forward_try_into{BigInt, _});
83
84impl_from!(BigInt, Integer);
85
86forward_unary_op!(BigInt, Not, not);
87forward_unary_op!(BigInt, Neg, neg);
88
89forward_binary_self!(BigInt, Add, add);
90forward_binary_self!(BigInt, Sub, sub);
91forward_binary_self!(BigInt, Mul, mul);
92forward_binary_self!(BigInt, Div, div);
93forward_binary_self!(BigInt, Rem, rem);
94forward_binary_self!(BigInt, BitAnd, bitand);
95forward_binary_self!(BigInt, BitOr, bitor);
96forward_binary_self!(BigInt, BitXor, bitxor);
97
98forward_assign_self!(BigInt, AddAssign, add_assign);
99forward_assign_self!(BigInt, SubAssign, sub_assign);
100forward_assign_self!(BigInt, MulAssign, mul_assign);
101forward_assign_self!(BigInt, DivAssign, div_assign);
102forward_assign_self!(BigInt, RemAssign, rem_assign);
103forward_assign_self!(BigInt, BitAndAssign, bitand_assign);
104forward_assign_self!(BigInt, BitOrAssign, bitor_assign);
105forward_assign_self!(BigInt, BitXorAssign, bitxor_assign);
106
107forward_pow_biguint!(BigInt);
108
109apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Add, add});
110apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Sub, sub});
111apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Mul, mul});
112apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Div, div});
113apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Rem, rem});
114
115apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Add, add});
116apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Sub, sub});
117apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Mul, mul});
118apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Div, div});
119apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Rem, rem});
120
121apply_to_primitives!(forward_binary_right_primitive{BigInt, _, Shl, shl});
122apply_to_primitives!(forward_binary_right_primitive{BigInt, _, Shr, shr});
123
124apply_to_primitives!(forward_assign_primitive_into{BigInt, _, AddAssign, add_assign});
125apply_to_primitives!(forward_assign_primitive_into{BigInt, _, SubAssign, sub_assign});
126apply_to_primitives!(forward_assign_primitive_into{BigInt, _, MulAssign, mul_assign});
127apply_to_primitives!(forward_assign_primitive_into{BigInt, _, DivAssign, div_assign});
128apply_to_primitives!(forward_assign_primitive_into{BigInt, _, RemAssign, rem_assign});
129
130apply_to_primitives!(forward_assign_primitive{BigInt, _, ShlAssign, shl_assign});
131apply_to_primitives!(forward_assign_primitive{BigInt, _, ShrAssign, shr_assign});
132
133apply_to_unsigneds!(forward_pow_primitive{BigInt, _});
134
135impl_product_iter_type!(BigInt);
136impl_sum_iter_type!(BigInt);
137
138forward_fmt!(BigInt, Debug, Display, Binary, Octal, LowerHex, UpperHex);
139
140impl CheckedAdd for BigInt {
141    #[inline]
142    fn checked_add(&self, v: &Self) -> Option<Self> {
143        Some(self.add(v))
144    }
145}
146
147impl CheckedSub for BigInt {
148    #[inline]
149    fn checked_sub(&self, v: &Self) -> Option<Self> {
150        Some(self.sub(v))
151    }
152}
153
154impl CheckedMul for BigInt {
155    #[inline]
156    fn checked_mul(&self, v: &Self) -> Option<Self> {
157        Some(self.mul(v))
158    }
159}
160
161impl CheckedDiv for BigInt {
162    #[inline]
163    fn checked_div(&self, v: &Self) -> Option<Self> {
164        (!v.is_zero()).then(|| self.div(v))
165    }
166}
167
168impl ToBigInt for BigInt {
169    #[inline]
170    fn to_bigint(&self) -> Option<BigInt> {
171        Some(self.clone())
172    }
173}
174
175impl ToBigUint for BigInt {
176    #[inline]
177    fn to_biguint(&self) -> Option<BigUint> {
178        (!self.is_negative()).then(|| self.magnitude().clone())
179    }
180}
181
182impl ToPrimitive for BigInt {
183    apply_to_primitives!(impl_to_primitive_fn_try_into{_});
184    impl_to_primitive_fn_float!(f32);
185    impl_to_primitive_fn_float!(f64);
186}
187
188impl FromPrimitive for BigInt {
189    apply_to_primitives!(impl_from_primitive_fn_infallible{_});
190    impl_from_primitive_fn_float!(f32);
191    impl_from_primitive_fn_float!(f64);
192}
193
194impl From<BigUint> for BigInt {
195    #[inline]
196    fn from(value: BigUint) -> Self {
197        Integer::from(value.0).into()
198    }
199}
200
201impl Zero for BigInt {
202    #[inline]
203    fn zero() -> Self {
204        Self(Integer::ZERO)
205    }
206
207    #[inline]
208    fn is_zero(&self) -> bool {
209        self.sign() == NoSign
210    }
211}
212
213impl One for BigInt {
214    #[inline]
215    fn one() -> Self {
216        Self(Integer::ONE)
217    }
218}
219
220impl Signed for BigInt {
221    #[inline]
222    fn abs(&self) -> Self {
223        (&self.0).abs().into()
224    }
225
226    #[inline]
227    fn abs_sub(&self, other: &Self) -> Self {
228        if self <= other {
229            Self::zero()
230        } else {
231            self - other
232        }
233    }
234
235    #[inline]
236    fn signum(&self) -> Self {
237        match self.sign() {
238            Minus => -Self::one(),
239            NoSign => Self::zero(),
240            Plus => Self::one(),
241        }
242    }
243
244    #[inline]
245    fn is_positive(&self) -> bool {
246        self.sign() == Plus
247    }
248
249    #[inline]
250    fn is_negative(&self) -> bool {
251        self.sign() == Minus
252    }
253}
254
255impl Num for BigInt {
256    type FromStrRadixErr = ParseBigIntError;
257
258    #[inline]
259    fn from_str_radix(mut s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
260        let sign = if s.starts_with('-') {
261            let tail = &s[1..];
262            if !tail.starts_with('+') {
263                s = tail;
264            }
265            Minus
266        } else {
267            Plus
268        };
269        let u = BigUint::from_str_radix(s, radix)?;
270        Ok(Self::from_biguint(sign, u))
271    }
272}
273
274impl num_integer::Integer for BigInt {
275    #[inline]
276    fn div_floor(&self, other: &Self) -> Self {
277        (&self.0).div_round(&other.0, RoundingMode::Floor).0.into()
278    }
279
280    #[inline]
281    fn mod_floor(&self, other: &Self) -> Self {
282        (&self.0).mod_op(&other.0).into()
283    }
284
285    #[inline]
286    fn gcd(&self, other: &Self) -> Self {
287        self.magnitude().gcd(other.magnitude()).into()
288    }
289
290    #[inline]
291    fn lcm(&self, other: &Self) -> Self {
292        self.magnitude().lcm(other.magnitude()).into()
293    }
294
295    #[inline]
296    fn divides(&self, other: &Self) -> bool {
297        Self::is_multiple_of(self, other)
298    }
299
300    #[inline]
301    fn is_multiple_of(&self, other: &Self) -> bool {
302        (&self.0).divisible_by(&other.0)
303    }
304
305    #[inline]
306    fn is_even(&self) -> bool {
307        self.0.even()
308    }
309
310    #[inline]
311    fn is_odd(&self) -> bool {
312        self.0.odd()
313    }
314
315    #[inline]
316    fn div_rem(&self, other: &Self) -> (Self, Self) {
317        let (div, rem) = (&self.0).div_rem(&other.0);
318        (div.into(), rem.into())
319    }
320
321    #[inline]
322    fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
323        let (div, rem) = (&self.0).div_mod(&other.0);
324        (div.into(), rem.into())
325    }
326
327    #[inline]
328    fn div_ceil(&self, other: &Self) -> Self {
329        (&self.0)
330            .div_round(&other.0, RoundingMode::Ceiling)
331            .0
332            .into()
333    }
334
335    #[inline]
336    fn gcd_lcm(&self, other: &Self) -> (Self, Self) {
337        let (gcd, lcm) = self.magnitude().gcd_lcm(other.magnitude());
338        (gcd.into(), lcm.into())
339    }
340
341    #[inline]
342    fn extended_gcd_lcm(&self, other: &Self) -> (num_integer::ExtendedGcd<Self>, Self) {
343        let egcd = self.extended_gcd(other);
344        let lcm = if egcd.gcd.is_zero() {
345            Self::zero()
346        } else {
347            Self((&self.0).div_exact(&egcd.gcd.0) * &other.0).abs()
348        };
349        (egcd, lcm)
350    }
351
352    #[inline]
353    fn next_multiple_of(&self, other: &Self) -> Self {
354        let rem = (&self.0).mod_op(&other.0);
355        if rem == 0u32 {
356            self.clone()
357        } else {
358            Self(&self.0 + &other.0 - rem)
359        }
360    }
361
362    #[inline]
363    fn prev_multiple_of(&self, other: &Self) -> Self {
364        Self(&self.0 - (&self.0).mod_op(&other.0))
365    }
366
367    #[inline]
368    fn dec(&mut self) {
369        self.0 -= Integer::ONE;
370    }
371
372    #[inline]
373    fn inc(&mut self) {
374        self.0 += Integer::ONE;
375    }
376}
377
378impl Mul for Sign {
379    type Output = Self;
380
381    #[inline]
382    fn mul(self, other: Self) -> Self {
383        match (self, other) {
384            (NoSign, _) | (_, NoSign) => NoSign,
385            (Plus, Plus) | (Minus, Minus) => Plus,
386            (Plus, Minus) | (Minus, Plus) => Minus,
387        }
388    }
389}
390
391impl Roots for BigInt {
392    #[inline]
393    fn nth_root(&self, n: u32) -> Self {
394        // num-bigint truncates toward zero, taking the root of the magnitude and reapplying the
395        // sign; `Integer`'s `FloorRoot` floors instead, which differs for negative inputs that are
396        // not perfect powers.
397        assert!(
398            !(self.is_negative() && n.even()),
399            "root of degree {n} is imaginary"
400        );
401        Self::from_biguint(self.sign(), self.magnitude().nth_root(n))
402    }
403}
404
405impl FromStr for BigInt {
406    type Err = ParseBigIntError;
407
408    #[inline]
409    fn from_str(s: &str) -> Result<Self, Self::Err> {
410        Self::from_str_radix(s, 10)
411    }
412}
413
414impl BigInt {
415    #[inline]
416    pub fn new(sign: Sign, digits: Vec<u32>) -> Self {
417        Self::from_biguint(sign, BigUint::new(digits))
418    }
419
420    #[inline]
421    pub fn from_biguint(sign: Sign, mut abs: BigUint) -> Self {
422        if sign == NoSign {
423            abs = BigUint::zero();
424        }
425
426        Integer::from_sign_and_abs(sign != Minus, abs.0).into()
427    }
428
429    #[inline]
430    pub fn from_slice(sign: Sign, slice: &[u32]) -> Self {
431        Self::from_biguint(sign, BigUint::from_slice(slice))
432    }
433
434    #[inline]
435    pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) {
436        if sign == NoSign {
437            self.set_zero();
438        } else {
439            *self = Self::from_slice(sign, slice);
440        }
441    }
442
443    #[inline]
444    pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> Self {
445        Self::from_biguint(sign, BigUint::from_bytes_be(bytes))
446    }
447
448    #[inline]
449    pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> Self {
450        Self::from_biguint(sign, BigUint::from_bytes_le(bytes))
451    }
452
453    #[inline]
454    pub fn from_signed_bytes_be(digits: &[u8]) -> Self {
455        let is_negative = match digits.first().copied() {
456            Some(x) => x > 0x7f,
457            None => return Self::zero(),
458        };
459
460        if is_negative {
461            let mut v = Vec::from(digits);
462            twos_complement_be(&mut v);
463            let u = BigUint::from_bytes_be(v.as_slice());
464            Self::from_biguint(Minus, u)
465        } else {
466            let u = BigUint::from_bytes_be(digits);
467            Self::from_biguint(Plus, u)
468        }
469    }
470
471    #[inline]
472    pub fn from_signed_bytes_le(digits: &[u8]) -> Self {
473        let is_negative = match digits.last().copied() {
474            Some(x) => x > 0x7f,
475            None => return Self::zero(),
476        };
477
478        if is_negative {
479            let mut v = Vec::from(digits);
480            twos_complement_le(&mut v);
481            let u = BigUint::from_bytes_le(v.as_slice());
482            Self::from_biguint(Minus, u)
483        } else {
484            let u = BigUint::from_bytes_le(digits);
485            Self::from_biguint(Plus, u)
486        }
487    }
488
489    #[inline]
490    pub fn parse_bytes(bytes: &[u8], radix: u32) -> Option<Self> {
491        let s = core::str::from_utf8(bytes).ok()?;
492        Self::from_str_radix(s, radix).ok()
493    }
494
495    #[inline]
496    pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option<Self> {
497        BigUint::from_radix_be(buf, radix).map(|u| Self::from_biguint(sign, u))
498    }
499
500    #[inline]
501    pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option<Self> {
502        BigUint::from_radix_le(buf, radix).map(|u| Self::from_biguint(sign, u))
503    }
504
505    #[inline]
506    pub fn to_bytes_be(&self) -> (Sign, Vec<u8>) {
507        (self.sign(), self.magnitude().to_bytes_be())
508    }
509
510    #[inline]
511    pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
512        (self.sign(), self.magnitude().to_bytes_le())
513    }
514
515    #[inline]
516    pub fn to_u32_digits(&self) -> (Sign, Vec<u32>) {
517        (self.sign(), self.magnitude().to_u32_digits())
518    }
519
520    #[inline]
521    pub fn to_u64_digits(&self) -> (Sign, Vec<u64>) {
522        (self.sign(), self.magnitude().to_u64_digits())
523    }
524
525    #[inline]
526    pub fn iter_u32_digits(&self) -> U32Digits<'_> {
527        self.magnitude().iter_u32_digits()
528    }
529
530    #[inline]
531    pub fn iter_u64_digits(&self) -> U64Digits<'_> {
532        self.magnitude().iter_u64_digits()
533    }
534
535    #[inline]
536    pub fn to_signed_bytes_be(&self) -> Vec<u8> {
537        let mut bytes = self.magnitude().to_bytes_be();
538        let first_byte = bytes.first().copied().unwrap_or(0);
539        let is_negative = self.is_negative();
540        if first_byte > 0x7f
541            && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && is_negative)
542        {
543            // msb used by magnitude, extend by 1 byte
544            bytes.insert(0, 0);
545        }
546        if self.is_negative() {
547            twos_complement_be(&mut bytes);
548        }
549        bytes
550    }
551
552    #[inline]
553    pub fn to_signed_bytes_le(&self) -> Vec<u8> {
554        let mut bytes = self.magnitude().to_bytes_le();
555        let is_negative = self.is_negative();
556        let last_byte = bytes.last().copied().unwrap_or(0);
557        if last_byte > 0x7f
558            && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero) && is_negative)
559        {
560            // msb used by magnitude, extend by 1 byte
561            bytes.push(0);
562        }
563        if self.is_negative() {
564            twos_complement_le(&mut bytes);
565        }
566        bytes
567    }
568
569    #[inline]
570    pub fn to_str_radix(&self, radix: u32) -> String {
571        self.0.to_string_base(radix as u8)
572    }
573
574    #[inline]
575    pub fn to_radix_be(&self, radix: u32) -> (Sign, Vec<u8>) {
576        (self.sign(), self.magnitude().to_radix_be(radix))
577    }
578
579    #[inline]
580    pub fn to_radix_le(&self, radix: u32) -> (Sign, Vec<u8>) {
581        (self.sign(), self.magnitude().to_radix_le(radix))
582    }
583
584    #[inline]
585    pub fn sign(&self) -> Sign {
586        match self.0.sign() {
587            Ordering::Less => Minus,
588            Ordering::Equal => NoSign,
589            Ordering::Greater => Plus,
590        }
591    }
592
593    #[inline]
594    pub fn magnitude(&self) -> &BigUint {
595        unsafe { core::mem::transmute(self.0.unsigned_abs_ref()) }
596    }
597
598    #[inline]
599    pub fn into_parts(self) -> (Sign, BigUint) {
600        (self.sign(), self.0.unsigned_abs().into())
601    }
602
603    #[inline]
604    pub fn bits(&self) -> u64 {
605        self.magnitude().bits()
606    }
607
608    #[inline]
609    pub fn to_biguint(&self) -> Option<BigUint> {
610        match self.sign() {
611            Plus => Some(self.magnitude().clone()),
612            NoSign => Some(BigUint::zero()),
613            Minus => None,
614        }
615    }
616
617    #[inline]
618    pub fn checked_add(&self, v: &Self) -> Option<Self> {
619        Some(self + v)
620    }
621
622    #[inline]
623    pub fn checked_sub(&self, v: &Self) -> Option<Self> {
624        Some(self - v)
625    }
626
627    #[inline]
628    pub fn checked_mul(&self, v: &Self) -> Option<Self> {
629        Some(self * v)
630    }
631
632    #[inline]
633    pub fn checked_div(&self, v: &Self) -> Option<Self> {
634        if v.is_zero() {
635            return None;
636        }
637        Some(self / v)
638    }
639
640    #[inline]
641    pub fn pow(&self, exponent: u32) -> Self {
642        Pow::pow(self, exponent)
643    }
644
645    #[inline]
646    pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
647        assert!(
648            !exponent.is_negative(),
649            "negative exponentiation is not supported!"
650        );
651        assert!(
652            !modulus.is_zero(),
653            "attempt to calculate with zero modulus!"
654        );
655
656        let mut abs = self
657            .magnitude()
658            .modpow(exponent.magnitude(), modulus.magnitude());
659
660        if abs.is_zero() {
661            return Self::zero();
662        }
663
664        if (self.is_negative() && exponent.0.odd()) != modulus.is_negative() {
665            abs = modulus.magnitude() - abs;
666        }
667
668        Self::from_biguint(modulus.sign(), abs)
669    }
670
671    #[inline]
672    pub fn sqrt(&self) -> Self {
673        Roots::sqrt(self)
674    }
675
676    #[inline]
677    pub fn cbrt(&self) -> Self {
678        Roots::cbrt(self)
679    }
680
681    #[inline]
682    pub fn nth_root(&self, n: u32) -> Self {
683        Roots::nth_root(self, n)
684    }
685
686    #[inline]
687    pub fn trailing_zeros(&self) -> Option<u64> {
688        self.magnitude().trailing_zeros()
689    }
690
691    #[inline]
692    pub fn bit(&self, bit: u64) -> bool {
693        self.0.get_bit(bit)
694    }
695
696    #[inline]
697    pub fn set_bit(&mut self, bit: u64, value: bool) {
698        if value {
699            self.0.set_bit(bit);
700        } else {
701            self.0.clear_bit(bit);
702        }
703    }
704}
705/// Perform in-place two's complement of the given binary representation, in little-endian byte
706/// order.
707#[inline]
708fn twos_complement_le(digits: &mut [u8]) {
709    twos_complement(digits);
710}
711
712/// Perform in-place two's complement of the given binary representation in big-endian byte order.
713#[inline]
714fn twos_complement_be(digits: &mut [u8]) {
715    twos_complement(digits.iter_mut().rev());
716}
717
718/// Perform in-place two's complement of the given digit iterator starting from the least
719/// significant byte.
720#[inline]
721fn twos_complement<'a, I>(digits: I)
722where
723    I: IntoIterator<Item = &'a mut u8>,
724{
725    let mut carry = true;
726    for d in digits {
727        d.not_assign();
728        if carry {
729            *d = d.wrapping_add(1);
730            carry = d.is_zero();
731        }
732    }
733}
734
735impl BigInt {
736    /// Creates a constant [`BigInt`] from a primitive [`i32`] value.
737    ///
738    /// Non-`const` callers should use [`From<i32>`] instead.
739    #[inline]
740    pub const fn new_const(n: i32) -> Self {
741        Self(Integer::const_from_signed(n as SignedLimb))
742    }
743
744    /// Converts this owned [`BigInt`] into a [`BigUint`], if it is not negative.
745    #[inline]
746    pub fn into_biguint(self) -> Option<BigUint> {
747        if self.is_negative() {
748            None
749        } else {
750            Some(BigUint(self.0.unsigned_abs()))
751        }
752    }
753
754    /// Returns the modular multiplicative inverse of `self` modulo `modulus`, or `None` if no
755    /// inverse exists.
756    ///
757    /// # Panics
758    /// Panics if `modulus` is zero.
759    pub fn modinv(&self, modulus: &Self) -> Option<Self> {
760        let result = self.magnitude().modinv(modulus.magnitude())?;
761        // The sign of the result follows the modulus, as `mod_floor` does.
762        let (sign, magnitude) = match (self.is_negative(), modulus.is_negative()) {
763            (false, false) => (Sign::Plus, result),
764            (true, false) => (Sign::Plus, modulus.magnitude() - result),
765            (false, true) => (Sign::Minus, modulus.magnitude() - result),
766            (true, true) => (Sign::Minus, result),
767        };
768        Some(Self::from_biguint(sign, magnitude))
769    }
770}
771
772impl num_traits::ConstZero for BigInt {
773    const ZERO: Self = Self::new_const(0);
774}
775
776impl num_traits::ConstOne for BigInt {
777    const ONE: Self = Self::new_const(1);
778}
779
780impl From<bool> for BigInt {
781    #[inline]
782    fn from(x: bool) -> Self {
783        if x { Self::one() } else { Self::zero() }
784    }
785}
786
787impl Euclid for BigInt {
788    #[inline]
789    fn div_euclid(&self, v: &Self) -> Self {
790        (&self.0).div_euclidean(&v.0).into()
791    }
792
793    #[inline]
794    fn rem_euclid(&self, v: &Self) -> Self {
795        // The Euclidean remainder is non-negative, so Malachite returns a `Natural`.
796        Integer::from((&self.0).mod_euclidean(&v.0)).into()
797    }
798
799    #[inline]
800    fn div_rem_euclid(&self, v: &Self) -> (Self, Self) {
801        let (q, r) = (&self.0).div_mod_euclidean(&v.0);
802        (q.into(), Integer::from(r).into())
803    }
804}
805
806impl CheckedEuclid for BigInt {
807    #[inline]
808    fn checked_div_euclid(&self, v: &Self) -> Option<Self> {
809        if v.is_zero() {
810            return None;
811        }
812        Some(self.div_euclid(v))
813    }
814
815    #[inline]
816    fn checked_rem_euclid(&self, v: &Self) -> Option<Self> {
817        if v.is_zero() {
818            return None;
819        }
820        Some(self.rem_euclid(v))
821    }
822
823    #[inline]
824    fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> {
825        if v.is_zero() {
826            return None;
827        }
828        Some(self.div_rem_euclid(v))
829    }
830}
831
832impl num_traits::FromBytes for BigInt {
833    type Bytes = [u8];
834
835    #[inline]
836    fn from_be_bytes(bytes: &Self::Bytes) -> Self {
837        Self::from_signed_bytes_be(bytes)
838    }
839
840    #[inline]
841    fn from_le_bytes(bytes: &Self::Bytes) -> Self {
842        Self::from_signed_bytes_le(bytes)
843    }
844}
845
846impl num_traits::ToBytes for BigInt {
847    type Bytes = Vec<u8>;
848
849    #[inline]
850    fn to_be_bytes(&self) -> Self::Bytes {
851        self.to_signed_bytes_be()
852    }
853
854    #[inline]
855    fn to_le_bytes(&self) -> Self::Bytes {
856        self.to_signed_bytes_le()
857    }
858}
859
860#[cfg(test)]
861mod test {
862    use super::*;
863    use alloc::{format, string::ToString};
864
865    #[test]
866    fn test_float_convert_nearest() {
867        let n25 = "10000000000000000000000000";
868        let val = BigInt::from_str(n25).unwrap();
869        let f = val.to_f64().unwrap();
870        assert_eq!(f.to_string(), n25);
871    }
872
873    #[test]
874    fn test_to_f64() {
875        use num_traits::ToPrimitive as NumToPrimitive;
876
877        let test_cases = [
878            "123456789012345678901234567890",
879            "999999999999999999999999999999",
880            "170141183460469231731687303715884105727",
881            "340282366920938463463374607431768211455",
882            "12345678901234567890123456789012345678901234567890",
883            "-123456789012345678901234567890",
884            "-999999999999999999999999999999",
885            "-170141183460469231731687303715884105728",
886            "-12345678901234567890123456789012345678901234567890",
887            "1208925819614629174706176",
888            "1329227995784915872903807060280344576",
889            "-1208925819614629174706176",
890            "-1329227995784915872903807060280344576",
891            // Overflow cases
892            "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
893            99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
894            99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
895            9999999999999999999999999999999999999999999999999999",
896            "-999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
897            99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
898            99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
899            99999999999999999999999999999999999999999999999999999",
900        ];
901
902        for test_str in &test_cases {
903            let malachite_val = BigInt::from_str(test_str).unwrap();
904            let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap();
905
906            assert_eq!(
907                malachite_val.to_f64(),
908                num_bigint_val.to_f64(),
909                "to_f64 mismatch for {test_str}",
910            );
911        }
912    }
913
914    #[test]
915    fn test_to_f32() {
916        use num_traits::ToPrimitive as NumToPrimitive;
917
918        let test_cases = [
919            "12345678901234567890",
920            "999999999999999999999999",
921            "-12345678901234567890",
922            "-999999999999999999999999",
923            "340282366920938463463374607431768211455",
924        ];
925
926        for test_str in &test_cases {
927            let malachite_val = BigInt::from_str(test_str).unwrap();
928            let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap();
929
930            assert_eq!(
931                malachite_val.to_f32(),
932                num_bigint_val.to_f32(),
933                "to_f32 mismatch for {test_str}",
934            );
935        }
936    }
937
938    #[test]
939    fn test_to_i64() {
940        use num_traits::ToPrimitive as NumToPrimitive;
941
942        let test_cases = [
943            "0",
944            "123",
945            "-456",
946            "9223372036854775807",  // i64::MAX
947            "-9223372036854775808", // i64::MIN
948            "9223372036854775808",  // overflow
949            "-9223372036854775809", // overflow
950        ];
951
952        for test_str in &test_cases {
953            let malachite_val = BigInt::from_str(test_str).unwrap();
954            let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap();
955
956            assert_eq!(
957                malachite_val.to_i64(),
958                num_bigint_val.to_i64(),
959                "to_i64 mismatch for {test_str}",
960            );
961        }
962    }
963
964    #[test]
965    fn test_to_u64() {
966        use num_traits::ToPrimitive as NumToPrimitive;
967
968        let test_cases = [
969            "0",
970            "123",
971            "18446744073709551615", // u64::MAX
972            "18446744073709551616", // overflow
973            "-1",                   // negative
974        ];
975
976        for test_str in &test_cases {
977            let malachite_val = BigInt::from_str(test_str).unwrap();
978            let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap();
979
980            assert_eq!(
981                malachite_val.to_u64(),
982                num_bigint_val.to_u64(),
983                "to_u64 mismatch for {test_str}",
984            );
985        }
986    }
987
988    #[test]
989    fn test_arithmetic() {
990        let test_cases = [
991            ("123456789", "987654321"),
992            ("999999999999999999", "1"),
993            ("-123456789", "987654321"),
994            ("123456789", "-987654321"),
995            ("-123456789", "-987654321"),
996        ];
997
998        for (a_str, b_str) in &test_cases {
999            let ma = BigInt::from_str(a_str).unwrap();
1000            let mb = BigInt::from_str(b_str).unwrap();
1001            let na = num_bigint::BigInt::from_str(a_str).unwrap();
1002            let nb = num_bigint::BigInt::from_str(b_str).unwrap();
1003
1004            assert_eq!((&ma + &mb).to_string(), (&na + &nb).to_string(), "add");
1005            assert_eq!((&ma - &mb).to_string(), (&na - &nb).to_string(), "sub");
1006            assert_eq!((&ma * &mb).to_string(), (&na * &nb).to_string(), "mul");
1007            if *b_str != "0" {
1008                assert_eq!((&ma / &mb).to_string(), (&na / &nb).to_string(), "div");
1009                assert_eq!((&ma % &mb).to_string(), (&na % &nb).to_string(), "rem");
1010            }
1011        }
1012    }
1013
1014    #[test]
1015    fn test_checked_arithmetic() {
1016        let test_cases = [
1017            ("123456789", "987654321"),
1018            ("999999999999999999", "1"),
1019            ("-123456789", "987654321"),
1020        ];
1021
1022        for (a_str, b_str) in &test_cases {
1023            let ma = BigInt::from_str(a_str).unwrap();
1024            let mb = BigInt::from_str(b_str).unwrap();
1025            let na = num_bigint::BigInt::from_str(a_str).unwrap();
1026            let nb = num_bigint::BigInt::from_str(b_str).unwrap();
1027
1028            assert_eq!(
1029                ma.checked_add(&mb).map(|v| v.to_string()),
1030                na.checked_add(&nb).map(|v| v.to_string()),
1031                "checked_add"
1032            );
1033            assert_eq!(
1034                ma.checked_sub(&mb).map(|v| v.to_string()),
1035                na.checked_sub(&nb).map(|v| v.to_string()),
1036                "checked_sub"
1037            );
1038            assert_eq!(
1039                ma.checked_mul(&mb).map(|v| v.to_string()),
1040                na.checked_mul(&nb).map(|v| v.to_string()),
1041                "checked_mul"
1042            );
1043            assert_eq!(
1044                ma.checked_div(&mb).map(|v| v.to_string()),
1045                na.checked_div(&nb).map(|v| v.to_string()),
1046                "checked_div"
1047            );
1048        }
1049    }
1050
1051    #[test]
1052    fn test_sign() {
1053        use num_traits::Signed;
1054
1055        let test_cases = [
1056            "0",
1057            "123",
1058            "-456",
1059            "999999999999999999",
1060            "-999999999999999999",
1061        ];
1062
1063        for test_str in &test_cases {
1064            let ma = BigInt::from_str(test_str).unwrap();
1065            let na = num_bigint::BigInt::from_str(test_str).unwrap();
1066
1067            assert_eq!(
1068                ma.is_positive(),
1069                na.is_positive(),
1070                "is_positive for {test_str}",
1071            );
1072            assert_eq!(
1073                ma.is_negative(),
1074                na.is_negative(),
1075                "is_negative for {test_str}",
1076            );
1077            assert_eq!(
1078                ma.abs().to_string(),
1079                na.abs().to_string(),
1080                "abs for {test_str}",
1081            );
1082        }
1083    }
1084
1085    #[test]
1086    fn test_pow() {
1087        use num_traits::Pow;
1088
1089        let test_cases = [("2", 10u32), ("10", 20u32), ("-3", 5u32), ("123", 4u32)];
1090
1091        for (base_str, exp) in &test_cases {
1092            let ma = BigInt::from_str(base_str).unwrap();
1093            let na = num_bigint::BigInt::from_str(base_str).unwrap();
1094
1095            assert_eq!(
1096                ma.pow(*exp).to_string(),
1097                na.pow(*exp).to_string(),
1098                "pow for {base_str}^{exp}",
1099            );
1100        }
1101    }
1102
1103    #[test]
1104    fn test_to_signed_bytes() {
1105        let sysmax = i64::MAX;
1106        let i = BigInt::from(sysmax);
1107        let b = i.to_signed_bytes_le();
1108        let i2 = BigInt::from_signed_bytes_le(&b);
1109        assert_eq!(i, i2);
1110    }
1111
1112    #[test]
1113    fn test_display_bigint() {
1114        let n = BigInt::from_str("1234567890").unwrap();
1115        assert_eq!(format!("{n}"), "1234567890");
1116    }
1117}