bignumbe_rs/
lib.rs

1//! This crate defines a custom medium-precision number type. It can support any base `b`
2//! in the range `[0, 65535]`, and can approximately represent numbers up to
3//! `b ^ u64::MAX` (actually a bit higher than that but the math is complicated). A core
4//! goal for this type was that it can implement `Copy` and as a result it can be used in
5//! almost any context a normal unsigned integer would be valid.
6
7// public re-exporting
8#[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)]
33/// This represents the non-inclusive range of exponents that constitute a valid
34/// non-compact significand in the given base. You only need to use this if manually
35/// defining a custom base (if performance is non-critical I would recommend using the
36/// `create_default_base` macro).
37///
38/// # Examples
39/// ```
40/// use bignumbe_rs::{ExpRange, Binary, Base};
41///
42/// let ExpRange(min_exp, max_exp) = Binary::calculate_ranges().0;
43///
44/// // Since the range of valid significands for non-compact Binary BigNum instances is
45/// // [2^63, 2^64), we expect an ExpRange of (63, 64)
46/// assert_eq!(min_exp, 63);
47/// assert_eq!(max_exp, 64);
48/// ```
49pub 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)]
70/// This represents the inclusive range of values that constitute a valid non-compact
71/// significand in the given base. You only need to use this if manually defining a custom
72/// base (if performance is non-critical I would recommend using the `create_default_base`
73/// macro).
74///
75/// # Examples
76/// ```
77/// use bignumbe_rs::{SigRange, Binary, Base};
78///
79/// let SigRange(min_sig, max_sig) = Binary::calculate_ranges().1;
80///
81/// // Since the range of valid significands for non-compact Binary BigNum instances is
82/// // [2^63, 2^64), we expect a SigRange of (2^63, 2^64 - 1)
83/// assert_eq!(min_sig, 1 << 63);
84/// assert_eq!(max_sig, u64::MAX);
85/// ```
86pub 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
106/// If performance isn't critical I'd highly recommend the `create_default_base` macro
107/// which creates a base with sensible defaults. The only reason to create a custom
108/// implementation is if you find the default implementations' operations to be a
109/// bottleneck. In this case I'd recommend looking at my implementation of the `Decimal`
110/// base as a guide.
111///
112/// This trait is used to indicate that a type is a valid base for a BigNumBase. It
113/// contains metadata and functions that can be used to efficiently handle arbitrary
114/// bases. Importantly you must ensure all of the following:
115/// - `base.exp_range().max() = base.exp_range().min() + 1`
116/// - `base.exp_range().min() > 0`
117/// - `base.sig_range().min() = base.pow(exp_range().min())`
118/// - `base.sig_range().max() = base.pow(exp_range().max()) - 1`
119/// - `B::pow(n) = NUMBER.pow(n)` for all `n < base.exp_range().max()`
120/// - `B::rshift(lhs, exp) = lhs / B::NUMBER.pow(n)` for all `n <= base.exp_range().max()`
121/// - `B::lshift(lhs, exp) = lhs * B::NUMBER.exp(n)` for all
122///     `n <= base.exp_range().max()`
123/// - `B::get_mag(n)` should return the highest exponent `x` such that `n >= B::pow(x)`,
124///     for all `n <= exp_range().max()`
125/// - `base.sig_range().min() * B::NUMBER > u64::MAX`
126///     - This restriction allows us to conveniently handle some construction cases
127///
128/// The above requirements also hold for the `u128` versions of
129/// `lshift, rshift, get_mag, pow` which are used for multiplication and division (since
130/// those calculations involve projecting values to `u128` to preserve information)
131///
132/// Some of these calculations have the potential to overflow a `u64` so you may need to
133/// think of other ways to compute them if you plan to verify them manually.
134///
135/// Additionally, the implementers will be copied on every math operation and in some
136/// other contexts, so ensure that they are lightweight. E.g. even though
137/// ```
138/// #[derive(Clone, Copy, Debug)]
139/// pub struct CustomBase {
140///     metadata: [u8; 10000000000],
141/// }
142/// ```
143/// is valid, it's ill-advised here. If you need a table of powers I would recommend a
144/// global const array that you reference in the `pow` method.
145///
146/// The recommended format for
147/// a non-performance critical simple Base definition and implementation is:
148/// ```
149/// use bignumbe_rs::{ExpRange, SigRange, Base};
150///
151/// #[derive(Clone, Copy, Debug)]
152/// pub struct Base13 {
153///     exp_range: ExpRange,
154///     sig_range: SigRange
155/// }
156///
157/// impl Base for Base13{
158///     const NUMBER: u16 = 13;
159///
160///     fn new() -> Self {
161///         let (exp_range, sig_range) = Self::calculate_ranges();
162///         Self {exp_range, sig_range}
163///     }
164///
165///     fn exp_range(&self) -> ExpRange {
166///         self.exp_range
167///     }
168///
169///     fn sig_range(&self) -> SigRange {
170///         self.sig_range
171///     }
172/// }
173/// ```
174pub trait Base: Copy + Debug {
175    /// This contains the numeric value of the type. E.g. for binary 2, for decimal 10,
176    /// etc.
177    const NUMBER: u16;
178
179    /// Function that can create an instance of this Base. Users should never have to
180    /// manually create instances of this type. This is called implicitly on every
181    /// call to `BigNumBase<Self>::new()` so it should be as lightweight as possible. Note
182    /// that it is not called when creating a BigNumBase<Self> from another, like when
183    /// performing an addition. In this case the base is simply copied over.
184    fn new() -> Self;
185
186    /// Function that fetches the non-inclusive range of the exponent for the significand
187    /// in the BigNum with this base. E.g. the range for binary is [63, 64), since the
188    /// range of the significand is [2^63, 2^64)
189    fn exp_range(&self) -> ExpRange;
190
191    /// Function that fetches the inclusive range for the significand in the BigNum with
192    /// this base. E.g. for binary the range of the significand is [2^63, 2^64 - 1]
193    fn sig_range(&self) -> SigRange;
194
195    /// This is a function that computes `Self::NUMBER ^ exp`. It has a default
196    /// implementation that computes the value directly. It is recommended to override
197    /// this behavior if there is a trick to the exponentiation (like how for binary
198    /// `2^n = (1 << n)`). You can also create a gloabl const lookup table and reference
199    /// that.
200    fn pow(exp: u32) -> u64 {
201        (Self::NUMBER as u64).pow(exp)
202    }
203
204    /// This is a function that computes the same value as `pow` but in a u128 value.
205    /// Mostly useful to help with multiplication/division, and as such it's probably
206    /// unnecessary to override it unless multiplication/division performance is critical
207    fn pow_u128(exp: u32) -> u128 {
208        (Self::NUMBER as u128).pow(exp)
209    }
210
211    /// This function calculates the ranges for the exponent and the significand. It is
212    /// not particularly efficient so if performance is a concern you should not use it.
213    /// It mainly exists to facilitate the `create_default_base!` macro. It is recommended
214    /// to store the ranges in a const and return them directly in the `exp_range` and
215    /// `sig_range` methods if convenient.
216    fn calculate_ranges() -> (ExpRange, SigRange) {
217        if Self::NUMBER.is_power_of_two() && Self::NUMBER.ilog2().is_power_of_two() {
218            // This is a special case where sig_max = u64::MAX. We have to handle it
219            // specially to avoid overflowing the u64
220            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    /// This is a function that computes `lhs * (Self::NUMBER ^ exp)`. There is a default
235    /// implementation that obtains the value of `Self::NUMBER ^ exp` via the `pow` method
236    /// for this type, and does a division. It is recommended to override this method if
237    /// there is a trick for the division (like how in binary,
238    /// `lhs * (2 ^ exp) = lhs >> exp`, or in octal `lhs * (8 ^ exp) = lhs >> (3 * exp)`
239    fn lshift(lhs: u64, exp: u32) -> u64 {
240        lhs * Self::pow(exp)
241    }
242    /// This is a function that computes `lhs / (Self::NUMBER ^ exp)`. There is a default
243    /// implementation that obtains the value of `Self::NUMBER ^ exp` via the `pow` method
244    /// for this type, and does a multiplication. It is recommended to override this
245    /// method if there is a trick for the division (like how in binary,
246    /// `lhs / (2 ^ exp) = lhs << exp`, or in octal `lhs / (8 ^ exp) = lhs << (3 * exp)`
247    fn rshift(lhs: u64, exp: u32) -> u64 {
248        lhs / Self::pow(exp)
249    }
250
251    /// This is a function that computes the same thing as `lshift` but in a u128 value.
252    /// Mostly useful to help with multiplication/division, and as such it's probably
253    /// unnecessary to override it unless multiplication/division performance is critical
254    fn lshift_u128(lhs: u128, exp: u32) -> u128 {
255        lhs * Self::pow_u128(exp)
256    }
257
258    /// This is a function that computes the same thing as `rshift` but in a u128 value.
259    /// Mostly useful to help with multiplication/division, and as such it's probably
260    /// unnecessary to override it unless multiplication/division performance is critical
261    fn rshift_u128(lhs: u128, exp: u32) -> u128 {
262        lhs / Self::pow_u128(exp)
263    }
264
265    /// This is a function that computes the highest power `x` such that
266    /// `sig >= (Self::NUMBER ^ x)`. There is a default implementation that uses `ilog`,
267    /// and it is recommended to use this unless there is a special way to find the
268    /// magnitude (e.g. binary and decimal have specialized `ilog` implementations).
269    /// As a special case, bases that are powers of 2 or 10 can use log arithmetic to
270    /// convert. I tried this with octal and hexadecimal but it had no noticeable impact.
271    fn get_mag(sig: u64) -> u32 {
272        sig.ilog(Self::NUMBER as u64)
273    }
274
275    /// This is a function that computes the same thing as `get_mag` but in a u128 value.
276    /// Mostly useful to help with multiplication/division, and as such it's probably
277    /// unnecessary to override it unless multiplication/division performance is critical
278    fn get_mag_u128(sig: u128) -> u32 {
279        sig.ilog(Self::NUMBER as u128)
280    }
281
282    /// This method just fetches `Self::NUMBER` but is provided as an instance method for
283    /// convenience. Overriding it is undefined behavior
284    fn as_number(&self) -> u16 {
285        Self::NUMBER
286    }
287}
288
289/// This type represents a binary base. It contains more efficient overrides of the
290/// `Base` functions to improve performance.
291#[derive(Clone, Copy, Debug)]
292pub struct Binary;
293pub type BigNumBin = BigNumBase<Binary>;
294
295/// This type represents an octal base. It contains more efficient overrides of the
296/// `Base` functions to improve performance.
297#[derive(Clone, Copy, Debug)]
298pub struct Octal;
299pub type BigNumOct = BigNumBase<Octal>;
300
301/// This type represents a hexadecimal base. It contains more efficient overrides of the
302/// `Base` functions to improve performance.
303#[derive(Clone, Copy, Debug)]
304pub struct Hexadecimal;
305pub type BigNumHex = BigNumBase<Hexadecimal>;
306
307/// This type represents a decimal base. It contains more efficient overrides of the
308/// `Base` functions to improve performance.
309#[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(63, 64)
321        ExpRange::from(BIN_EXP_RANGE)
322    }
323
324    fn sig_range(&self) -> SigRange {
325        //SigRange(1 << 63, u64::MAX)
326        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/// This is the main struct for `bignumbe-rs`.
475///
476/// It takes a generic argument for the base, e.g.
477/// `BigNumBase<Binary>`. It is recommended to either create a custom type alias or
478/// use one of the predefined ones (`BigNumBin, BigNumOct, BigNumDec, BigNumHex`). You
479/// should be able to use them pretty much exactly like other numbers in most contexts.
480/// For convenience I define `From` and all math operations for `u64`, but keep in mind
481/// that the `From` implementation, like `new`, involves recalculating the base ranges.
482///
483/// ```
484/// use bignumbe_rs::{BigNumBase, Binary};
485///
486/// type BigNum = BigNumBase<Binary>;
487///
488/// let bn1 = BigNum::from(1);
489/// let bn2 = BigNum::from(u64::MAX);
490///
491/// // Since this operation's result doesn't fit in `u64` it wraps over to the minimum
492/// // significand and increments the `exp`
493/// assert_eq!(bn1 + bn2, BigNum::new(1 << 63, 1));
494///
495/// assert_eq!(bn1 / bn2, BigNum::from(0));
496/// assert_eq!(bn1 * bn2, bn2);
497/// assert_eq!(bn2 * bn2, BigNum::new(u64::MAX - 1, 64));
498/// ```
499#[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    /// Creates a new `BigNumBase` instance that represents the value
514    /// `sig * T::NUMBER^exp`. E.g. `BigNumBin::new(12341234, 12341)` represents
515    /// `12341234 * 2^12341`. This method will perform normalization if necessary, to
516    /// ensure the significand is in the valid range (if the number is non-compact). As
517    /// such when creating a BigNum from scratch you should always use this unless you
518    /// absolutely need a raw constructor
519    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            // Since we know `max_sig * base.as_number() > u64::MAX`, we also know
529            // that `sig / base.as_number() <= max_sig`
530            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    /// Creates a BigNumBase directly from values, panicking if not possible. This is
569    /// mostly for testing but may be more performant on inputs that are guaranteed valid
570    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    /// Returns true if the values are valid for the current base
593    fn is_valid(sig: u64, exp: u64, range: SigRange) -> bool {
594        sig <= range.max() && (exp == 0 || sig >= range.min())
595    }
596
597    /// Allows fuzzy comparison between two values. Since operations can result in loss of
598    /// precision this allows you to compare values that may have drifted. Since each
599    /// operation can result in an error of 1, an upper bound is the sum of the number of
600    /// operations performed on each operand. E.g. for `n: BigNumDec`, to ensure that
601    /// (n * 1000) / 500 = (n / 500) * 1000, you might use a margin of 4
602    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            // This shift is guaranteed to result in 0 on lhs, no need to compute
674            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            // How much we need to add to the overflow result to make up for differences
681            // in the significand's range
682            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            // This shift is guaranteed to result in 0 on rhs, no need to compute
733            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            // Wrapping occurred, handle it by decrementing the exponent
740            (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            // This operation can result in arbitrary loss in magnitude so we have to
759            // calculate the differential directly
760            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                // Have to adjust by more than exp so we will have a compact result
771                // TODO Verify this again, pretty sure it's right but I can't figure out
772                // why the -1 is there
773                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    // The basic idea here is to project both numbers to a u128 like in multiplication,
883    // but this time the lhs goes in the upper 64 bits and the rhs goes in the lower. This
884    // way we preserve as much info as possible
885    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        // lsig had a magnitude of min_exp + max_exp, this tracks how many orders of
910        // magnitude were "lost" with this division
911        let adj = (min_exp + max_exp) - mag;
912
913        if adj as u64 <= res_exp {
914            // We would shift by max_exp normally, but since we lost adj orders of
915            // magnitude we have to shift by max_exp - adj
916            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            // We would normally shift by max_exp, but we lost adj order of magnitude
924            // and took diff orders of magnitude from the exponent, so we shift by
925            // max_exp - adj + diff
926            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            // Already in expanded form
946            Self {
947                exp: self.exp.checked_add(rhs).unwrap(),
948                ..self
949            }
950        } else {
951            let mag = T::get_mag(self.sig);
952            // The number of orders of magnitude the significand can be increased
953            let adj = min_exp - mag;
954
955            if adj as u64 > rhs {
956                // The result can be made compact
957                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            // Precision specifier has special behavior on floats which is undesired
1032            // here. Want to force it to string and use the default behavior, e.g.
1033            // a max-width setting.
1034            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                // Anything after the decimal point won't make a significant difference in
1093                // the total
1094                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        // Check that adjustment is correct, especially around edge cases
1128        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, BASE) + BigNum::new(1, 10, BASE),
1222            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    // I won't test each individual base since the logic is the same, but I will test
1258    // binary and arbitrary
1259    #[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        // This is an example of how subtraction results in a loss of precision. I may
1267        // do a lossless_sub trait at some point that casts both sigs to u128 before
1268        // calculating
1269
1270        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        // 2^63 * 2^63 = 2^126
1294        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        // Since we apply 4 operations to b this is a good upper bound
1504        assert!(b.fuzzy_eq(c, 4));
1505        // Since we apply 20 operations to d this is a good upper bound
1506        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        // Result of adding a to a float that doesn't fit in u64 bounds
1521        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        // Error in result is less than 1/100000 = .001%
1530        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        // Error in result is less than 1/100000 = .001%
1545        assert!(max / (max - min) > BigNum::from(100000));
1546    }
1547}