1use 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, DivRem, DivRound, DivisibleBy, FloorRoot, Mod, Parity, UnsignedAbs,
26 },
27 conversion::traits::{RoundingInto, ToStringBase},
28 logic::traits::BitAccess,
29 },
30 rounding_modes::RoundingMode,
31};
32use malachite_nz::integer::Integer;
33use num_integer::Roots;
34use num_traits::{
35 CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Num, One, Pow, Signed,
36 ToPrimitive, Zero,
37};
38use paste::paste;
39
40use crate::{
41 BigUint, ParseBigIntError,
42 Sign::{Minus, NoSign, Plus},
43 ToBigUint, TryFromBigIntError, U32Digits, U64Digits,
44};
45
46pub trait ToBigInt {
47 fn to_bigint(&self) -> Option<BigInt>;
48}
49
50apply_to_primitives!(impl_primitive_convert{BigInt, _});
51impl_primitive_convert!(BigInt, f32);
52impl_primitive_convert!(BigInt, f64);
53
54#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)]
55pub enum Sign {
56 Minus,
57 NoSign,
58 Plus,
59}
60
61impl Neg for Sign {
62 type Output = Self;
63
64 #[inline]
65 fn neg(self) -> Self::Output {
66 match self {
67 Minus => Plus,
68 NoSign => NoSign,
69 Plus => Minus,
70 }
71 }
72}
73
74#[repr(transparent)]
75#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
76pub struct BigInt(Integer);
77
78apply_to_primitives!(forward_from{BigInt, _});
79apply_to_primitives!(forward_try_into{BigInt, _});
80
81impl_from!(BigInt, Integer);
82
83forward_unary_op!(BigInt, Not, not);
84forward_unary_op!(BigInt, Neg, neg);
85
86forward_binary_self!(BigInt, Add, add);
87forward_binary_self!(BigInt, Sub, sub);
88forward_binary_self!(BigInt, Mul, mul);
89forward_binary_self!(BigInt, Div, div);
90forward_binary_self!(BigInt, Rem, rem);
91forward_binary_self!(BigInt, BitAnd, bitand);
92forward_binary_self!(BigInt, BitOr, bitor);
93forward_binary_self!(BigInt, BitXor, bitxor);
94
95forward_assign_self!(BigInt, AddAssign, add_assign);
96forward_assign_self!(BigInt, SubAssign, sub_assign);
97forward_assign_self!(BigInt, MulAssign, mul_assign);
98forward_assign_self!(BigInt, DivAssign, div_assign);
99forward_assign_self!(BigInt, RemAssign, rem_assign);
100forward_assign_self!(BigInt, BitAndAssign, bitand_assign);
101forward_assign_self!(BigInt, BitOrAssign, bitor_assign);
102forward_assign_self!(BigInt, BitXorAssign, bitxor_assign);
103
104forward_pow_biguint!(BigInt);
105
106apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Add, add});
107apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Sub, sub});
108apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Mul, mul});
109apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Div, div});
110apply_to_primitives!(forward_binary_right_primitive_into{BigInt, _, Rem, rem});
111
112apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Add, add});
113apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Sub, sub});
114apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Mul, mul});
115apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Div, div});
116apply_to_primitives!(forward_binary_left_primitive_into{_, BigInt, Rem, rem});
117
118apply_to_primitives!(forward_binary_right_primitive{BigInt, _, Shl, shl});
119apply_to_primitives!(forward_binary_right_primitive{BigInt, _, Shr, shr});
120
121apply_to_primitives!(forward_assign_primitive_into{BigInt, _, AddAssign, add_assign});
122apply_to_primitives!(forward_assign_primitive_into{BigInt, _, SubAssign, sub_assign});
123apply_to_primitives!(forward_assign_primitive_into{BigInt, _, MulAssign, mul_assign});
124apply_to_primitives!(forward_assign_primitive_into{BigInt, _, DivAssign, div_assign});
125apply_to_primitives!(forward_assign_primitive_into{BigInt, _, RemAssign, rem_assign});
126
127apply_to_primitives!(forward_assign_primitive{BigInt, _, ShlAssign, shl_assign});
128apply_to_primitives!(forward_assign_primitive{BigInt, _, ShrAssign, shr_assign});
129
130apply_to_unsigneds!(forward_pow_primitive{BigInt, _});
131
132impl_product_iter_type!(BigInt);
133impl_sum_iter_type!(BigInt);
134
135forward_fmt!(BigInt, Debug, Display, Binary, Octal, LowerHex, UpperHex);
136
137impl CheckedAdd for BigInt {
138 #[inline]
139 fn checked_add(&self, v: &Self) -> Option<Self> {
140 Some(self.add(v))
141 }
142}
143
144impl CheckedSub for BigInt {
145 #[inline]
146 fn checked_sub(&self, v: &Self) -> Option<Self> {
147 Some(self.sub(v))
148 }
149}
150
151impl CheckedMul for BigInt {
152 #[inline]
153 fn checked_mul(&self, v: &Self) -> Option<Self> {
154 Some(self.mul(v))
155 }
156}
157
158impl CheckedDiv for BigInt {
159 #[inline]
160 fn checked_div(&self, v: &Self) -> Option<Self> {
161 (!v.is_zero()).then(|| self.div(v))
162 }
163}
164
165impl ToBigInt for BigInt {
166 #[inline]
167 fn to_bigint(&self) -> Option<BigInt> {
168 Some(self.clone())
169 }
170}
171
172impl ToBigUint for BigInt {
173 #[inline]
174 fn to_biguint(&self) -> Option<BigUint> {
175 (!self.is_negative()).then(|| self.magnitude().clone())
176 }
177}
178
179impl ToPrimitive for BigInt {
180 apply_to_primitives!(impl_to_primitive_fn_try_into{_});
181 impl_to_primitive_fn_float!(f32);
182 impl_to_primitive_fn_float!(f64);
183}
184
185impl FromPrimitive for BigInt {
186 apply_to_primitives!(impl_from_primitive_fn_infallible{_});
187 impl_from_primitive_fn_float!(f32);
188 impl_from_primitive_fn_float!(f64);
189}
190
191impl From<BigUint> for BigInt {
192 #[inline]
193 fn from(value: BigUint) -> Self {
194 Integer::from(value.0).into()
195 }
196}
197
198impl Zero for BigInt {
199 #[inline]
200 fn zero() -> Self {
201 Self(<Integer as malachite_base::num::basic::traits::Zero>::ZERO)
202 }
203
204 #[inline]
205 fn is_zero(&self) -> bool {
206 self.sign() == NoSign
207 }
208}
209
210impl One for BigInt {
211 #[inline]
212 fn one() -> Self {
213 Self(<Integer as malachite_base::num::basic::traits::One>::ONE)
214 }
215}
216
217impl Signed for BigInt {
218 #[inline]
219 fn abs(&self) -> Self {
220 (&self.0).abs().into()
221 }
222
223 #[inline]
224 fn abs_sub(&self, other: &Self) -> Self {
225 if self <= other {
226 Self::zero()
227 } else {
228 self - other
229 }
230 }
231
232 #[inline]
233 fn signum(&self) -> Self {
234 match self.sign() {
235 Minus => -Self::one(),
236 NoSign => Self::zero(),
237 Plus => Self::one(),
238 }
239 }
240
241 #[inline]
242 fn is_positive(&self) -> bool {
243 self.sign() == Plus
244 }
245
246 #[inline]
247 fn is_negative(&self) -> bool {
248 self.sign() == Minus
249 }
250}
251
252impl Num for BigInt {
253 type FromStrRadixErr = ParseBigIntError;
254
255 #[inline]
256 fn from_str_radix(mut s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
257 let sign = if s.starts_with('-') {
258 let tail = &s[1..];
259 if !tail.starts_with('+') {
260 s = tail;
261 }
262 Minus
263 } else {
264 Plus
265 };
266 let u = BigUint::from_str_radix(s, radix)?;
267 Ok(Self::from_biguint(sign, u))
268 }
269}
270
271impl num_integer::Integer for BigInt {
272 #[inline]
273 fn div_floor(&self, other: &Self) -> Self {
274 (&self.0).div_round(&other.0, RoundingMode::Floor).0.into()
275 }
276
277 #[inline]
278 fn mod_floor(&self, other: &Self) -> Self {
279 (&self.0).mod_op(&other.0).into()
280 }
281
282 #[inline]
283 fn gcd(&self, other: &Self) -> Self {
284 self.magnitude().gcd(other.magnitude()).into()
285 }
286
287 #[inline]
288 fn lcm(&self, other: &Self) -> Self {
289 self.magnitude().lcm(other.magnitude()).into()
290 }
291
292 #[inline]
293 fn divides(&self, other: &Self) -> bool {
294 Self::is_multiple_of(self, other)
295 }
296
297 #[inline]
298 fn is_multiple_of(&self, other: &Self) -> bool {
299 (&self.0).divisible_by(&other.0)
300 }
301
302 #[inline]
303 fn is_even(&self) -> bool {
304 self.0.even()
305 }
306
307 #[inline]
308 fn is_odd(&self) -> bool {
309 self.0.odd()
310 }
311
312 #[inline]
313 fn div_rem(&self, other: &Self) -> (Self, Self) {
314 let (div, rem) = (&self.0).div_rem(&other.0);
315 (div.into(), rem.into())
316 }
317}
318
319impl Roots for BigInt {
320 #[inline]
321 fn nth_root(&self, n: u32) -> Self {
322 (&self.0).floor_root(u64::from(n)).into()
323 }
324}
325
326impl FromStr for BigInt {
327 type Err = ParseBigIntError;
328
329 #[inline]
330 fn from_str(s: &str) -> Result<Self, Self::Err> {
331 Self::from_str_radix(s, 10)
332 }
333}
334
335impl BigInt {
336 #[inline]
337 pub fn new(sign: Sign, digits: Vec<u32>) -> Self {
338 Self::from_biguint(sign, BigUint::new(digits))
339 }
340
341 #[inline]
342 pub fn from_biguint(sign: Sign, mut abs: BigUint) -> Self {
343 if sign == NoSign {
344 abs = BigUint::zero();
345 }
346
347 Integer::from_sign_and_abs(sign != Minus, abs.0).into()
348 }
349
350 #[inline]
351 pub fn from_slice(sign: Sign, slice: &[u32]) -> Self {
352 Self::from_biguint(sign, BigUint::from_slice(slice))
353 }
354
355 #[inline]
356 pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) {
357 if sign == NoSign {
358 self.set_zero();
359 } else {
360 *self = Self::from_slice(sign, slice);
361 }
362 }
363
364 #[inline]
365 pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> Self {
366 Self::from_biguint(sign, BigUint::from_bytes_be(bytes))
367 }
368
369 #[inline]
370 pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> Self {
371 Self::from_biguint(sign, BigUint::from_bytes_le(bytes))
372 }
373
374 #[inline]
375 pub fn from_signed_bytes_be(digits: &[u8]) -> Self {
376 let is_negative = match digits.first().copied() {
377 Some(x) => x > 0x7f,
378 None => return Self::zero(),
379 };
380
381 if is_negative {
382 let mut v = Vec::from(digits);
383 twos_complement_be(&mut v);
384 let u = BigUint::from_bytes_be(v.as_slice());
385 Self::from_biguint(Minus, u)
386 } else {
387 let u = BigUint::from_bytes_be(digits);
388 Self::from_biguint(Plus, u)
389 }
390 }
391
392 #[inline]
393 pub fn from_signed_bytes_le(digits: &[u8]) -> Self {
394 let is_negative = match digits.last().copied() {
395 Some(x) => x > 0x7f,
396 None => return Self::zero(),
397 };
398
399 if is_negative {
400 let mut v = Vec::from(digits);
401 twos_complement_le(&mut v);
402 let u = BigUint::from_bytes_le(v.as_slice());
403 Self::from_biguint(Minus, u)
404 } else {
405 let u = BigUint::from_bytes_le(digits);
406 Self::from_biguint(Plus, u)
407 }
408 }
409
410 #[inline]
411 pub fn parse_bytes(bytes: &[u8], radix: u32) -> Option<Self> {
412 let s = core::str::from_utf8(bytes).ok()?;
413 Self::from_str_radix(s, radix).ok()
414 }
415
416 #[inline]
417 pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option<Self> {
418 BigUint::from_radix_be(buf, radix).map(|u| Self::from_biguint(sign, u))
419 }
420
421 #[inline]
422 pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option<Self> {
423 BigUint::from_radix_le(buf, radix).map(|u| Self::from_biguint(sign, u))
424 }
425
426 #[inline]
427 pub fn to_bytes_be(&self) -> (Sign, Vec<u8>) {
428 (self.sign(), self.magnitude().to_bytes_be())
429 }
430
431 #[inline]
432 pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
433 (self.sign(), self.magnitude().to_bytes_le())
434 }
435
436 #[inline]
437 pub fn to_u32_digits(&self) -> (Sign, Vec<u32>) {
438 (self.sign(), self.magnitude().to_u32_digits())
439 }
440
441 #[inline]
442 pub fn to_u64_digits(&self) -> (Sign, Vec<u64>) {
443 (self.sign(), self.magnitude().to_u64_digits())
444 }
445
446 #[inline]
447 pub fn iter_u32_digits(&self) -> U32Digits<'_> {
448 self.magnitude().iter_u32_digits()
449 }
450
451 #[inline]
452 pub fn iter_u64_digits(&self) -> U64Digits<'_> {
453 self.magnitude().iter_u64_digits()
454 }
455
456 #[inline]
457 pub fn to_signed_bytes_be(&self) -> Vec<u8> {
458 let mut bytes = self.magnitude().to_bytes_be();
459 let first_byte = bytes.first().copied().unwrap_or(0);
460 let is_negative = self.is_negative();
461 if first_byte > 0x7f
462 && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && is_negative)
463 {
464 bytes.insert(0, 0);
466 }
467 if self.is_negative() {
468 twos_complement_be(&mut bytes);
469 }
470 bytes
471 }
472
473 #[inline]
474 pub fn to_signed_bytes_le(&self) -> Vec<u8> {
475 let mut bytes = self.magnitude().to_bytes_le();
476 let is_negative = self.is_negative();
477 let last_byte = bytes.last().copied().unwrap_or(0);
478 if last_byte > 0x7f
479 && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero) && is_negative)
480 {
481 bytes.push(0);
483 }
484 if self.is_negative() {
485 twos_complement_le(&mut bytes);
486 }
487 bytes
488 }
489
490 #[inline]
491 pub fn to_str_radix(&self, radix: u32) -> String {
492 self.0.to_string_base(radix as u8)
493 }
494
495 #[inline]
496 pub fn to_radix_be(&self, radix: u32) -> (Sign, Vec<u8>) {
497 (self.sign(), self.magnitude().to_radix_be(radix))
498 }
499
500 #[inline]
501 pub fn to_radix_le(&self, radix: u32) -> (Sign, Vec<u8>) {
502 (self.sign(), self.magnitude().to_radix_le(radix))
503 }
504
505 #[inline]
506 pub fn sign(&self) -> Sign {
507 match <_ as malachite_base::num::arithmetic::traits::Sign>::sign(&self.0) {
508 Ordering::Less => Minus,
509 Ordering::Equal => NoSign,
510 Ordering::Greater => Plus,
511 }
512 }
513
514 #[inline]
515 pub fn magnitude(&self) -> &BigUint {
516 unsafe { core::mem::transmute(self.0.unsigned_abs_ref()) }
517 }
518
519 #[inline]
520 pub fn into_parts(self) -> (Sign, BigUint) {
521 (self.sign(), self.0.unsigned_abs().into())
522 }
523
524 #[inline]
525 pub fn bits(&self) -> u64 {
526 self.magnitude().bits()
527 }
528
529 #[inline]
530 pub fn to_biguint(&self) -> Option<BigUint> {
531 match self.sign() {
532 Plus => Some(self.magnitude().clone()),
533 NoSign => Some(BigUint::zero()),
534 Minus => None,
535 }
536 }
537
538 #[inline]
539 pub fn checked_add(&self, v: &Self) -> Option<Self> {
540 Some(self + v)
541 }
542
543 #[inline]
544 pub fn checked_sub(&self, v: &Self) -> Option<Self> {
545 Some(self - v)
546 }
547
548 #[inline]
549 pub fn checked_mul(&self, v: &Self) -> Option<Self> {
550 Some(self * v)
551 }
552
553 #[inline]
554 pub fn checked_div(&self, v: &Self) -> Option<Self> {
555 if v.is_zero() {
556 return None;
557 }
558 Some(self / v)
559 }
560
561 #[inline]
562 pub fn pow(&self, exponent: u32) -> Self {
563 Pow::pow(self, exponent)
564 }
565
566 #[inline]
567 pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self {
568 assert!(
569 !exponent.is_negative(),
570 "negative exponentiation is not supported!"
571 );
572 assert!(
573 !modulus.is_zero(),
574 "attempt to calculate with zero modulus!"
575 );
576
577 let mut abs = self
578 .magnitude()
579 .modpow(exponent.magnitude(), modulus.magnitude());
580
581 if abs.is_zero() {
582 return Self::zero();
583 }
584
585 if (self.is_negative() && exponent.0.odd()) != modulus.is_negative() {
586 abs = modulus.magnitude() - abs;
587 }
588
589 Self::from_biguint(modulus.sign(), abs)
590 }
591
592 #[inline]
593 pub fn sqrt(&self) -> Self {
594 Roots::sqrt(self)
595 }
596
597 #[inline]
598 pub fn cbrt(&self) -> Self {
599 Roots::cbrt(self)
600 }
601
602 #[inline]
603 pub fn nth_root(&self, n: u32) -> Self {
604 Roots::nth_root(self, n)
605 }
606
607 #[inline]
608 pub fn trailing_zeros(&self) -> Option<u64> {
609 self.magnitude().trailing_zeros()
610 }
611
612 #[inline]
613 pub fn bit(&self, bit: u64) -> bool {
614 self.0.get_bit(bit)
615 }
616
617 #[inline]
618 pub fn set_bit(&mut self, bit: u64, value: bool) {
619 if value {
620 self.0.set_bit(bit);
621 } else {
622 self.0.clear_bit(bit);
623 }
624 }
625}
626#[inline]
629fn twos_complement_le(digits: &mut [u8]) {
630 twos_complement(digits);
631}
632
633#[inline]
635fn twos_complement_be(digits: &mut [u8]) {
636 twos_complement(digits.iter_mut().rev());
637}
638
639#[inline]
642fn twos_complement<'a, I>(digits: I)
643where
644 I: IntoIterator<Item = &'a mut u8>,
645{
646 let mut carry = true;
647 for d in digits {
648 *d = !*d;
649 if carry {
650 *d = d.wrapping_add(1);
651 carry = d.is_zero();
652 }
653 }
654}
655
656#[cfg(test)]
657mod test {
658 use super::*;
659 use alloc::{format, string::ToString};
660
661 #[test]
662 fn test_float_convert_nearest() {
663 let n25 = "10000000000000000000000000";
664 let val = BigInt::from_str(n25).unwrap();
665 let f = val.to_f64().unwrap();
666 assert_eq!(f.to_string(), n25);
667 }
668
669 #[test]
670 fn test_to_f64() {
671 use num_traits::ToPrimitive as NumToPrimitive;
672
673 let test_cases = [
674 "123456789012345678901234567890",
675 "999999999999999999999999999999",
676 "170141183460469231731687303715884105727",
677 "340282366920938463463374607431768211455",
678 "12345678901234567890123456789012345678901234567890",
679 "-123456789012345678901234567890",
680 "-999999999999999999999999999999",
681 "-170141183460469231731687303715884105728",
682 "-12345678901234567890123456789012345678901234567890",
683 "1208925819614629174706176",
684 "1329227995784915872903807060280344576",
685 "-1208925819614629174706176",
686 "-1329227995784915872903807060280344576",
687 "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
689 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
690 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
691 9999999999999999999999999999999999999999999999999999",
692 "-999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
693 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
694 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999\
695 99999999999999999999999999999999999999999999999999999",
696 ];
697
698 for test_str in &test_cases {
699 let malachite_val = BigInt::from_str(test_str).unwrap();
700 let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap();
701
702 assert_eq!(
703 malachite_val.to_f64(),
704 num_bigint_val.to_f64(),
705 "to_f64 mismatch for {test_str}",
706 );
707 }
708 }
709
710 #[test]
711 fn test_to_f32() {
712 use num_traits::ToPrimitive as NumToPrimitive;
713
714 let test_cases = [
715 "12345678901234567890",
716 "999999999999999999999999",
717 "-12345678901234567890",
718 "-999999999999999999999999",
719 "340282366920938463463374607431768211455",
720 ];
721
722 for test_str in &test_cases {
723 let malachite_val = BigInt::from_str(test_str).unwrap();
724 let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap();
725
726 assert_eq!(
727 malachite_val.to_f32(),
728 num_bigint_val.to_f32(),
729 "to_f32 mismatch for {test_str}",
730 );
731 }
732 }
733
734 #[test]
735 fn test_to_i64() {
736 use num_traits::ToPrimitive as NumToPrimitive;
737
738 let test_cases = [
739 "0",
740 "123",
741 "-456",
742 "9223372036854775807", "-9223372036854775808", "9223372036854775808", "-9223372036854775809", ];
747
748 for test_str in &test_cases {
749 let malachite_val = BigInt::from_str(test_str).unwrap();
750 let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap();
751
752 assert_eq!(
753 malachite_val.to_i64(),
754 num_bigint_val.to_i64(),
755 "to_i64 mismatch for {test_str}",
756 );
757 }
758 }
759
760 #[test]
761 fn test_to_u64() {
762 use num_traits::ToPrimitive as NumToPrimitive;
763
764 let test_cases = [
765 "0",
766 "123",
767 "18446744073709551615", "18446744073709551616", "-1", ];
771
772 for test_str in &test_cases {
773 let malachite_val = BigInt::from_str(test_str).unwrap();
774 let num_bigint_val = num_bigint::BigInt::from_str(test_str).unwrap();
775
776 assert_eq!(
777 malachite_val.to_u64(),
778 num_bigint_val.to_u64(),
779 "to_u64 mismatch for {test_str}",
780 );
781 }
782 }
783
784 #[test]
785 fn test_arithmetic() {
786 let test_cases = [
787 ("123456789", "987654321"),
788 ("999999999999999999", "1"),
789 ("-123456789", "987654321"),
790 ("123456789", "-987654321"),
791 ("-123456789", "-987654321"),
792 ];
793
794 for (a_str, b_str) in &test_cases {
795 let ma = BigInt::from_str(a_str).unwrap();
796 let mb = BigInt::from_str(b_str).unwrap();
797 let na = num_bigint::BigInt::from_str(a_str).unwrap();
798 let nb = num_bigint::BigInt::from_str(b_str).unwrap();
799
800 assert_eq!((&ma + &mb).to_string(), (&na + &nb).to_string(), "add");
801 assert_eq!((&ma - &mb).to_string(), (&na - &nb).to_string(), "sub");
802 assert_eq!((&ma * &mb).to_string(), (&na * &nb).to_string(), "mul");
803 if *b_str != "0" {
804 assert_eq!((&ma / &mb).to_string(), (&na / &nb).to_string(), "div");
805 assert_eq!((&ma % &mb).to_string(), (&na % &nb).to_string(), "rem");
806 }
807 }
808 }
809
810 #[test]
811 fn test_checked_arithmetic() {
812 let test_cases = [
813 ("123456789", "987654321"),
814 ("999999999999999999", "1"),
815 ("-123456789", "987654321"),
816 ];
817
818 for (a_str, b_str) in &test_cases {
819 let ma = BigInt::from_str(a_str).unwrap();
820 let mb = BigInt::from_str(b_str).unwrap();
821 let na = num_bigint::BigInt::from_str(a_str).unwrap();
822 let nb = num_bigint::BigInt::from_str(b_str).unwrap();
823
824 assert_eq!(
825 ma.checked_add(&mb).map(|v| v.to_string()),
826 na.checked_add(&nb).map(|v| v.to_string()),
827 "checked_add"
828 );
829 assert_eq!(
830 ma.checked_sub(&mb).map(|v| v.to_string()),
831 na.checked_sub(&nb).map(|v| v.to_string()),
832 "checked_sub"
833 );
834 assert_eq!(
835 ma.checked_mul(&mb).map(|v| v.to_string()),
836 na.checked_mul(&nb).map(|v| v.to_string()),
837 "checked_mul"
838 );
839 assert_eq!(
840 ma.checked_div(&mb).map(|v| v.to_string()),
841 na.checked_div(&nb).map(|v| v.to_string()),
842 "checked_div"
843 );
844 }
845 }
846
847 #[test]
848 fn test_sign() {
849 use num_traits::Signed;
850
851 let test_cases = [
852 "0",
853 "123",
854 "-456",
855 "999999999999999999",
856 "-999999999999999999",
857 ];
858
859 for test_str in &test_cases {
860 let ma = BigInt::from_str(test_str).unwrap();
861 let na = num_bigint::BigInt::from_str(test_str).unwrap();
862
863 assert_eq!(
864 ma.is_positive(),
865 na.is_positive(),
866 "is_positive for {test_str}",
867 );
868 assert_eq!(
869 ma.is_negative(),
870 na.is_negative(),
871 "is_negative for {test_str}",
872 );
873 assert_eq!(
874 ma.abs().to_string(),
875 na.abs().to_string(),
876 "abs for {test_str}",
877 );
878 }
879 }
880
881 #[test]
882 fn test_pow() {
883 use num_traits::Pow;
884
885 let test_cases = [("2", 10u32), ("10", 20u32), ("-3", 5u32), ("123", 4u32)];
886
887 for (base_str, exp) in &test_cases {
888 let ma = BigInt::from_str(base_str).unwrap();
889 let na = num_bigint::BigInt::from_str(base_str).unwrap();
890
891 assert_eq!(
892 ma.pow(*exp).to_string(),
893 na.pow(*exp).to_string(),
894 "pow for {base_str}^{exp}",
895 );
896 }
897 }
898
899 #[test]
900 fn test_to_signed_bytes() {
901 let sysmax = i64::MAX;
902 let i = BigInt::from(sysmax);
903 let b = i.to_signed_bytes_le();
904 let i2 = BigInt::from_signed_bytes_le(&b);
905 assert_eq!(i, i2);
906 }
907
908 #[test]
909 fn test_display_bigint() {
910 let n = BigInt::from_str("1234567890").unwrap();
911 assert_eq!(format!("{n}"), "1234567890");
912 }
913}