1use alloc::string::String;
9use alloc::vec::Vec;
10use core::cmp::Ordering;
11
12#[derive(Clone, PartialEq, Eq)]
14pub struct BigInt {
15 negative: bool,
17 limbs: Vec<u32>,
19}
20
21impl BigInt {
22 pub fn zero() -> Self {
24 BigInt {
25 negative: false,
26 limbs: Vec::new(),
27 }
28 }
29
30 pub fn is_zero(&self) -> bool {
32 self.limbs.is_empty()
33 }
34
35 fn normalize(mut self) -> Self {
37 while let Some(&last) = self.limbs.last() {
38 if last == 0 {
39 self.limbs.pop();
40 } else {
41 break;
42 }
43 }
44 if self.limbs.is_empty() {
45 self.negative = false;
46 }
47 self
48 }
49
50 pub fn from_i64(mut v: i64) -> Self {
52 if v == 0 {
53 return BigInt::zero();
54 }
55 let negative = v < 0;
56 let mut mag = if negative {
58 (v as i128).unsigned_abs()
59 } else {
60 v as u128
61 };
62 let _ = &mut v;
63 let mut limbs = Vec::new();
64 while mag > 0 {
65 limbs.push((mag & 0xFFFF_FFFF) as u32);
66 mag >>= 32;
67 }
68 BigInt { negative, limbs }.normalize()
69 }
70
71 pub fn from_u64(v: u64) -> Self {
73 if v == 0 {
74 return BigInt::zero();
75 }
76 let mut mag = v;
77 let mut limbs = Vec::new();
78 while mag > 0 {
79 limbs.push((mag & 0xFFFF_FFFF) as u32);
80 mag >>= 32;
81 }
82 BigInt { negative: false, limbs }.normalize()
83 }
84
85 pub fn from_f64(v: f64) -> Option<Self> {
87 if !v.is_finite() {
88 return None;
89 }
90 if libm::trunc(v) != v {
91 return None;
92 }
93 if v == 0.0 {
94 return Some(BigInt::zero());
95 }
96 let negative = v < 0.0;
97 let mut mag = libm::fabs(v);
98 let mut limbs = Vec::new();
101 let base = 4294967296.0_f64; while mag >= 1.0 {
103 let rem = mag - libm::floor(mag / base) * base;
104 limbs.push(rem as u32);
105 mag = libm::floor(mag / base);
106 }
107 Some(BigInt { negative, limbs }.normalize())
108 }
109
110 pub fn parse_decimal(s: &str) -> Option<Self> {
112 let t = s.trim();
113 if t.is_empty() {
114 return Some(BigInt::zero());
115 }
116 let (negative, digits) = match t.strip_prefix('-') {
117 Some(rest) => (true, rest),
118 None => (false, t.strip_prefix('+').unwrap_or(t)),
119 };
120 if digits.is_empty() {
121 return None;
122 }
123 let mut acc = BigInt::zero();
124 let ten = BigInt::from_i64(10);
125 for ch in digits.chars() {
126 if ch == '_' {
127 continue;
128 }
129 let d = ch.to_digit(10)?;
130 acc = acc.mul(&ten).add(&BigInt::from_i64(d as i64));
131 }
132 acc.negative = negative;
133 Some(acc.normalize())
134 }
135
136 pub fn parse_str(s: &str) -> Option<Self> {
138 let t = s.trim();
139 let (neg, body) = match t.strip_prefix('-') {
140 Some(r) => (true, r),
141 None => (false, t.strip_prefix('+').unwrap_or(t)),
142 };
143 let parsed = if let Some(h) = body.strip_prefix("0x").or_else(|| body.strip_prefix("0X")) {
144 Self::parse_radix(h, 16)
145 } else if let Some(o) = body.strip_prefix("0o").or_else(|| body.strip_prefix("0O")) {
146 Self::parse_radix(o, 8)
147 } else if let Some(b) = body.strip_prefix("0b").or_else(|| body.strip_prefix("0B")) {
148 Self::parse_radix(b, 2)
149 } else {
150 Self::parse_decimal(body)
151 };
152 parsed.map(|mut v| {
153 if neg {
154 v.negative = !v.negative;
155 }
156 v.normalize()
157 })
158 }
159
160 fn parse_radix(digits: &str, radix: u32) -> Option<Self> {
162 if digits.is_empty() {
163 return None;
164 }
165 let mut acc = BigInt::zero();
166 let base = BigInt::from_i64(radix as i64);
167 for ch in digits.chars() {
168 if ch == '_' {
169 continue;
170 }
171 let d = ch.to_digit(radix)?;
172 acc = acc.mul(&base).add(&BigInt::from_i64(d as i64));
173 }
174 Some(acc)
175 }
176
177 fn cmp_magnitude(&self, other: &Self) -> Ordering {
179 if self.limbs.len() != other.limbs.len() {
180 return self.limbs.len().cmp(&other.limbs.len());
181 }
182 for i in (0..self.limbs.len()).rev() {
184 if self.limbs[i] != other.limbs[i] {
185 return self.limbs[i].cmp(&other.limbs[i]);
186 }
187 }
188 Ordering::Equal
189 }
190
191 #[allow(clippy::should_implement_trait)]
193 pub fn cmp(&self, other: &Self) -> Ordering {
194 match (self.negative, other.negative) {
195 (false, true) => Ordering::Greater,
196 (true, false) => Ordering::Less,
197 (false, false) => self.cmp_magnitude(other),
198 (true, true) => other.cmp_magnitude(self),
199 }
200 }
201
202 fn add_magnitude(a: &[u32], b: &[u32]) -> Vec<u32> {
204 let mut out = Vec::with_capacity(a.len().max(b.len()) + 1);
205 let mut carry: u64 = 0;
206 let n = a.len().max(b.len());
207 for i in 0..n {
208 let av = *a.get(i).unwrap_or(&0) as u64;
209 let bv = *b.get(i).unwrap_or(&0) as u64;
210 let sum = av + bv + carry;
211 out.push((sum & 0xFFFF_FFFF) as u32);
212 carry = sum >> 32;
213 }
214 if carry > 0 {
215 out.push(carry as u32);
216 }
217 out
218 }
219
220 fn sub_magnitude(a: &[u32], b: &[u32]) -> Vec<u32> {
222 let mut out = Vec::with_capacity(a.len());
223 let mut borrow: i64 = 0;
224 for i in 0..a.len() {
225 let av = a[i] as i64;
226 let bv = *b.get(i).unwrap_or(&0) as i64;
227 let mut diff = av - bv - borrow;
228 if diff < 0 {
229 diff += 1 << 32;
230 borrow = 1;
231 } else {
232 borrow = 0;
233 }
234 out.push((diff & 0xFFFF_FFFF) as u32);
235 }
236 out
237 }
238
239 pub fn add(&self, other: &Self) -> Self {
241 if self.negative == other.negative {
242 BigInt {
244 negative: self.negative,
245 limbs: Self::add_magnitude(&self.limbs, &other.limbs),
246 }
247 .normalize()
248 } else {
249 match self.cmp_magnitude(other) {
251 Ordering::Equal => BigInt::zero(),
252 Ordering::Greater => BigInt {
253 negative: self.negative,
254 limbs: Self::sub_magnitude(&self.limbs, &other.limbs),
255 }
256 .normalize(),
257 Ordering::Less => BigInt {
258 negative: other.negative,
259 limbs: Self::sub_magnitude(&other.limbs, &self.limbs),
260 }
261 .normalize(),
262 }
263 }
264 }
265
266 pub fn sub(&self, other: &Self) -> Self {
268 let neg_other = BigInt {
270 negative: !other.negative,
271 limbs: other.limbs.clone(),
272 }
273 .normalize();
274 self.add(&neg_other)
275 }
276
277 pub fn neg(&self) -> Self {
279 if self.is_zero() {
280 return BigInt::zero();
281 }
282 BigInt {
283 negative: !self.negative,
284 limbs: self.limbs.clone(),
285 }
286 }
287
288 pub fn abs(&self) -> Self {
290 BigInt {
291 negative: false,
292 limbs: self.limbs.clone(),
293 }
294 }
295
296 pub fn mul(&self, other: &Self) -> Self {
298 if self.is_zero() || other.is_zero() {
299 return BigInt::zero();
300 }
301 let mut out = alloc::vec![0u32; self.limbs.len() + other.limbs.len()];
302 for (i, &a) in self.limbs.iter().enumerate() {
303 let mut carry: u64 = 0;
304 for (j, &b) in other.limbs.iter().enumerate() {
305 let idx = i + j;
306 let cur = out[idx] as u64 + (a as u64) * (b as u64) + carry;
307 out[idx] = (cur & 0xFFFF_FFFF) as u32;
308 carry = cur >> 32;
309 }
310 let mut k = i + other.limbs.len();
312 while carry > 0 {
313 let cur = out[k] as u64 + carry;
314 out[k] = (cur & 0xFFFF_FFFF) as u32;
315 carry = cur >> 32;
316 k += 1;
317 }
318 }
319 BigInt {
320 negative: self.negative != other.negative,
321 limbs: out,
322 }
323 .normalize()
324 }
325
326 fn divmod_magnitude(a: &[u32], b: &[u32]) -> (Vec<u32>, Vec<u32>) {
329 let dividend = BigInt {
331 negative: false,
332 limbs: a.to_vec(),
333 }
334 .normalize();
335 let divisor = BigInt {
336 negative: false,
337 limbs: b.to_vec(),
338 }
339 .normalize();
340 if dividend.cmp_magnitude(&divisor) == Ordering::Less {
341 return (Vec::new(), dividend.limbs);
342 }
343 let total_bits = dividend.limbs.len() * 32;
345 let mut quotient = BigInt::zero();
346 let mut remainder = BigInt::zero();
347 let one = BigInt::from_i64(1);
348 for i in (0..total_bits).rev() {
349 remainder = remainder.shl_bits(1);
351 let limb = i / 32;
353 let bit = i % 32;
354 if (dividend.limbs[limb] >> bit) & 1 == 1 {
355 remainder = remainder.add(&one);
356 }
357 if remainder.cmp_magnitude(&divisor) != Ordering::Less {
358 remainder = BigInt {
359 negative: false,
360 limbs: Self::sub_magnitude(&remainder.limbs, &divisor.limbs),
361 }
362 .normalize();
363 quotient = quotient.set_bit(i);
364 }
365 }
366 (quotient.normalize().limbs, remainder.normalize().limbs)
367 }
368
369 fn shl_bits(&self, bits: usize) -> Self {
371 if self.is_zero() || bits == 0 {
372 return self.clone();
373 }
374 let limb_shift = bits / 32;
375 let bit_shift = bits % 32;
376 let mut out = alloc::vec![0u32; self.limbs.len() + limb_shift + 1];
377 for (i, &v) in self.limbs.iter().enumerate() {
378 let val = (v as u64) << bit_shift;
379 out[i + limb_shift] |= (val & 0xFFFF_FFFF) as u32;
380 out[i + limb_shift + 1] |= (val >> 32) as u32;
381 }
382 BigInt {
383 negative: self.negative,
384 limbs: out,
385 }
386 .normalize()
387 }
388
389 fn shr_bits(&self, bits: usize) -> Self {
391 if self.is_zero() || bits == 0 {
392 return self.clone();
393 }
394 let limb_shift = bits / 32;
395 let bit_shift = bits % 32;
396 if limb_shift >= self.limbs.len() {
397 return BigInt::zero();
398 }
399 let mut out = alloc::vec![0u32; self.limbs.len() - limb_shift];
400 for i in 0..out.len() {
401 let lo = self.limbs[i + limb_shift] >> bit_shift;
402 let hi = if bit_shift > 0 && i + limb_shift + 1 < self.limbs.len() {
403 self.limbs[i + limb_shift + 1] << (32 - bit_shift)
404 } else {
405 0
406 };
407 out[i] = lo | hi;
408 }
409 BigInt {
410 negative: self.negative,
411 limbs: out,
412 }
413 .normalize()
414 }
415
416 fn set_bit(&self, i: usize) -> Self {
418 let limb = i / 32;
419 let bit = i % 32;
420 let mut limbs = self.limbs.clone();
421 if limb >= limbs.len() {
422 limbs.resize(limb + 1, 0);
423 }
424 limbs[limb] |= 1 << bit;
425 BigInt {
426 negative: self.negative,
427 limbs,
428 }
429 }
430
431 pub fn div(&self, other: &Self) -> Option<Self> {
433 if other.is_zero() {
434 return None;
435 }
436 let (q, _) = Self::divmod_magnitude(&self.limbs, &other.limbs);
437 Some(
438 BigInt {
439 negative: self.negative != other.negative,
440 limbs: q,
441 }
442 .normalize(),
443 )
444 }
445
446 pub fn rem(&self, other: &Self) -> Option<Self> {
448 if other.is_zero() {
449 return None;
450 }
451 let (_, r) = Self::divmod_magnitude(&self.limbs, &other.limbs);
452 Some(
453 BigInt {
454 negative: self.negative,
455 limbs: r,
456 }
457 .normalize(),
458 )
459 }
460
461 pub fn pow(&self, exp: &Self) -> Option<Self> {
463 if exp.negative {
464 return None;
465 }
466 if exp.is_zero() {
467 return Some(BigInt::from_i64(1));
468 }
469 let mut result = BigInt::from_i64(1);
470 let mut base = self.clone();
471 let mut e = exp.clone();
472 let two = BigInt::from_i64(2);
473 while !e.is_zero() {
474 let (_, r) = Self::divmod_magnitude(&e.limbs, &two.limbs);
476 let odd = !r.is_empty();
477 if odd {
478 result = result.mul(&base);
479 }
480 base = base.mul(&base);
481 e = e.shr_bits(1).abs();
482 }
483 Some(result)
484 }
485
486 pub fn to_decimal_string(&self) -> String {
488 if self.is_zero() {
489 return String::from("0");
490 }
491 let mut digits_rev: Vec<u32> = Vec::new();
493 let chunk = BigInt::from_i64(1_000_000_000);
494 let mut cur = self.abs();
495 while !cur.is_zero() {
496 let (q, r) = Self::divmod_magnitude(&cur.limbs, &chunk.limbs);
497 let rem_val = limbs_to_u64(&r) as u32;
498 digits_rev.push(rem_val);
499 cur = BigInt {
500 negative: false,
501 limbs: q,
502 }
503 .normalize();
504 }
505 let mut s = String::new();
506 if self.negative {
507 s.push('-');
508 }
509 for (i, chunk_val) in digits_rev.iter().rev().enumerate() {
511 if i == 0 {
512 s.push_str(&alloc::format!("{}", chunk_val));
513 } else {
514 s.push_str(&alloc::format!("{:09}", chunk_val));
515 }
516 }
517 s
518 }
519
520 pub fn to_f64(&self) -> f64 {
522 let mut result = 0.0_f64;
523 let base = 4294967296.0_f64; for &limb in self.limbs.iter().rev() {
525 result = result * base + (limb as f64);
526 }
527 if self.negative {
528 -result
529 } else {
530 result
531 }
532 }
533
534 pub fn is_one(&self) -> bool {
536 !self.negative && self.limbs.len() == 1 && self.limbs[0] == 1
537 }
538
539 fn bit_length(&self) -> usize {
541 match self.limbs.last() {
542 None => 0,
543 Some(&top) => (self.limbs.len() - 1) * 32 + (32 - top.leading_zeros() as usize),
544 }
545 }
546
547 fn to_twos_complement(&self, width: usize) -> Vec<u32> {
550 let mut out = alloc::vec![0u32; width];
551 for (i, slot) in out.iter_mut().enumerate() {
552 *slot = *self.limbs.get(i).unwrap_or(&0);
553 }
554 if self.negative {
555 for slot in out.iter_mut() {
557 *slot = !*slot;
558 }
559 let mut carry = 1u64;
560 for slot in out.iter_mut() {
561 let v = *slot as u64 + carry;
562 *slot = (v & 0xFFFF_FFFF) as u32;
563 carry = v >> 32;
564 if carry == 0 {
565 break;
566 }
567 }
568 }
569 out
570 }
571
572 fn from_twos_complement(mut limbs: Vec<u32>) -> Self {
575 let negative = limbs
576 .last()
577 .map(|&top| (top >> 31) & 1 == 1)
578 .unwrap_or(false);
579 if negative {
580 for slot in limbs.iter_mut() {
582 *slot = !*slot;
583 }
584 let mut carry = 1u64;
585 for slot in limbs.iter_mut() {
586 let v = *slot as u64 + carry;
587 *slot = (v & 0xFFFF_FFFF) as u32;
588 carry = v >> 32;
589 if carry == 0 {
590 break;
591 }
592 }
593 }
594 BigInt { negative, limbs }.normalize()
595 }
596
597 fn bitop_width(&self, other: &Self) -> usize {
599 let bits = self.bit_length().max(other.bit_length());
600 (bits / 32) + 2
602 }
603
604 pub fn bitand(&self, other: &Self) -> Self {
606 let w = self.bitop_width(other);
607 let a = self.to_twos_complement(w);
608 let b = other.to_twos_complement(w);
609 let out: Vec<u32> = a.iter().zip(b.iter()).map(|(x, y)| x & y).collect();
610 Self::from_twos_complement(out)
611 }
612
613 pub fn bitor(&self, other: &Self) -> Self {
615 let w = self.bitop_width(other);
616 let a = self.to_twos_complement(w);
617 let b = other.to_twos_complement(w);
618 let out: Vec<u32> = a.iter().zip(b.iter()).map(|(x, y)| x | y).collect();
619 Self::from_twos_complement(out)
620 }
621
622 pub fn bitxor(&self, other: &Self) -> Self {
624 let w = self.bitop_width(other);
625 let a = self.to_twos_complement(w);
626 let b = other.to_twos_complement(w);
627 let out: Vec<u32> = a.iter().zip(b.iter()).map(|(x, y)| x ^ y).collect();
628 Self::from_twos_complement(out)
629 }
630
631 pub fn bitnot(&self) -> Self {
633 self.neg().sub(&BigInt::from_i64(1))
635 }
636
637 pub fn shl(&self, count: i64) -> Self {
639 if count < 0 {
640 return self.shr(-count);
641 }
642 let shifted = self.shl_bits(count as usize);
643 BigInt {
644 negative: self.negative,
645 limbs: shifted.limbs,
646 }
647 .normalize()
648 }
649
650 pub fn shr(&self, count: i64) -> Self {
652 if count < 0 {
653 return self.shl(-count);
654 }
655 let n = count as usize;
656 if !self.negative {
657 let shifted = self.shr_bits(n);
659 return BigInt {
660 negative: false,
661 limbs: shifted.limbs,
662 }
663 .normalize();
664 }
665 let full_limbs = n / 32;
668 let rem_bits = n % 32;
669 let mut truncated_bits = false;
670 for &l in self.limbs.iter().take(full_limbs) {
671 if l != 0 {
672 truncated_bits = true;
673 break;
674 }
675 }
676 if !truncated_bits && rem_bits > 0 {
677 if let Some(&l) = self.limbs.get(full_limbs) {
678 let mask = (1u32 << rem_bits) - 1;
679 if (l & mask) != 0 {
680 truncated_bits = true;
681 }
682 }
683 }
684 let mag = self.shr_bits(n);
685 let mut result = BigInt {
686 negative: true,
687 limbs: mag.limbs,
688 }
689 .normalize();
690 if truncated_bits {
691 result = result.sub(&BigInt::from_i64(1));
693 }
694 result
695 }
696
697 pub fn as_uint_n(&self, bits: u64) -> Self {
699 if bits == 0 {
700 return BigInt::zero();
701 }
702 let full_limbs = (bits / 32) as usize;
703 let rem_bits = (bits % 32) as usize;
704 let width = full_limbs + if rem_bits > 0 { 1 } else { 0 } + 1;
705 let tc = self.to_twos_complement(width);
706 let out_limbs_count = full_limbs + if rem_bits > 0 { 1 } else { 0 };
707 let mut out = alloc::vec![0u32; out_limbs_count];
708 for i in 0..full_limbs {
709 if i < tc.len() {
710 out[i] = tc[i];
711 }
712 }
713 if rem_bits > 0 && full_limbs < tc.len() {
714 let mask = (1u32 << rem_bits) - 1;
715 out[full_limbs] = tc[full_limbs] & mask;
716 }
717 BigInt {
719 negative: false,
720 limbs: out,
721 }
722 .normalize()
723 }
724
725 pub fn as_int_n(&self, bits: u64) -> Self {
727 if bits == 0 {
728 return BigInt::zero();
729 }
730 let unsigned = self.as_uint_n(bits);
731 let top = (bits - 1) as usize;
733 let limb = top / 32;
734 let bit = top % 32;
735 let is_neg = limb < unsigned.limbs.len() && (unsigned.limbs[limb] >> bit) & 1 == 1;
736 if is_neg {
737 let two_pow = BigInt::from_i64(1).shl(bits as i64);
739 unsigned.sub(&two_pow)
740 } else {
741 unsigned
742 }
743 }
744
745 pub fn to_u64_truncated(&self) -> u64 {
748 let unsigned = self.as_uint_n(64);
749 let low = *unsigned.limbs.first().unwrap_or(&0) as u64;
750 let high = *unsigned.limbs.get(1).unwrap_or(&0) as u64;
751 low | (high << 32)
752 }
753}
754
755fn limbs_to_u64(limbs: &[u32]) -> u64 {
757 let mut v = 0u64;
758 for (i, &l) in limbs.iter().enumerate().take(2) {
759 v |= (l as u64) << (32 * i);
760 }
761 v
762}
763
764pub fn selftest() -> (usize, usize) {
767 let mut pass = 0usize;
768 let mut total = 0usize;
769
770 fn check_str(pass: &mut usize, total: &mut usize, got: &str, want: &str) {
772 *total += 1;
773 if got == want {
774 *pass += 1;
775 }
776 }
777 fn check_bool(pass: &mut usize, total: &mut usize, cond: bool) {
779 *total += 1;
780 if cond {
781 *pass += 1;
782 }
783 }
784 fn check_opt(pass: &mut usize, total: &mut usize, got: Option<String>, want: &str) {
787 *total += 1;
788 if got.as_deref() == Some(want) {
789 *pass += 1;
790 }
791 }
792
793 let bi = BigInt::from_i64;
794 let p = &mut pass;
795 let t = &mut total;
796
797 check_opt(
799 p,
800 t,
801 BigInt::parse_str("0").map(|b| b.to_decimal_string()),
802 "0",
803 );
804 check_opt(
805 p,
806 t,
807 BigInt::parse_str("12345678901234567890").map(|b| b.to_decimal_string()),
808 "12345678901234567890",
809 );
810 check_opt(
811 p,
812 t,
813 BigInt::parse_str("-98765432109876543210").map(|b| b.to_decimal_string()),
814 "-98765432109876543210",
815 );
816 check_opt(
817 p,
818 t,
819 BigInt::parse_str("0xff").map(|b| b.to_decimal_string()),
820 "255",
821 );
822 check_opt(
823 p,
824 t,
825 BigInt::parse_str("0b1010").map(|b| b.to_decimal_string()),
826 "10",
827 );
828 check_opt(
829 p,
830 t,
831 BigInt::parse_str("0o17").map(|b| b.to_decimal_string()),
832 "15",
833 );
834 check_opt(
835 p,
836 t,
837 BigInt::parse_str("1_000_000").map(|b| b.to_decimal_string()),
838 "1000000",
839 );
840
841 check_str(p, t, &bi(2).add(&bi(3)).to_decimal_string(), "5");
843 check_opt(
844 p,
845 t,
846 BigInt::parse_str("4294967295").map(|b| b.add(&bi(1)).to_decimal_string()),
847 "4294967296",
848 );
849 check_str(p, t, &bi(5).sub(&bi(8)).to_decimal_string(), "-3");
850 check_str(p, t, &bi(-5).add(&bi(5)).to_decimal_string(), "0");
851 check_opt(
852 p,
853 t,
854 BigInt::parse_str("18446744073709551616").map(|b| b.sub(&bi(1)).to_decimal_string()),
855 "18446744073709551615",
856 );
857
858 check_str(
860 p,
861 t,
862 &bi(123456789).mul(&bi(987654321)).to_decimal_string(),
863 "121932631112635269",
864 );
865 check_str(p, t, &bi(-7).mul(&bi(6)).to_decimal_string(), "-42");
866 check_opt(
867 p,
868 t,
869 BigInt::parse_str("99999999999999999999").and_then(|a| {
870 BigInt::parse_str("99999999999999999999").map(|b| a.mul(&b).to_decimal_string())
871 }),
872 "9999999999999999999800000000000000000001",
873 );
874
875 check_opt(
877 p,
878 t,
879 bi(100).div(&bi(7)).map(|b| b.to_decimal_string()),
880 "14",
881 );
882 check_opt(
883 p,
884 t,
885 bi(100).rem(&bi(7)).map(|b| b.to_decimal_string()),
886 "2",
887 );
888 check_opt(
889 p,
890 t,
891 bi(-100).div(&bi(7)).map(|b| b.to_decimal_string()),
892 "-14",
893 );
894 check_opt(
895 p,
896 t,
897 bi(-100).rem(&bi(7)).map(|b| b.to_decimal_string()),
898 "-2",
899 );
900 check_bool(p, t, bi(1).div(&bi(0)).is_none());
901
902 check_opt(
904 p,
905 t,
906 bi(2).pow(&bi(64)).map(|b| b.to_decimal_string()),
907 "18446744073709551616",
908 );
909 check_opt(p, t, bi(3).pow(&bi(0)).map(|b| b.to_decimal_string()), "1");
910 check_opt(
911 p,
912 t,
913 bi(-2).pow(&bi(3)).map(|b| b.to_decimal_string()),
914 "-8",
915 );
916
917 check_bool(p, t, bi(5).cmp(&bi(7)) == Ordering::Less);
919 check_bool(p, t, bi(-3).cmp(&bi(-9)) == Ordering::Greater);
920 check_bool(p, t, bi(42).cmp(&bi(42)) == Ordering::Equal);
921
922 check_str(
924 p,
925 t,
926 &bi(0b1100).bitand(&bi(0b1010)).to_decimal_string(),
927 "8",
928 ); check_str(
930 p,
931 t,
932 &bi(0b1100).bitor(&bi(0b1010)).to_decimal_string(),
933 "14",
934 ); check_str(
936 p,
937 t,
938 &bi(0b1100).bitxor(&bi(0b1010)).to_decimal_string(),
939 "6",
940 ); check_str(p, t, &bi(5).bitnot().to_decimal_string(), "-6"); check_str(p, t, &bi(-1).bitnot().to_decimal_string(), "0"); check_str(p, t, &bi(-1).bitand(&bi(5)).to_decimal_string(), "5"); check_str(p, t, &bi(-1).bitor(&bi(5)).to_decimal_string(), "-1"); check_str(p, t, &bi(-2).bitand(&bi(3)).to_decimal_string(), "2"); check_str(p, t, &bi(-1).bitxor(&bi(-1)).to_decimal_string(), "0"); check_str(
952 p,
953 t,
954 &bi(1).shl(64).to_decimal_string(),
955 "18446744073709551616",
956 );
957 check_str(p, t, &bi(255).shr(4).to_decimal_string(), "15");
958 check_str(p, t, &bi(-8).shr(1).to_decimal_string(), "-4");
960 check_str(p, t, &bi(-7).shr(1).to_decimal_string(), "-4");
961 check_str(p, t, &bi(-1).shr(5).to_decimal_string(), "-1");
962 check_str(
963 p,
964 t,
965 &bi(12345).shl(40).shr(40).to_decimal_string(),
966 "12345",
967 );
968
969 check_str(p, t, &bi(256).as_uint_n(8).to_decimal_string(), "0");
971 check_str(p, t, &bi(257).as_uint_n(8).to_decimal_string(), "1");
972 check_str(p, t, &bi(-1).as_uint_n(8).to_decimal_string(), "255");
973 check_str(p, t, &bi(255).as_int_n(8).to_decimal_string(), "-1");
974 check_str(p, t, &bi(128).as_int_n(8).to_decimal_string(), "-128");
975 check_str(p, t, &bi(127).as_int_n(8).to_decimal_string(), "127");
976 check_str(p, t, &bi(0x8000).as_int_n(16).to_decimal_string(), "-32768");
977
978 check_bool(p, t, bi(9007199254740992).to_f64() == 9007199254740992.0);
980 check_bool(
981 p,
982 t,
983 BigInt::from_f64(42.0).map(|b| b.to_decimal_string()) == Some(String::from("42")),
984 );
985 check_bool(p, t, BigInt::from_f64(1.5).is_none());
986
987 (pass, total)
988}