Skip to main content

malachite_bigint/
biguint.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::{Equal, Greater, Less},
13    iter::{Product, Sum},
14    ops::{
15        Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
16        DivAssign, Mul, MulAssign, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
17    },
18    str::FromStr,
19};
20use malachite_base::{
21    num::{
22        arithmetic::traits::{
23            DivRem, DivRound, DivisibleBy, FloorRoot, Gcd, Lcm, Mod, ModPow, Parity,
24        },
25        conversion::traits::{Digits, FromStringBase, PowerOf2Digits, RoundingInto, ToStringBase},
26        logic::traits::{BitAccess, BitIterable, CountOnes, SignificantBits},
27    },
28    rounding_modes::RoundingMode,
29};
30use malachite_nz::{integer::Integer, natural::Natural};
31use num_integer::Roots;
32use num_traits::{
33    CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, ToPrimitive,
34    Unsigned, Zero,
35};
36use paste::paste;
37
38use crate::{ParseBigIntError, ToBigInt, TryFromBigIntError, U32Digits, U64Digits};
39
40pub trait ToBigUint {
41    fn to_biguint(&self) -> Option<BigUint>;
42}
43
44apply_to_primitives!(impl_primitive_convert{BigUint, _});
45impl_primitive_convert!(BigUint, f32);
46impl_primitive_convert!(BigUint, f64);
47
48#[repr(transparent)]
49#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
50pub struct BigUint(pub(crate) Natural);
51
52apply_to_unsigneds!(forward_from{BigUint, _});
53apply_to_signeds!(forward_try_from{BigUint, _});
54apply_to_primitives!(forward_try_into{BigUint, _});
55
56impl_from!(BigUint, Natural);
57
58forward_binary_self!(BigUint, Add, add);
59forward_binary_self!(BigUint, Sub, sub);
60forward_binary_self!(BigUint, Mul, mul);
61forward_binary_self!(BigUint, Div, div);
62forward_binary_self!(BigUint, Rem, rem);
63forward_binary_self!(BigUint, BitAnd, bitand);
64forward_binary_self!(BigUint, BitOr, bitor);
65forward_binary_self!(BigUint, BitXor, bitxor);
66
67forward_assign_self!(BigUint, AddAssign, add_assign);
68forward_assign_self!(BigUint, SubAssign, sub_assign);
69forward_assign_self!(BigUint, MulAssign, mul_assign);
70forward_assign_self!(BigUint, DivAssign, div_assign);
71forward_assign_self!(BigUint, RemAssign, rem_assign);
72forward_assign_self!(BigUint, BitAndAssign, bitand_assign);
73forward_assign_self!(BigUint, BitOrAssign, bitor_assign);
74forward_assign_self!(BigUint, BitXorAssign, bitxor_assign);
75
76forward_pow_biguint!(BigUint);
77
78apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Add, add});
79apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Sub, sub});
80apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Mul, mul});
81apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Div, div});
82apply_to_unsigneds!(forward_binary_right_primitive_into{BigUint, _, Rem, rem});
83
84apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Add, add});
85apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Sub, sub});
86apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Mul, mul});
87apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Div, div});
88apply_to_unsigneds!(forward_binary_left_primitive_into{_, BigUint, Rem, rem});
89
90apply_to_primitives!(forward_binary_right_primitive{BigUint, _, Shl, shl});
91apply_to_primitives!(forward_binary_right_primitive{BigUint, _, Shr, shr});
92
93apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, AddAssign, add_assign});
94apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, SubAssign, sub_assign});
95apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, MulAssign, mul_assign});
96apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, DivAssign, div_assign});
97apply_to_unsigneds!(forward_assign_primitive_into{BigUint, _, RemAssign, rem_assign});
98
99apply_to_primitives!(forward_assign_primitive{BigUint, _, ShlAssign, shl_assign});
100apply_to_primitives!(forward_assign_primitive{BigUint, _, ShrAssign, shr_assign});
101
102apply_to_unsigneds!(forward_pow_primitive{BigUint, _});
103
104impl_product_iter_type!(BigUint);
105impl_sum_iter_type!(BigUint);
106
107forward_fmt!(BigUint, Debug, Display, Binary, Octal, LowerHex, UpperHex);
108
109impl CheckedAdd for BigUint {
110    #[inline]
111    fn checked_add(&self, v: &Self) -> Option<Self> {
112        Some(self.add(v))
113    }
114}
115
116impl CheckedSub for BigUint {
117    #[inline]
118    fn checked_sub(&self, v: &Self) -> Option<Self> {
119        match self.cmp(v) {
120            Less => None,
121            Equal => Some(Self::zero()),
122            Greater => Some(self.sub(v)),
123        }
124    }
125}
126
127impl CheckedMul for BigUint {
128    #[inline]
129    fn checked_mul(&self, v: &Self) -> Option<Self> {
130        Some(self.mul(v))
131    }
132}
133
134impl CheckedDiv for BigUint {
135    #[inline]
136    fn checked_div(&self, v: &Self) -> Option<Self> {
137        (!v.is_zero()).then(|| self.div(v))
138    }
139}
140
141impl ToBigUint for BigUint {
142    #[inline]
143    fn to_biguint(&self) -> Option<BigUint> {
144        Some(self.clone())
145    }
146}
147
148impl ToBigInt for BigUint {
149    #[inline]
150    fn to_bigint(&self) -> Option<crate::BigInt> {
151        Some(Integer::from(&self.0).into())
152    }
153}
154
155impl ToPrimitive for BigUint {
156    apply_to_primitives!(impl_to_primitive_fn_try_into{_});
157    impl_to_primitive_fn_float!(f32);
158    impl_to_primitive_fn_float!(f64);
159}
160
161impl FromPrimitive for BigUint {
162    apply_to_signeds!(impl_from_primitive_fn_try_from{_});
163    apply_to_unsigneds!(impl_from_primitive_fn_infallible{_});
164    impl_from_primitive_fn_float!(f32);
165    impl_from_primitive_fn_float!(f64);
166}
167
168impl Zero for BigUint {
169    #[inline]
170    fn zero() -> Self {
171        Self(<Natural as malachite_base::num::basic::traits::Zero>::ZERO)
172    }
173
174    #[inline]
175    fn is_zero(&self) -> bool {
176        *self == Self::zero()
177    }
178}
179
180impl One for BigUint {
181    #[inline]
182    fn one() -> Self {
183        Self(<Natural as malachite_base::num::basic::traits::One>::ONE)
184    }
185}
186
187impl Unsigned for BigUint {}
188
189impl Num for BigUint {
190    type FromStrRadixErr = ParseBigIntError;
191
192    fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
193        let mut s = s;
194        if s.starts_with('+') {
195            let tail = &s[1..];
196            if !tail.starts_with('+') {
197                s = tail;
198            }
199        }
200
201        // FIXME: workaround, remove the check if malachite issue fixed
202        // https://github.com/mhogrefe/malachite/issues/20
203        if radix == 16
204            && s.bytes().any(|x| {
205                !matches!(x,
206                    b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F' | b'_'
207                )
208            })
209        {
210            return Err(ParseBigIntError::invalid());
211        }
212
213        // fast path
214        if let Some(val) = Natural::from_string_base(radix as u8, s) {
215            return Ok(val.into());
216        }
217
218        if s.is_empty() {
219            return Err(ParseBigIntError::empty());
220        }
221
222        if s.starts_with('_') {
223            // Must lead with a real digit!
224            return Err(ParseBigIntError::invalid());
225        }
226
227        let v: Vec<u8> = s.bytes().filter(|&x| x != b'_').collect();
228        let s = core::str::from_utf8(v.as_slice()).map_err(|_| ParseBigIntError::invalid())?;
229        Natural::from_string_base(radix as u8, s)
230            .map(Self)
231            .ok_or_else(ParseBigIntError::invalid)
232    }
233}
234
235impl num_integer::Integer for BigUint {
236    #[inline]
237    fn div_floor(&self, other: &Self) -> Self {
238        (&self.0).div_round(&other.0, RoundingMode::Floor).0.into()
239    }
240
241    #[inline]
242    fn mod_floor(&self, other: &Self) -> Self {
243        (&self.0).mod_op(&other.0).into()
244    }
245
246    #[inline]
247    fn gcd(&self, other: &Self) -> Self {
248        (&self.0).gcd(&other.0).into()
249    }
250
251    #[inline]
252    fn lcm(&self, other: &Self) -> Self {
253        (&self.0).lcm(&other.0).into()
254    }
255
256    #[inline]
257    fn divides(&self, other: &Self) -> bool {
258        Self::is_multiple_of(self, other)
259    }
260
261    #[inline]
262    fn is_multiple_of(&self, other: &Self) -> bool {
263        (&self.0).divisible_by(&other.0)
264    }
265
266    #[inline]
267    fn is_even(&self) -> bool {
268        self.0.even()
269    }
270
271    #[inline]
272    fn is_odd(&self) -> bool {
273        self.0.odd()
274    }
275
276    #[inline]
277    fn div_rem(&self, other: &Self) -> (Self, Self) {
278        let (div, rem) = (&self.0).div_rem(&other.0);
279        (div.into(), rem.into())
280    }
281}
282
283impl Roots for BigUint {
284    #[inline]
285    fn nth_root(&self, n: u32) -> Self {
286        (&self.0).floor_root(u64::from(n)).into()
287    }
288}
289
290impl FromStr for BigUint {
291    type Err = ParseBigIntError;
292
293    #[inline]
294    fn from_str(s: &str) -> Result<Self, Self::Err> {
295        Self::from_str_radix(s, 10)
296    }
297}
298
299impl BigUint {
300    // TODO consider passing &[u32] instead (breaking change)
301    #[allow(clippy::needless_pass_by_value)]
302    #[inline]
303    pub fn new(digits: Vec<u32>) -> Self {
304        Self::from_slice(digits.as_slice())
305    }
306
307    #[inline]
308    pub fn from_slice(slice: &[u32]) -> Self {
309        let mut uint = Self::zero();
310        uint.assign_from_slice(slice);
311        uint
312    }
313
314    #[inline]
315    pub fn assign_from_slice(&mut self, slice: &[u32]) {
316        // SAFETY: &[u32] cannot have any digit greater than 2^32
317        self.0 = unsafe {
318            Natural::from_power_of_2_digits_asc(32, slice.iter().copied()).unwrap_unchecked()
319        };
320    }
321
322    #[inline]
323    pub fn from_bytes_be(bytes: &[u8]) -> Self {
324        // SAFETY: &[u8] cannot have any digit greater than 2^8
325        Self(unsafe {
326            Natural::from_power_of_2_digits_desc(8, bytes.iter().copied()).unwrap_unchecked()
327        })
328    }
329
330    #[inline]
331    pub fn from_bytes_le(bytes: &[u8]) -> Self {
332        // SAFETY: &[u8] cannot have any digit greater than 2^8
333        Self(unsafe {
334            Natural::from_power_of_2_digits_asc(8, bytes.iter().copied()).unwrap_unchecked()
335        })
336    }
337
338    #[inline]
339    pub fn parse_bytes(bytes: &[u8], radix: u32) -> Option<Self> {
340        let s = core::str::from_utf8(bytes).ok()?;
341        Self::from_str_radix(s, radix).ok()
342    }
343
344    #[inline]
345    pub fn from_radix_be(bytes: &[u8], radix: u32) -> Option<Self> {
346        if radix == 256 {
347            Some(Self::from_bytes_be(bytes))
348        } else {
349            Natural::from_digits_desc(&(radix as u8), bytes.iter().copied()).map(Self)
350        }
351    }
352
353    #[inline]
354    pub fn from_radix_le(bytes: &[u8], radix: u32) -> Option<Self> {
355        if radix == 256 {
356            Some(Self::from_bytes_le(bytes))
357        } else {
358            Natural::from_digits_asc(&(radix as u8), bytes.iter().copied()).map(Self)
359        }
360    }
361
362    #[inline]
363    pub fn to_bytes_be(&self) -> Vec<u8> {
364        self.0.to_power_of_2_digits_desc(8)
365    }
366
367    #[inline]
368    pub fn to_bytes_le(&self) -> Vec<u8> {
369        self.0.to_power_of_2_digits_asc(8)
370    }
371
372    #[inline]
373    pub fn to_u32_digits(&self) -> Vec<u32> {
374        self.0.to_power_of_2_digits_asc(32)
375    }
376
377    #[inline]
378    pub fn to_u64_digits(&self) -> Vec<u64> {
379        self.0.to_limbs_asc()
380    }
381
382    #[inline]
383    pub fn iter_u32_digits(&self) -> U32Digits<'_> {
384        U32Digits::new(self.0.limbs())
385    }
386
387    #[inline]
388    pub fn iter_u64_digits(&self) -> U64Digits<'_> {
389        U64Digits::new(self.0.limbs())
390    }
391
392    #[inline]
393    pub fn to_str_radix(&self, radix: u32) -> String {
394        self.0.to_string_base(radix as u8)
395    }
396
397    #[inline]
398    pub fn to_radix_be(&self, radix: u32) -> Vec<u8> {
399        debug_assert!(radix <= 256);
400        if radix == 256 {
401            self.to_bytes_be()
402        } else {
403            self.0.to_digits_desc(&(radix as u8))
404        }
405    }
406
407    #[inline]
408    pub fn to_radix_le(&self, radix: u32) -> Vec<u8> {
409        debug_assert!(radix <= 256);
410        if radix == 256 {
411            self.to_bytes_le()
412        } else {
413            self.0.to_digits_asc(&(radix as u8))
414        }
415    }
416
417    #[inline]
418    pub fn bits(&self) -> u64 {
419        self.0.significant_bits()
420    }
421
422    #[inline]
423    pub fn pow(&self, exponent: u32) -> Self {
424        Pow::pow(self, exponent)
425    }
426
427    #[inline]
428    pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
429        if self >= modulus {
430            let x = self % modulus;
431            x.0.mod_pow(&exponent.0, &modulus.0).into()
432        } else {
433            (&self.0).mod_pow(&exponent.0, &modulus.0).into()
434        }
435    }
436
437    #[inline]
438    pub fn cbrt(&self) -> Self {
439        Roots::cbrt(self)
440    }
441
442    #[inline]
443    pub fn nth_root(&self, n: u32) -> Self {
444        Roots::nth_root(self, n)
445    }
446
447    #[inline]
448    pub fn trailing_zeros(&self) -> Option<u64> {
449        self.0.trailing_zeros()
450    }
451
452    #[inline]
453    pub fn trailing_ones(&self) -> u64 {
454        self.0.bits().take_while(|&x| x).count() as u64
455    }
456
457    #[inline]
458    pub fn count_ones(&self) -> u64 {
459        self.0.count_ones()
460    }
461
462    #[inline]
463    pub fn bit(&self, bit: u64) -> bool {
464        self.0.get_bit(bit)
465    }
466
467    #[inline]
468    pub fn set_bit(&mut self, bit: u64, value: bool) {
469        if value {
470            self.0.set_bit(bit);
471        } else {
472            self.0.clear_bit(bit);
473        }
474    }
475}
476
477#[cfg(test)]
478mod test {
479    use super::*;
480    use alloc::format;
481
482    #[test]
483    fn test_from_string_base() {
484        assert!(BigUint::from_str_radix("1000000000000000111111100112abcdefg", 16).is_err());
485    }
486
487    #[test]
488    fn test_display_biguint() {
489        let x = BigUint::from_str_radix("1234567890", 10).unwrap();
490        assert_eq!(format!("{x}"), "1234567890");
491    }
492
493    #[test]
494    fn test_to_f64() {
495        use num_traits::ToPrimitive;
496
497        let test_cases = [
498            "123456789012345678901234567890",
499            "999999999999999999999999999999",
500            "340282366920938463463374607431768211455",
501            "12345678901234567890123456789012345678901234567890",
502            "1208925819614629174706176",
503            "1329227995784915872903807060280344576",
504            "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
505            99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
506            99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
507            9999999999999999999999999999999999999999999999999999",
508        ];
509
510        for test_str in &test_cases {
511            let malachite_val = BigUint::from_str(test_str).unwrap();
512            let num_bigint_val = num_bigint::BigUint::from_str(test_str).unwrap();
513
514            assert_eq!(
515                malachite_val.to_f64(),
516                num_bigint_val.to_f64(),
517                "to_f64 mismatch for {test_str}",
518            );
519        }
520    }
521
522    #[test]
523    fn test_to_f32() {
524        use num_traits::ToPrimitive;
525
526        let test_cases = [
527            "12345678901234567890",
528            "999999999999999999999999",
529            "340282366920938463463374607431768211455",
530        ];
531
532        for test_str in &test_cases {
533            let malachite_val = BigUint::from_str(test_str).unwrap();
534            let num_bigint_val = num_bigint::BigUint::from_str(test_str).unwrap();
535
536            assert_eq!(
537                malachite_val.to_f32(),
538                num_bigint_val.to_f32(),
539                "to_f32 mismatch for {test_str}",
540            );
541        }
542    }
543
544    #[test]
545    fn test_to_u64() {
546        use num_traits::ToPrimitive;
547
548        let test_cases = ["0", "123", "18446744073709551615", "18446744073709551616"];
549
550        for test_str in &test_cases {
551            let malachite_val = BigUint::from_str(test_str).unwrap();
552            let num_bigint_val = num_bigint::BigUint::from_str(test_str).unwrap();
553
554            assert_eq!(
555                malachite_val.to_u64(),
556                num_bigint_val.to_u64(),
557                "to_u64 mismatch for {test_str}",
558            );
559        }
560    }
561
562    #[test]
563    fn test_arithmetic() {
564        let test_cases = [
565            ("123456789", "987654321"),
566            ("999999999999999999", "1"),
567            ("1000000000000000000", "999999999999999999"),
568        ];
569
570        for (a_str, b_str) in &test_cases {
571            let ma = BigUint::from_str(a_str).unwrap();
572            let mb = BigUint::from_str(b_str).unwrap();
573            let na = num_bigint::BigUint::from_str(a_str).unwrap();
574            let nb = num_bigint::BigUint::from_str(b_str).unwrap();
575
576            assert_eq!((&ma + &mb).to_string(), (&na + &nb).to_string(), "add");
577            assert_eq!((&ma * &mb).to_string(), (&na * &nb).to_string(), "mul");
578            if ma >= mb {
579                assert_eq!((&ma - &mb).to_string(), (&na - &nb).to_string(), "sub");
580            }
581            if *b_str != "0" {
582                assert_eq!((&ma / &mb).to_string(), (&na / &nb).to_string(), "div");
583                assert_eq!((&ma % &mb).to_string(), (&na % &nb).to_string(), "rem");
584            }
585        }
586    }
587
588    #[test]
589    fn test_pow() {
590        use num_traits::Pow;
591
592        let test_cases = [("2", 10u32), ("10", 20u32), ("123", 4u32)];
593
594        for (base_str, exp) in &test_cases {
595            let ma = BigUint::from_str(base_str).unwrap();
596            let na = num_bigint::BigUint::from_str(base_str).unwrap();
597
598            assert_eq!(
599                ma.pow(*exp).to_string(),
600                na.pow(*exp).to_string(),
601                "pow for {base_str}^{exp}",
602            );
603        }
604    }
605}