1#[cfg(feature = "macro")]
9pub use bignum_proc_macro::{create_efficient_base, make_bignum};
10
11use std::{
12 cmp::Ordering,
13 fmt::{Debug, Display},
14 iter::{Product, Sum},
15 ops::{Add, AddAssign, Div, Mul, MulAssign, Shl, Shr, Sub, SubAssign},
16};
17
18use consts::{
19 BIN_EXP_RANGE, BIN_POWERS, BIN_POWERS_U128, BIN_SIG_RANGE, DEC_EXP_RANGE, DEC_POWERS,
20 DEC_POWERS_U128, DEC_SIG_RANGE, HEX_EXP_RANGE, HEX_POWERS, HEX_POWERS_U128, HEX_SIG_RANGE,
21 OCT_EXP_RANGE, OCT_POWERS, OCT_POWERS_U128, OCT_SIG_RANGE,
22};
23
24#[cfg(any(feature = "random", test))]
25pub mod random;
26
27pub(crate) mod consts;
28pub(crate) mod macros;
29
30pub mod traits;
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub struct ExpRange(pub u32, pub u32);
50
51impl ExpRange {
52 pub const fn new(min: u32, max: u32) -> Self {
53 Self(min, max)
54 }
55
56 pub const fn from(range: (u32, u32)) -> Self {
57 Self(range.0, range.1)
58 }
59
60 pub fn min(&self) -> u32 {
61 self.0
62 }
63
64 pub fn max(&self) -> u32 {
65 self.1
66 }
67}
68
69#[derive(Clone, Copy, Debug, PartialEq, Eq)]
70pub struct SigRange(pub u64, pub u64);
87
88impl SigRange {
89 pub const fn new(min: u64, max: u64) -> Self {
90 Self(min, max)
91 }
92
93 pub const fn from(range: (u64, u64)) -> Self {
94 Self(range.0, range.1)
95 }
96
97 pub fn min(&self) -> u64 {
98 self.0
99 }
100
101 pub fn max(&self) -> u64 {
102 self.1
103 }
104}
105
106pub trait Base: Copy + Debug {
175 const NUMBER: u16;
178
179 fn new() -> Self;
185
186 fn exp_range(&self) -> ExpRange;
190
191 fn sig_range(&self) -> SigRange;
194
195 fn pow(exp: u32) -> u64 {
201 (Self::NUMBER as u64).pow(exp)
202 }
203
204 fn pow_u128(exp: u32) -> u128 {
208 (Self::NUMBER as u128).pow(exp)
209 }
210
211 fn calculate_ranges() -> (ExpRange, SigRange) {
217 if Self::NUMBER.is_power_of_two() && Self::NUMBER.ilog2().is_power_of_two() {
218 let pow = Self::NUMBER.ilog2();
221 let exp = 64 / pow;
222 let sig = Self::pow(exp - 1);
223
224 (ExpRange(exp - 1, exp), SigRange(sig, u64::MAX))
225 } else {
226 let exp = u64::MAX.ilog(Self::NUMBER as u64);
227 (
228 ExpRange(exp - 1, exp),
229 SigRange(Self::pow(exp - 1), Self::pow(exp) - 1),
230 )
231 }
232 }
233
234 fn lshift(lhs: u64, exp: u32) -> u64 {
240 lhs * Self::pow(exp)
241 }
242 fn rshift(lhs: u64, exp: u32) -> u64 {
248 lhs / Self::pow(exp)
249 }
250
251 fn lshift_u128(lhs: u128, exp: u32) -> u128 {
255 lhs * Self::pow_u128(exp)
256 }
257
258 fn rshift_u128(lhs: u128, exp: u32) -> u128 {
262 lhs / Self::pow_u128(exp)
263 }
264
265 fn get_mag(sig: u64) -> u32 {
272 sig.ilog(Self::NUMBER as u64)
273 }
274
275 fn get_mag_u128(sig: u128) -> u32 {
279 sig.ilog(Self::NUMBER as u128)
280 }
281
282 fn as_number(&self) -> u16 {
285 Self::NUMBER
286 }
287}
288
289#[derive(Clone, Copy, Debug)]
292pub struct Binary;
293pub type BigNumBin = BigNumBase<Binary>;
294
295#[derive(Clone, Copy, Debug)]
298pub struct Octal;
299pub type BigNumOct = BigNumBase<Octal>;
300
301#[derive(Clone, Copy, Debug)]
304pub struct Hexadecimal;
305pub type BigNumHex = BigNumBase<Hexadecimal>;
306
307#[derive(Clone, Copy, Debug)]
310pub struct Decimal;
311pub type BigNumDec = BigNumBase<Decimal>;
312
313impl Base for Binary {
314 const NUMBER: u16 = 2;
315 fn new() -> Self {
316 Self
317 }
318
319 fn exp_range(&self) -> ExpRange {
320 ExpRange::from(BIN_EXP_RANGE)
322 }
323
324 fn sig_range(&self) -> SigRange {
325 SigRange::from(BIN_SIG_RANGE)
327 }
328
329 fn pow(exp: u32) -> u64 {
330 BIN_POWERS[exp as usize]
331 }
332
333 fn pow_u128(exp: u32) -> u128 {
334 BIN_POWERS_U128[exp as usize]
335 }
336
337 fn rshift(lhs: u64, exp: u32) -> u64 {
338 lhs >> exp
339 }
340
341 fn rshift_u128(lhs: u128, exp: u32) -> u128 {
342 lhs >> exp
343 }
344
345 fn lshift(lhs: u64, exp: u32) -> u64 {
346 lhs << exp
347 }
348
349 fn lshift_u128(lhs: u128, exp: u32) -> u128 {
350 lhs << exp
351 }
352
353 fn get_mag(sig: u64) -> u32 {
354 sig.ilog2()
355 }
356
357 fn get_mag_u128(sig: u128) -> u32 {
358 sig.ilog2()
359 }
360}
361
362impl Base for Octal {
363 const NUMBER: u16 = 8;
364
365 fn new() -> Self {
366 Self
367 }
368
369 fn exp_range(&self) -> ExpRange {
370 ExpRange::from(OCT_EXP_RANGE)
371 }
372
373 fn sig_range(&self) -> SigRange {
374 SigRange::from(OCT_SIG_RANGE)
375 }
376
377 fn pow(exp: u32) -> u64 {
378 OCT_POWERS[exp as usize]
379 }
380
381 fn pow_u128(exp: u32) -> u128 {
382 OCT_POWERS_U128[exp as usize]
383 }
384
385 fn rshift(lhs: u64, exp: u32) -> u64 {
386 lhs >> (3 * exp)
387 }
388
389 fn rshift_u128(lhs: u128, exp: u32) -> u128 {
390 lhs >> (3 * exp)
391 }
392
393 fn lshift(lhs: u64, exp: u32) -> u64 {
394 lhs << (3 * exp)
395 }
396
397 fn lshift_u128(lhs: u128, exp: u32) -> u128 {
398 lhs << (3 * exp)
399 }
400}
401
402impl Base for Hexadecimal {
403 const NUMBER: u16 = 16;
404
405 fn new() -> Self {
406 Self
407 }
408
409 fn exp_range(&self) -> ExpRange {
410 ExpRange::from(HEX_EXP_RANGE)
411 }
412
413 fn sig_range(&self) -> SigRange {
414 SigRange::from(HEX_SIG_RANGE)
415 }
416
417 fn pow(exp: u32) -> u64 {
418 HEX_POWERS[exp as usize]
419 }
420
421 fn pow_u128(exp: u32) -> u128 {
422 HEX_POWERS_U128[exp as usize]
423 }
424
425 fn lshift(lhs: u64, exp: u32) -> u64 {
426 lhs << (4 * exp)
427 }
428
429 fn lshift_u128(lhs: u128, exp: u32) -> u128 {
430 lhs << (4 * exp)
431 }
432
433 fn rshift(lhs: u64, exp: u32) -> u64 {
434 lhs >> (4 * exp)
435 }
436
437 fn rshift_u128(lhs: u128, exp: u32) -> u128 {
438 lhs >> (4 * exp)
439 }
440}
441
442impl Base for Decimal {
443 const NUMBER: u16 = 10;
444
445 fn new() -> Self {
446 Self
447 }
448
449 fn exp_range(&self) -> ExpRange {
450 ExpRange(DEC_EXP_RANGE.0, DEC_EXP_RANGE.1)
451 }
452
453 fn sig_range(&self) -> SigRange {
454 SigRange(DEC_SIG_RANGE.0, DEC_SIG_RANGE.1)
455 }
456
457 fn pow(exp: u32) -> u64 {
458 DEC_POWERS[exp as usize]
459 }
460
461 fn pow_u128(exp: u32) -> u128 {
462 DEC_POWERS_U128[exp as usize]
463 }
464
465 fn get_mag(sig: u64) -> u32 {
466 sig.ilog10()
467 }
468
469 fn get_mag_u128(sig: u128) -> u32 {
470 sig.ilog10()
471 }
472}
473
474#[derive(Clone, Copy, Debug)]
500pub struct BigNumBase<T>
501where
502 T: Base,
503{
504 pub sig: u64,
505 pub exp: u64,
506 pub base: T,
507}
508
509impl<T> BigNumBase<T>
510where
511 T: Base,
512{
513 pub fn new(sig: u64, exp: u64) -> Self {
520 let base = T::new();
521
522 let SigRange(min_sig, max_sig) = base.sig_range();
523 let ExpRange(min_exp, _) = base.exp_range();
524
525 if sig >= min_sig && sig <= max_sig {
526 Self { sig, exp, base }
527 } else if sig > max_sig {
528 Self {
531 sig: T::rshift(sig, 1),
532 exp: exp.checked_add(1).unwrap_or_else(|| {
533 panic!(
534 "Unable to create a BigNum with an exp of u64::MAX and a significand greater than max_sig = {}",
535 max_sig
536 )
537 }),
538 base,
539 }
540 } else if exp == 0 {
541 Self { sig, exp, base }
542 } else if sig == 0 {
543 panic!(
544 "Unable to create BigNumBase with exp of {} and sig of 0",
545 exp
546 );
547 } else {
548 let mag = T::get_mag(sig);
549
550 if mag.saturating_add(exp as u32) <= min_exp {
551 Self {
552 sig: T::lshift(sig, exp as u32),
553 exp: 0,
554 base,
555 }
556 } else {
557 let adj = min_exp - mag;
558
559 Self {
560 sig: T::lshift(sig, adj),
561 exp: exp - adj as u64,
562 base,
563 }
564 }
565 }
566 }
567
568 pub fn new_raw(sig: u64, exp: u64) -> Self {
571 let base = T::new();
572
573 if Self::is_valid(sig, exp, base.sig_range()) {
574 Self { sig, exp, base }
575 } else {
576 panic!(
577 "Unable to create BigNumBase with sig
5780x{:x} and exp
579{}
580min_sig:
5810x{:x},
582max_sig:
5830x{:x}",
584 sig,
585 exp,
586 base.sig_range().0,
587 base.sig_range().1
588 );
589 }
590 }
591
592 fn is_valid(sig: u64, exp: u64, range: SigRange) -> bool {
594 sig <= range.max() && (exp == 0 || sig >= range.min())
595 }
596
597 pub fn fuzzy_eq(self, other: Self, margin: u64) -> bool {
603 let SigRange(min_sig, max_sig) = self.base.sig_range();
604
605 let (min, max) = if self > other {
606 (other, self)
607 } else {
608 (self, other)
609 };
610
611 if max.exp == min.exp {
612 max.sig - min.sig <= margin
613 } else if max.exp == min.exp.wrapping_add(1) {
614 max.sig.saturating_sub(margin) <= min_sig && min.sig.saturating_add(margin) >= max_sig
615 } else {
616 false
617 }
618 }
619}
620
621impl<T> PartialEq for BigNumBase<T>
622where
623 T: Base,
624{
625 fn eq(&self, other: &Self) -> bool {
626 self.sig == other.sig && self.exp == other.exp
627 }
628}
629
630impl<T> Eq for BigNumBase<T> where T: Base {}
631
632impl<T> Ord for BigNumBase<T>
633where
634 T: Base,
635{
636 fn cmp(&self, other: &Self) -> Ordering {
637 match self.exp.cmp(&other.exp) {
638 Ordering::Less => Ordering::Less,
639 Ordering::Greater => Ordering::Greater,
640 Ordering::Equal => match self.sig.cmp(&other.sig) {
641 Ordering::Less => Ordering::Less,
642 Ordering::Greater => Ordering::Greater,
643 Ordering::Equal => Ordering::Equal,
644 },
645 }
646 }
647}
648
649impl<T> PartialOrd for BigNumBase<T>
650where
651 T: Base,
652{
653 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
654 Some(self.cmp(other))
655 }
656}
657
658impl<T> Add for BigNumBase<T>
659where
660 T: Base,
661{
662 type Output = Self;
663
664 fn add(self, rhs: Self) -> Self::Output {
665 let base = self.base;
666 let SigRange(min_sig, max_sig) = base.sig_range();
667 let ExpRange(_, max_exp) = base.exp_range();
668
669 let (max, min) = if self > rhs { (self, rhs) } else { (rhs, self) };
670 let shift = max.exp - min.exp;
671
672 if shift >= max_exp as u64 {
673 return max;
675 }
676
677 let result = max.sig.wrapping_add(T::rshift(min.sig, shift as u32));
678
679 let (sig, exp) = if result < max.sig {
680 let diff = u64::MAX - max_sig;
683 (min_sig + T::rshift(result + diff, 1), max.exp + 1)
684 } else if T::NUMBER != 2 && result > max_sig {
685 (T::rshift(result, 1), max.exp + 1)
686 } else {
687 (result, max.exp)
688 };
689
690 Self {
691 sig,
692 exp,
693 base: self.base,
694 }
695 }
696}
697
698impl<T> AddAssign for BigNumBase<T>
699where
700 T: Base,
701{
702 fn add_assign(&mut self, rhs: Self) {
703 *self = *self + rhs;
704 }
705}
706
707impl<T> Sub for BigNumBase<T>
708where
709 T: Base,
710{
711 type Output = Self;
712
713 fn sub(self, rhs: Self) -> Self::Output {
714 let base = self.base;
715 let SigRange(min_sig, _) = base.sig_range();
716 let ExpRange(min_exp, max_exp) = base.exp_range();
717
718 let (max, min) = if self >= rhs {
719 (self, rhs)
720 } else {
721 panic!(
722 "Attempt to subtract
723{:?} from
724{:?}",
725 rhs, self
726 )
727 };
728
729 let shift = max.exp - min.exp;
730
731 if shift >= max_exp as u64 {
732 return max;
734 }
735
736 let result = max.sig.wrapping_sub(T::rshift(min.sig, shift as u32));
737
738 let (res_sig, res_exp) = if result > max.sig {
739 (result, max.exp - 1)
741 } else {
742 (result, max.exp)
743 };
744
745 if res_sig == 0 {
746 Self {
747 sig: 0,
748 exp: 0,
749 base,
750 }
751 } else if res_exp == 0 || res_sig >= min_sig {
752 Self {
753 sig: res_sig,
754 exp: res_exp,
755 base,
756 }
757 } else {
758 let mag = T::get_mag(res_sig);
761 let adj = min_exp - mag;
762
763 if adj as u64 == res_exp {
764 Self {
765 sig: T::lshift(res_sig, adj),
766 exp: 0,
767 base,
768 }
769 } else if adj as u64 >= res_exp {
770 let diff = adj as u64 - res_exp - 1;
774
775 Self {
776 sig: T::lshift(res_sig, diff as u32),
777 exp: 0,
778 base,
779 }
780 } else {
781 Self {
782 sig: T::lshift(res_sig, adj),
783 exp: res_exp - adj as u64,
784 base,
785 }
786 }
787 }
788 }
789}
790
791impl<T> SubAssign for BigNumBase<T>
792where
793 T: Base,
794{
795 fn sub_assign(&mut self, rhs: Self) {
796 *self = *self - rhs;
797 }
798}
799
800impl<T> Mul for BigNumBase<T>
801where
802 T: Base,
803{
804 type Output = BigNumBase<T>;
805
806 fn mul(self, rhs: Self) -> Self::Output {
807 let base = self.base;
808
809 if self.exp == 0 && self.sig == 1 {
810 return rhs;
811 } else if self.exp == 0 && self.sig == 0 {
812 return Self {
813 sig: 0,
814 exp: 0,
815 base,
816 };
817 } else if rhs.exp == 0 && rhs.sig == 1 {
818 return self;
819 } else if rhs.exp == 0 && rhs.sig == 0 {
820 return Self {
821 sig: 0,
822 exp: 0,
823 base,
824 };
825 }
826
827 let (lsig, rsig) = (self.sig as u128, rhs.sig as u128);
828 let (lexp, rexp) = (self.exp, rhs.exp);
829 let SigRange(min_sig, max_sig) = base.sig_range();
830 let ExpRange(min_exp, _) = base.exp_range();
831
832 let res_sig = lsig * rsig;
833 let res_exp = lexp + rexp;
834
835 if res_sig > max_sig as u128 {
836 let mag = T::get_mag_u128(res_sig);
837
838 let adj = mag - min_exp;
839 let sig = T::rshift_u128(res_sig, adj);
840 if sig > u64::MAX as u128 {
841 panic!(
842 "Unable to normalize result for multiplication between {:?} and {:?}",
843 self, rhs
844 );
845 } else {
846 Self {
847 sig: sig as u64,
848 exp: res_exp + adj as u64,
849 base,
850 }
851 }
852 } else if res_exp != 0 && res_sig < min_sig as u128 {
853 panic!(
854 "Found invalid significand while multiplying {:?} and {:?}",
855 self, rhs
856 );
857 } else {
858 Self {
859 sig: res_sig as u64,
860 exp: res_exp,
861 base,
862 }
863 }
864 }
865}
866
867impl<T> MulAssign for BigNumBase<T>
868where
869 T: Base,
870{
871 fn mul_assign(&mut self, rhs: Self) {
872 *self = *self * rhs;
873 }
874}
875
876impl<T> Div for BigNumBase<T>
877where
878 T: Base,
879{
880 type Output = Self;
881
882 fn div(self, rhs: Self) -> Self::Output {
886 match self.cmp(&rhs) {
887 Ordering::Less => return Self::new(0, 0),
888 Ordering::Equal => return Self::new(1, 0),
889 _ => (),
890 }
891
892 if self.exp == 0 {
893 return Self {
894 sig: self.sig / rhs.sig,
895 ..self
896 };
897 }
898
899 let base = self.base;
900 let ExpRange(min_exp, max_exp) = base.exp_range();
901
902 let (lsig, rsig) = (T::lshift_u128(self.sig as u128, max_exp), rhs.sig as u128);
903 let (lexp, rexp) = (self.exp, rhs.exp);
904
905 let res_sig = lsig / rsig;
906 let res_exp = lexp - rexp;
907
908 let mag = T::get_mag_u128(res_sig);
909 let adj = (min_exp + max_exp) - mag;
912
913 if adj as u64 <= res_exp {
914 Self {
917 sig: T::rshift_u128(res_sig, max_exp - adj) as u64,
918 exp: res_exp - adj as u64,
919 ..self
920 }
921 } else {
922 let diff = adj as u64 - res_exp;
923 Self {
927 sig: T::rshift_u128(res_sig, max_exp - adj + diff as u32) as u64,
928 exp: 0,
929 ..self
930 }
931 }
932 }
933}
934
935impl<T> Shl<u64> for BigNumBase<T>
936where
937 T: Base,
938{
939 type Output = Self;
940
941 fn shl(self, rhs: u64) -> Self::Output {
942 let ExpRange(min_exp, _) = self.base.exp_range();
943
944 if self.exp != 0 {
945 Self {
947 exp: self.exp.checked_add(rhs).unwrap(),
948 ..self
949 }
950 } else {
951 let mag = T::get_mag(self.sig);
952 let adj = min_exp - mag;
954
955 if adj as u64 > rhs {
956 Self {
958 sig: T::lshift(self.sig, rhs as u32),
959 exp: 0,
960 ..self
961 }
962 } else {
963 Self {
964 sig: T::lshift(self.sig, adj),
965 exp: rhs - adj as u64,
966 ..self
967 }
968 }
969 }
970 }
971}
972
973impl<T> Shr<u64> for BigNumBase<T>
974where
975 T: Base,
976{
977 type Output = Self;
978
979 fn shr(self, rhs: u64) -> Self::Output {
980 if self.exp >= rhs {
981 return Self {
982 exp: self.exp - rhs,
983 ..self
984 };
985 }
986
987 let mag = T::get_mag(self.sig);
988 let diff = rhs - self.exp;
989
990 if diff > mag as u64 {
991 panic!("Unable to shift {:?} by {}", self, rhs);
992 }
993
994 Self {
995 sig: T::rshift(self.sig, diff as u32),
996 exp: 0,
997 ..self
998 }
999 }
1000}
1001
1002impl<T> Sum for BigNumBase<T>
1003where
1004 T: Base,
1005{
1006 fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
1007 if let Some(elem) = iter.next() {
1008 iter.fold(elem, |acc, n| acc + n)
1009 } else {
1010 Self::from(0)
1011 }
1012 }
1013}
1014
1015impl<T> Product for BigNumBase<T>
1016where
1017 T: Base,
1018{
1019 fn product<I: Iterator<Item = Self>>(mut iter: I) -> Self {
1020 if let Some(elem) = iter.next() {
1021 iter.fold(elem, |acc, n| acc * n)
1022 } else {
1023 Self::from(0)
1024 }
1025 }
1026}
1027
1028impl Display for BigNumBase<Decimal> {
1029 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1030 if self.exp == 0 {
1031 let mag = Decimal::get_mag(self.sig);
1035
1036 if mag < 3 {
1037 f.write_fmt(format_args!("{}", self.sig))
1038 } else if mag < 6 {
1039 f.write_fmt(format_args!("{0:.5}k", (self.sig as f64 / 1e3).to_string()))
1040 } else if mag < 9 {
1041 f.write_fmt(format_args!("{0:.5}m", (self.sig as f64 / 1e6).to_string()))
1042 } else if mag < 12 {
1043 f.write_fmt(format_args!("{0:.5}b", (self.sig as f64 / 1e9).to_string()))
1044 } else if mag < 15 {
1045 f.write_fmt(format_args!(
1046 "{0:.5}t",
1047 (self.sig as f64 / 1e12).to_string()
1048 ))
1049 } else {
1050 let res = (self.sig as f64) / 10f64.powi(mag as i32);
1051
1052 if res == 10.0 {
1053 f.write_fmt(format_args!("9.999e{}", mag))
1054 } else {
1055 f.write_fmt(format_args!("{0:.5}e{1}", res.to_string(), mag))
1056 }
1057 }
1058 } else {
1059 let min_exp = self.base.exp_range().min();
1060 let res = (self.sig as f64) / 10f64.powi(min_exp as i32);
1061
1062 if res == 10.0 {
1063 f.write_fmt(format_args!("9.999e{}", min_exp as u64 + self.exp))
1064 } else {
1065 f.write_fmt(format_args!(
1066 "{0:.5}e{1}",
1067 res.to_string(),
1068 min_exp as u64 + self.exp
1069 ))
1070 }
1071 }
1072 }
1073}
1074
1075impl<T> Mul<f64> for BigNumBase<T>
1076where
1077 T: Base,
1078{
1079 type Output = Self;
1080
1081 fn mul(self, rhs: f64) -> Self::Output {
1082 let min_exp = self.base.exp_range().min();
1083 let cutoff_exp = min_exp / 2;
1084 let cutoff = T::pow(cutoff_exp);
1085 if rhs > cutoff as f64 {
1086 if rhs > u64::MAX as f64 {
1087 let mag = rhs.log(T::NUMBER as f64).floor() as u64;
1088 let diff = mag - min_exp as u64;
1089
1090 self * Self::new((rhs / (T::NUMBER as f64).powi(diff as i32)) as u64, diff)
1091 } else {
1092 self * (rhs.ceil() as u64)
1095 }
1096 } else {
1097 (self * (rhs * cutoff as f64).ceil() as u64) / cutoff
1098 }
1099 }
1100}
1101
1102impl<T> MulAssign<f64> for BigNumBase<T>
1103where
1104 T: Base,
1105{
1106 fn mul_assign(&mut self, rhs: f64) {
1107 *self = *self * rhs;
1108 }
1109}
1110
1111#[cfg(test)]
1112mod tests {
1113 use std::iter::repeat_n;
1114
1115 use macros::test_macros::assert_eq_bignum;
1116 use rand::distributions::Uniform;
1117 use rand::prelude::Distribution;
1118 use rand::thread_rng;
1119 use traits::Succ;
1120
1121 use super::*;
1122 use crate::Binary;
1123
1124 #[test]
1125 fn new_binary_test() {
1126 type BigNum = BigNumBase<Binary>;
1127 assert_eq_bignum!(BigNum::new(1, 0), BigNum::new_raw(1, 0));
1129 assert_eq_bignum!(BigNum::new(0b100, 2), BigNum::new_raw(0b10000, 0));
1130 assert_eq_bignum!(BigNum::new(1 << 62, 20), BigNum::new_raw(1 << 63, 19));
1131 assert_eq_bignum!(BigNum::new(1 << 62, 20), BigNum::new_raw(1 << 63, 19));
1132 }
1133
1134 #[test]
1135 fn add_binary_test() {
1136 type BigNum = BigNumBase<Binary>;
1137 assert_eq_bignum!(
1138 BigNum::new(0x100, 0) + BigNum::new(0x0100_0000, 4),
1139 BigNum::new_raw(0x1000_0100, 0)
1140 );
1141 assert_eq_bignum!(
1142 BigNum::new(0x1000_0000, 32) + BigNum::new(0x0100_0000, 4),
1143 BigNum::new_raw(0x1000_0000_1000_0000, 0)
1144 );
1145 assert_eq_bignum!(
1146 BigNum::new(0xFFFF_FFFF, 32) + BigNum::new(0x8000_0000, 1),
1147 BigNum::new_raw(0x8000_0000_0000_0000, 1)
1148 );
1149 assert_eq_bignum!(
1150 BigNum::new(0xFFFF_FFFF_FFFF_FFFF, 1) + 0x1u64,
1151 BigNum::new_raw(0xFFFF_FFFF_FFFF_FFFF, 1)
1152 );
1153 assert_eq_bignum!(
1154 BigNum::new(0xFFFF_FFFF_FFFF_FFFF, 1) + 0x2u64,
1155 BigNum::new_raw(0x8000_0000_0000_0000, 2)
1156 );
1157 }
1158
1159 #[test]
1160 fn add_hex_test() {
1161 type BigNum = BigNumBase<Hexadecimal>;
1162 assert_eq_bignum!(
1163 BigNum::from(0xFFFF_FFFF_FFFF_FFFFu64) + 1u64,
1164 BigNum::new_raw(0x1000_0000_0000_0000, 1)
1165 );
1166 assert_eq_bignum!(
1167 BigNum::from(0xFFFF_FFFF_FFFF_FFFEu64) + 1u64,
1168 BigNum::new_raw(0xFFFF_FFFF_FFFF_FFFF, 0)
1169 );
1170 assert_eq_bignum!(
1171 BigNum::new(0xFFFF_FFFF_FFFF_FFFEu64, 10) + 0x0100_0000_0000u64,
1172 BigNum::new_raw(0xFFFF_FFFF_FFFF_FFFF, 10)
1173 );
1174 assert_eq_bignum!(
1175 BigNum::new(0xFFFF_FFFF_FFFF_FFFFu64, 0xFFFF_FFFF_FFFF_0000) + 0x0100_0000_0000u64,
1176 BigNum::new_raw(0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_0000)
1177 );
1178 assert_eq_bignum!(
1179 BigNum::new(0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF)
1180 + BigNum::new(0x1FFF_FFFF_FFFF_FFFF, 0xFFFF_FFF0),
1181 BigNum::new_raw(0x1000_0000_0000_0000, 0x1_0000_0000)
1182 );
1183 assert_eq_bignum!(
1184 BigNum::new(0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF)
1185 + BigNum::new(0x1FFF_FFFF_FFFF_FFFF, 0xFFFF_FFEF),
1186 BigNum::new_raw(0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF)
1187 );
1188 }
1189
1190 #[test]
1191 fn add_decimal_test() {
1192 type BigNum = BigNumBase<Decimal>;
1193
1194 assert_eq_bignum!(
1195 BigNum::from(1) + BigNum::new(1243123123, 3),
1196 BigNum::new_raw(1243123123001, 0)
1197 );
1198 assert_eq_bignum!(
1199 BigNum::from(1000) + BigNum::new(10u64.pow(19) - 1, 3),
1200 BigNum::new_raw(10u64.pow(18), 4)
1201 );
1202 assert_eq_bignum!(
1203 BigNum::new(10u64.pow(19) - 1, 13) + BigNum::new(10u64.pow(18), 3),
1204 BigNum::new_raw(10u64.pow(18) + 10u64.pow(7) - 1, 14)
1205 );
1206 }
1207
1208 #[test]
1209 fn add_arbitrary_test() {
1210 create_default_base!(Base61, 61);
1211 type BigNum = BigNumBase<Base61>;
1212
1213 let SigRange(min_sig, max_sig) = Base61::calculate_ranges().1;
1214
1215 assert_eq_bignum!(
1216 BigNum::from(0xFFFF_FFFF_FFFF_FFFEu64) + 1u64,
1217 BigNum::new_raw(((u64::MAX as u128 + 1) / 61u128) as u64, 1)
1218 );
1219 assert_eq_bignum!(BigNum::from(1u64) + 1u64, BigNum::new_raw(2, 0));
1220 assert_eq_bignum!(
1221 BigNum::new(max_sig, 10) + BigNum::new(1, 10),
1223 BigNum::new_raw(min_sig, 11)
1224 );
1225 assert_eq_bignum!(
1226 BigNum::new(max_sig, 10) + BigNum::new(61u64, 9),
1227 BigNum::new_raw(min_sig, 11)
1228 );
1229 }
1230
1231 #[test]
1232 fn sub_binary_test() {
1233 type BigNum = BigNumBase<Binary>;
1234
1235 assert_eq_bignum!(
1236 BigNum::new(0x100, 32) - BigNum::new(0x0080_0000_0000, 0),
1237 BigNum::new_raw(0x0080_0000_0000, 0)
1238 );
1239 assert_eq_bignum!(
1240 BigNum::new(0x1000_0000_0000_0000, 0) - BigNum::new(0x0010_0000_0000_0000, 8),
1241 BigNum::from(0)
1242 );
1243 assert_eq_bignum!(
1244 BigNum::new(0xFFFF_FFFF_FFFF_FFFF, 48) - BigNum::new(0x8000_0000_0000_0000, 16),
1245 BigNum::new(0xFFFF_FFFF_7FFF_FFFF, 48)
1246 );
1247 assert_eq_bignum!(
1248 BigNum::new(0xFFFF_FFFF_FFFF_FFFF, 48) - BigNum::new(0xFFFF_FFFF_0000_0000, 48),
1249 BigNum::new(0xFFFF_FFFF_0000_0000, 16)
1250 );
1251 assert_eq_bignum!(
1252 BigNum::new(0x8000_0000_0000_0000, 48) - BigNum::new(0xFFFF_FFFF_0000_0000, 16),
1253 BigNum::new(0xFFFF_FFFE_0000_0002, 47)
1254 );
1255 }
1256
1257 #[test]
1260 fn sub_arbitrary_test() {
1261 create_default_base!(Base61, 61);
1262 type BigNum = BigNumBase<Base61>;
1263
1264 let SigRange(min_sig, max_sig) = Base61::calculate_ranges().1;
1265
1266 assert_eq_bignum!(
1271 BigNum::new(min_sig, 1) - 61u64,
1272 BigNum::new_raw(max_sig - 60, 0)
1273 );
1274 assert_eq_bignum!(
1275 BigNum::new(max_sig, 1) - max_sig,
1276 BigNum::new_raw(max_sig - max_sig / 61, 1)
1277 );
1278 assert_eq_bignum!(
1279 BigNum::new(12341098709128730491, 11234) - BigNum::new(12341098709128730491, 11234),
1280 BigNum::from(0)
1281 )
1282 }
1283
1284 #[test]
1285 fn mul_binary_test() {
1286 type BigNum = BigNumBase<Binary>;
1287 let SigRange(min_sig, max_sig) = Binary::calculate_ranges().1;
1288
1289 assert_eq_bignum!(
1290 BigNum::from(14215125) * BigNum::from(120487091724u64),
1291 BigNum::from(120487091724u64 * 14215125)
1292 );
1293 assert_eq_bignum!(
1295 BigNum::from(min_sig) * BigNum::from(min_sig),
1296 BigNum::new(min_sig, 63)
1297 );
1298 assert_eq_bignum!(
1299 BigNum::from(min_sig) * BigNum::from(min_sig),
1300 BigNum::new(min_sig, 63)
1301 );
1302 assert_eq_bignum!(
1303 BigNum::new(max_sig, 1) * BigNum::new(max_sig, 1),
1304 BigNum::new(max_sig - 1, 64 + 2)
1305 );
1306 assert_eq_bignum!(
1307 BigNum::new(max_sig, 1123) * BigNum::new(max_sig, 11325),
1308 BigNum::new(max_sig - 1, 64 + 1123 + 11325)
1309 );
1310 assert_eq_bignum!(
1311 BigNum::new(max_sig - min_sig, 123410923) * BigNum::from(0),
1312 BigNum::from(0)
1313 );
1314 assert_eq_bignum!(
1315 BigNum::new(max_sig - min_sig, 123410923) * BigNum::from(1),
1316 BigNum::new(max_sig - min_sig, 123410923)
1317 );
1318 }
1319
1320 #[test]
1321 fn binary_div_test() {
1322 type BigNum = BigNumBase<Binary>;
1323 let SigRange(min_sig, max_sig) = Binary::calculate_ranges().1;
1324
1325 assert_eq_bignum!(
1326 BigNum::from(123412341234432u64) / BigNum::from(1221314),
1327 BigNum::from(123412341234432u64 / 1221314)
1328 );
1329 assert_eq_bignum!(
1330 BigNum::from(123412341234432u64) / BigNum::from(123412341234432u64),
1331 BigNum::from(1)
1332 );
1333 assert_eq_bignum!(
1334 BigNum::from(123412341234432u64) / BigNum::from(12341234123412341234u64),
1335 BigNum::from(0)
1336 );
1337 assert_eq_bignum!(
1338 BigNum::new(123412341234432u64, 12341234) / BigNum::new(123412341234432u64, 12341234),
1339 BigNum::from(1)
1340 );
1341 assert_eq_bignum!(
1342 BigNum::new(123412341234432u64, 12341234) / BigNum::new(123412341234432u64, 12341235),
1343 BigNum::from(0)
1344 );
1345 assert_eq_bignum!(
1346 BigNum::new(123412341234432u64, 12341234) / BigNum::new(123412341234433u64, 12341234),
1347 BigNum::from(0)
1348 );
1349 assert_eq_bignum!(
1350 BigNum::new(min_sig, 12341234) / BigNum::new(min_sig, 12341233),
1351 BigNum::from(2)
1352 );
1353 assert_eq_bignum!(
1354 BigNum::new(min_sig, 12341234) / BigNum::new(min_sig, 1),
1355 BigNum::new(min_sig, 12341234 - 64)
1356 );
1357 assert_eq_bignum!(
1358 BigNum::new(max_sig, 12341234) / BigNum::new(max_sig, 1),
1359 BigNum::new(min_sig, 12341234 - 64)
1360 );
1361 assert_eq_bignum!(
1362 BigNum::new(max_sig, 12341234) / BigNum::new(min_sig, 1),
1363 BigNum::new(max_sig, 12341234 - 64)
1364 );
1365 assert_eq_bignum!(
1366 BigNum::new(max_sig, 63 + 12341234) / BigNum::new(min_sig, 1),
1367 BigNum::new(max_sig, 12341234 - 1)
1368 );
1369 }
1370
1371 #[test]
1372 fn binary_shifts() {
1373 type BigNum = BigNumBase<Binary>;
1374
1375 assert_eq_bignum!(BigNum::new(0b100, 0) << 1, BigNum::new(0b1000, 0));
1376 assert_eq_bignum!(BigNum::new(0b100, 0) << 2, BigNum::new(0b10000, 0));
1377 assert_eq_bignum!(BigNum::new(u64::MAX, 1) << 3, BigNum::new(u64::MAX, 4));
1378 assert_eq_bignum!(BigNum::new(u64::MAX, 0) << 64, BigNum::new(u64::MAX, 64));
1379
1380 assert_eq_bignum!(BigNum::new(0b100, 0) >> 1, BigNum::new(0b10, 0));
1381 assert_eq_bignum!(BigNum::new(0b100, 0) >> 2, BigNum::new(0b1, 0));
1382 assert_eq_bignum!(BigNum::new(u64::MAX, 1) >> 3, BigNum::new(u64::MAX / 4, 0));
1383 assert_eq_bignum!(BigNum::new(u64::MAX, 0) >> 63, BigNum::from(1));
1384 assert_eq_bignum!(
1385 BigNum::new(u64::MAX, 100) >> 105,
1386 BigNum::new(u64::MAX / 32, 0)
1387 );
1388 }
1389
1390 #[test]
1391 fn display_test() {
1392 type BigNum = BigNumBase<Decimal>;
1393
1394 assert_eq!(format!("{}", BigNum::from(1)), "1");
1395 assert_eq!(format!("{}", BigNum::from(999)), "999");
1396 assert_eq!(format!("{}", BigNum::from(1000)), "1k");
1397 assert_eq!(format!("{}", BigNum::from(1001)), "1.001k");
1398 assert_eq!(format!("{}", BigNum::from(999999)), "999.9k");
1399 assert_eq!(format!("{}", BigNum::from(1000000)), "1m");
1400 assert_eq!(format!("{}", BigNum::from(1001000)), "1.001m");
1401 assert_eq!(format!("{}", BigNum::from(999999999)), "999.9m");
1402 assert_eq!(format!("{}", BigNum::from(1000000000)), "1b");
1403 assert_eq!(format!("{}", BigNum::from(1001000000)), "1.001b");
1404 assert_eq!(format!("{}", BigNum::from(999999999999)), "999.9b");
1405 assert_eq!(format!("{}", BigNum::from(1000000000000)), "1t");
1406 assert_eq!(format!("{}", BigNum::from(1001000000000)), "1.001t");
1407 assert_eq!(format!("{}", BigNum::from(999999999999999)), "999.9t");
1408 assert_eq!(format!("{}", BigNum::from(1000000000000000)), "1e15");
1409 assert_eq!(format!("{}", BigNum::from(1001000000000000)), "1.001e15");
1410 assert_eq!(format!("{}", BigNum::from(999999999999999999)), "9.999e17");
1411 assert_eq!(format!("{}", BigNum::new(9999, 123523)), "9.999e123526");
1412 assert_eq!(format!("{}", BigNum::new(9099, 123523)), "9.099e123526");
1413 assert_eq!(format!("{}", BigNum::new(999, 123523)), "9.99e123525");
1414 }
1415
1416 #[test]
1417 fn test_random_bin() {
1418 #![allow(clippy::erasing_op)]
1419
1420 type BigNum = BigNumBase<Binary>;
1421
1422 let dist: Uniform<BigNum> = Uniform::new(BigNum::from(0), BigNum::new(1, u64::MAX / 2));
1423 let rng = &mut thread_rng();
1424 let nums = dist.sample_iter(rng).take(100);
1425
1426 for n in nums {
1427 assert_eq_bignum!(n + n, n * 2);
1428 assert_eq_bignum!(n + n + n, n * BigNum::new(3, 0));
1429 assert_eq_bignum!(2 * n + 2 * n, 4 * n);
1430 assert_eq_bignum!(n / 2 / 16, n / 32);
1431 assert_eq_bignum!(n * 0, n / (n.succ()));
1432 assert_eq_bignum!(n + 0, n / 1);
1433 assert_eq_bignum!(n / n, BigNum::from(1));
1434 }
1435 }
1436
1437 #[test]
1438 fn sum_test_binary() {
1439 type BigNum = BigNumBin;
1440
1441 let a: [BigNum; 0] = [];
1442 let b: [BigNum; 10] = [BigNum::from(100); 10];
1443 let c = (0u64..100).map(BigNum::from);
1444 let d: [BigNum; 100] = [BigNum::from(1 << 63); 100];
1445
1446 assert_eq!(BigNum::from(0), a.into_iter().sum());
1447 assert_eq!(BigNum::from(1000), b.into_iter().sum());
1448 assert_eq!(BigNum::from(4950), c.sum());
1449
1450 assert_eq!(BigNum::from(1 << 63) * 100, d.into_iter().sum());
1451 }
1452
1453 #[test]
1454 fn prod_test_binary() {
1455 type BigNum = BigNumBin;
1456
1457 let a: [BigNum; 0] = [];
1458 let b: [BigNum; 10] = [BigNum::from(2); 10];
1459 let c: [BigNum; 10] = [BigNum::from(8); 10];
1460 let d: [BigNum; 100] = [BigNum::from(1 << 63); 100];
1461
1462 assert_eq!(BigNum::from(0), a.into_iter().product());
1463 assert_eq!(BigNum::from(1024), b.into_iter().product());
1464 assert_eq!(BigNum::from(1024 * 1024 * 1024), c.into_iter().product());
1465
1466 assert_eq!(BigNum::new(1, 63 * 100), d.into_iter().product());
1467 }
1468
1469 #[should_panic]
1470 #[test]
1471 fn fuzzy_eq_failed1() {
1472 type BigNum = BigNumDec;
1473
1474 let a = BigNum::new(DEC_SIG_RANGE.1, 234);
1475 let b = a + a + a + a + a;
1476 let c = 2 * a + 3 * a;
1477
1478 assert_eq!(b, c);
1479 }
1480
1481 #[should_panic]
1482 #[test]
1483 fn fuzzy_eq_failed2() {
1484 type BigNum = BigNumDec;
1485
1486 let a = BigNum::new(DEC_SIG_RANGE.1, 234);
1487 let d: BigNum = repeat_n(a, 20).sum();
1488 let e = a * 20;
1489
1490 assert_eq!(d, e)
1491 }
1492
1493 #[test]
1494 fn fuzzy_eq_test() {
1495 type BigNum = BigNumDec;
1496
1497 let a = BigNum::new(DEC_SIG_RANGE.1, 234);
1498 let b = a + a + a + a + a;
1499 let c = 2 * a + 3 * a;
1500 let d: BigNum = repeat_n(a, 20).sum();
1501 let e = a * 20;
1502
1503 assert!(b.fuzzy_eq(c, 4));
1505 assert!(d.fuzzy_eq(e, 20));
1507 }
1508
1509 #[test]
1510 fn float_mult_test() {
1511 type BigNum = BigNumDec;
1512
1513 let a = BigNum::new(DEC_SIG_RANGE.0, 1234);
1514 let b = BigNum::new(DEC_SIG_RANGE.1, 1234);
1515
1516 assert_eq!(a * 1.5, a * 3 / 2);
1517 assert_eq!(a * 12.5, a * 100 / 8);
1518 assert_eq!(a * 0.5, a / 2);
1519
1520 let a_overflow_res = a * 1e250;
1522 let a_exp_res = a * BigNum::new(1, 250);
1523 let (min, max) = if a_overflow_res > a_exp_res {
1524 (a_exp_res, a_overflow_res)
1525 } else {
1526 (a_overflow_res, a_exp_res)
1527 };
1528
1529 assert!(max / (max - min) > BigNum::from(100000));
1531
1532 assert_eq!(b * 1.5, b * 3 / 2);
1533 assert_eq!(b * 12.5, b * 100 / 8);
1534 assert_eq!(b * 0.5, b / 2);
1535
1536 let b_overflow_res = b * 1.234e280;
1537 let b_exp_res = b * BigNum::new(1234, 277);
1538 let (min, max) = if b_overflow_res > b_exp_res {
1539 (b_exp_res, b_overflow_res)
1540 } else {
1541 (b_overflow_res, b_exp_res)
1542 };
1543
1544 assert!(max / (max - min) > BigNum::from(100000));
1546 }
1547}