Skip to main content

smallbigint/
lib.rs

1//! Two types, [`Uint`] and [`Int`], like `smallvec` for big integers.
2//! Anything that fits in 32 bits stays on the stack. Numbers that
3//! don't fit are stored in a `Box<num_bigint::BigUint>` / `Box<num_bigint::BigInt>`.
4//!
5//! On 64-bit architectures, by default we use `unsafe` to compress
6//! the types to 8 bytes, exploiting pointer alignment. This behavior
7//! is triggered by the `unsafe-opt` feature, which is enabled by default.
8//!
9//! ## Implemented traits
10//!
11//! Most important numeric traits have been implemented. Here are some that aren't yet;
12//! pull requests are welcome!
13//!
14//! - Bit operations
15//! - [`num_traits::Num`], [`num_traits::Signed`], [`num_traits::Unsigned`],
16//!   [`num_integer::Integer`], [`num_integer::Roots`], [`std::iter::Product`],
17//!   [`std::iter::Sum`], [`num_traits::pow::Pow`]
18//! - Other methods implemented directly on [`BigInt`], [`BigUint`]
19//! - Implement `num_bigint::{ToBigInt, ToBigUint}`
20//!
21//!
22//! There aren't super many unit tests currently, but the code is sufficiently
23//! simple that there is not much space where bugs could hide.
24
25// Some useless conversions make the code look more uniform.
26#![allow(clippy::useless_conversion)]
27
28use cfg_if::cfg_if;
29use either::{Either, Left, Right};
30use num_bigint::{BigInt, BigUint, ParseBigIntError, ToBigInt, ToBigUint};
31use num_traits::cast::{FromPrimitive, ToPrimitive};
32use num_traits::identities::{One, Zero};
33#[allow(unused_imports)]
34use num_traits::{
35    CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
36};
37use std::borrow::Cow::{self, Borrowed, Owned};
38use std::cmp::Ordering;
39use std::convert::{From, Into, TryFrom, TryInto};
40use std::fmt::Debug;
41use std::hash::{Hash, Hasher};
42use std::ops::{
43    Add, AddAssign, Deref, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
44};
45
46use std::str::FromStr;
47
48mod to_primitive_generic;
49// Don't want to commit to exporting this yet
50use to_primitive_generic::ToGeneric;
51
52#[allow(non_camel_case_types)]
53type uint = u32;
54#[allow(non_camel_case_types)]
55type int = i32;
56
57cfg_if! {
58    if #[cfg(any(not(feature = "unsafe-opt"), not(target_pointer_width = "64")))] {
59        // The real contents of the Uint and Int types. If we are using the
60        // unsafe optimization, then we use a different type that's equivalent
61        // to these Eithers.
62
63        #[derive(Clone)]
64        pub struct UintInner(Either<uint, Box<BigUint>>);
65        #[derive(Clone)]
66        pub struct IntInner(Either<int, Box<BigInt>>);
67
68        impl UintInner {
69            const fn make_left(i: u32) -> Self {
70                UintInner(Left(i))
71            }
72            fn make(v: Either<u32, Box<BigUint>>) -> Self {
73                UintInner(v)
74            }
75            fn get(self) -> Either<u32, Box<BigUint>> {
76                self.0
77            }
78            fn get_ref(&self) -> Either<u32, &BigUint> {
79                match self.0 {
80                    Left(v) => Left(v),
81                    Right(ref b) => Right(&*b),
82                }
83            }
84        }
85
86        impl IntInner {
87            const fn make_left(i: i32) -> Self {
88                IntInner(Left(i))
89            }
90            fn make(v: Either<i32, Box<BigInt>>) -> Self {
91                IntInner(v)
92            }
93            fn get(self) -> Either<i32, Box<BigInt>> {
94                self.0
95            }
96            fn get_ref(&self) -> Either<i32, &BigInt> {
97                match self.0 {
98                    Left(v) => Left(v),
99                    Right(ref b) => Right(&*b),
100                }
101            }
102        }
103    } else {
104        mod unsafeu32orbox;
105
106        type UintInner = unsafeu32orbox::UnsafeU32OrBox<BigUint>;
107        type IntInner = unsafeu32orbox::UnsafeI32OrBox<BigInt>;
108    }
109}
110
111#[derive(Clone)]
112pub struct Uint(UintInner);
113#[derive(Clone)]
114pub struct Int(IntInner);
115
116impl Uint {
117    const fn make_left(i: u32) -> Self {
118        Uint(UintInner::make_left(i))
119    }
120    fn mk(v: Either<u32, Box<BigUint>>) -> Self {
121        Uint(UintInner::make(v))
122    }
123    fn get(self) -> Either<u32, Box<BigUint>> {
124        self.0.get()
125    }
126    fn get_ref(&self) -> Either<u32, &BigUint> {
127        self.0.get_ref()
128    }
129
130    pub const fn zero() -> Self {
131        Self::small(0)
132    }
133    pub const fn small(x: uint) -> Self {
134        Uint::make_left(x)
135    }
136    pub fn big(v: BigUint) -> Self {
137        Uint::mk(Right(Box::new(v)))
138    }
139    /// A convenience function to get or convert to a [`BigUint`], without
140    /// having to copy any heap-allocated data if we are already a `&BigUint`.
141    ///
142    /// Given a variable `x : &Uint`, the following pattern may be useful to get
143    /// a `&BigUint` without unneeded allocation. If the [`Uint`] is small, then
144    /// we create a new temporary [`BigUint`] from it and the Rust compiler can
145    /// automatically figure out the lifetimes.
146    ///
147    /// ```rust
148    /// # use smallbigint::Uint; use num_bigint::BigUint;
149    /// # use std::ops::Deref;
150    /// # let x = Uint::small(42);
151    /// let x1 = x.cow_big();
152    /// let x2 : &BigUint = x1.deref();
153    /// ```
154    ///
155    /// We have to
156    ///
157    /// - Put `x1` in a variable, so that the compiler can figure out the lifetimes
158    /// - Put `x2` in a variable, otherwise the Rust compiler can't figure out its type.
159    pub fn cow_big(&self) -> Cow<BigUint> {
160        match self.get_ref() {
161            Left(x) => Owned(x.into()),
162            Right(ref b) => Borrowed(b),
163        }
164    }
165    /// If we're storing a [`BigUint`] but it would fit in a small uint instead, then
166    /// convert, and discard the heap-allocated memory.
167    pub fn normalize(self) -> Self {
168        match self.get() {
169            Left(x) => Self::mk(Left(x)),
170            Right(b) => {
171                if let Some(x) = b.to_u32() {
172                    Self::mk(Left(x)) // drop the memory
173                } else {
174                    Self::mk(Right(b))
175                }
176            }
177        }
178    }
179    /// Like `normalize`, but borrows instead.
180    #[allow(clippy::needless_return)]
181    pub fn normalize_ref(&self) -> Cow<Self> {
182        if let Right(ref b) = self.0.get_ref() {
183            if let Some(x) = b.to_u32() {
184                return Owned(Self::mk(Left(x)));
185            }
186        }
187        return Borrowed(self);
188    }
189    #[allow(dead_code)]
190    fn is_stored_as_big(&self) -> bool {
191        matches!(self.0.get_ref(), Right(_))
192    }
193}
194
195impl Int {
196    const fn make_left(i: i32) -> Self {
197        Int(IntInner::make_left(i))
198    }
199    fn mk(v: Either<i32, Box<BigInt>>) -> Self {
200        Int(IntInner::make(v))
201    }
202    fn get(self) -> Either<i32, Box<BigInt>> {
203        self.0.get()
204    }
205    fn get_ref(&self) -> Either<i32, &BigInt> {
206        self.0.get_ref()
207    }
208
209    pub const fn zero() -> Self {
210        Self::small(0)
211    }
212    pub const fn small(x: int) -> Self {
213        Int::make_left(x)
214    }
215    pub fn big(v: BigInt) -> Self {
216        Int::mk(Right(Box::new(v)))
217    }
218    /// A convenience function to get or convert to a [`BigInt`], without
219    /// having to copy any heap-allocated data if we are already a `&BigInt`.
220    ///
221    /// Given a variable `x : &Int`, the following pattern may be useful to get
222    /// a `&BigInt` without unneeded allocation. If the [`Int`] is small, then
223    /// we create a new temporary [`BigInt`] from it and the Rust compiler can
224    /// automatically figure out the lifetimes.
225    ///
226    /// ```rust
227    /// # use smallbigint::Int; use num_bigint::BigInt;
228    /// # use std::ops::Deref;
229    /// # let x = Int::small(42);
230    /// let x1 = x.cow_big();
231    /// let x2 : &BigInt = x1.deref();
232    /// ```
233    ///
234    /// We have to
235    ///
236    /// - Put `x1` in a variable, so that the compiler can figure out the lifetimes
237    /// - Put `x2` in a variable, otherwise the Rust compiler can't figure out its type.
238    pub fn cow_big(&self) -> Cow<BigInt> {
239        match self.get_ref() {
240            Left(x) => Owned(x.into()),
241            Right(ref b) => Borrowed(b),
242        }
243    }
244    /// If we're storing a [`BigInt`] but it would fit in a small int instead, then
245    /// convert, and discard the heap-allocated memory.
246    pub fn normalize(self) -> Self {
247        match self.get() {
248            Left(x) => Self::mk(Left(x)),
249            Right(b) => {
250                if let Some(x) = b.to_i32() {
251                    Self::mk(Left(x)) // drop the memory
252                } else {
253                    Self::mk(Right(b))
254                }
255            }
256        }
257    }
258    /// Like `normalize`, but borrows instead.
259    #[allow(clippy::needless_return)]
260    pub fn normalize_ref(&self) -> Cow<Self> {
261        if let Right(ref b) = self.0.get_ref() {
262            if let Some(x) = b.to_i32() {
263                return Owned(Self::mk(Left(x)));
264            }
265        }
266        return Borrowed(self);
267    }
268    #[allow(dead_code)]
269    fn is_stored_as_big(&self) -> bool {
270        matches!(self.0.get_ref(), Right(_))
271    }
272}
273
274// Convenience private trait to make the code easier to write
275
276trait SmallBig {
277    type Big;
278    type Small;
279
280    fn make_left(i: Self::Small) -> Self;
281    fn mk(v: Either<Self::Small, Box<Self::Big>>) -> Self;
282    fn get(self) -> Either<Self::Small, Box<Self::Big>>;
283    fn get_ref(&self) -> Either<Self::Small, &Self::Big>;
284    fn zero() -> Self;
285    fn small(x: Self::Small) -> Self;
286    fn big(v: Self::Big) -> Self;
287    fn into_big(self) -> Self::Big;
288}
289
290impl SmallBig for Uint {
291    type Big = BigUint;
292    type Small = u32;
293
294    fn make_left(i: Self::Small) -> Self {
295        Self::make_left(i)
296    }
297    fn mk(v: Either<Self::Small, Box<Self::Big>>) -> Self {
298        Self::mk(v)
299    }
300    fn get(self) -> Either<Self::Small, Box<Self::Big>> {
301        self.get()
302    }
303    fn get_ref(&self) -> Either<Self::Small, &Self::Big> {
304        self.get_ref()
305    }
306    fn zero() -> Self {
307        Self::zero()
308    }
309    fn small(x: Self::Small) -> Self {
310        Self::small(x)
311    }
312    fn big(v: Self::Big) -> Self {
313        Self::big(v)
314    }
315    fn into_big(self) -> Self::Big {
316        self.into()
317    }
318}
319impl SmallBig for Int {
320    type Big = BigInt;
321    type Small = i32;
322
323    fn make_left(i: Self::Small) -> Self {
324        Self::make_left(i)
325    }
326    fn mk(v: Either<Self::Small, Box<Self::Big>>) -> Self {
327        Self::mk(v)
328    }
329    fn get(self) -> Either<Self::Small, Box<Self::Big>> {
330        self.get()
331    }
332    fn get_ref(&self) -> Either<Self::Small, &Self::Big> {
333        self.get_ref()
334    }
335    fn zero() -> Self {
336        Self::zero()
337    }
338    fn small(x: Self::Small) -> Self {
339        Self::small(x)
340    }
341    fn big(v: Self::Big) -> Self {
342        Self::big(v)
343    }
344    fn into_big(self) -> Self::Big {
345        self.into()
346    }
347}
348// -- Basic stuff between the same signedness --
349
350impl Default for Uint {
351    fn default() -> Self {
352        Self::zero()
353    }
354}
355
356impl Default for Int {
357    fn default() -> Self {
358        Self::zero()
359    }
360}
361
362impl Zero for Uint {
363    fn zero() -> Self {
364        Self::small(0)
365    }
366    fn is_zero(&self) -> bool {
367        *self == Self::zero()
368    }
369}
370impl Zero for Int {
371    fn zero() -> Self {
372        Self::small(0)
373    }
374    fn is_zero(&self) -> bool {
375        *self == Self::zero()
376    }
377}
378
379impl One for Uint {
380    fn one() -> Self {
381        Self::small(1)
382    }
383    fn is_one(&self) -> bool {
384        *self == Self::one()
385    }
386}
387impl One for Int {
388    fn one() -> Self {
389        Self::small(1)
390    }
391    fn is_one(&self) -> bool {
392        *self == Self::one()
393    }
394}
395
396/// A utility extension function to make it easier to transform values in-place. Works
397/// well automatically for types with a cheap [`Default`].
398trait Transformable: Sized {
399    fn transform(&mut self, f: impl FnOnce(Self) -> Self);
400}
401
402impl<T: Default> Transformable for T {
403    fn transform(&mut self, f: impl FnOnce(Self) -> Self) {
404        let mut tmp = Self::default();
405        std::mem::swap(&mut tmp, self);
406        *self = f(tmp)
407    }
408}
409
410macro_rules! call_with_args {
411    ($macroname:tt, $baseargs:tt, [$($nextarg:tt),*]) => {
412        $(append_macro_call!{$macroname, $baseargs, $nextarg})*
413    };
414}
415
416macro_rules! append_macro_call {
417    ($macroname:tt, ($($baseargs:tt)*), $nextarg:tt) => {
418        $macroname!($($baseargs)* $nextarg)
419    };
420    ($macroname:tt, [$($baseargs:tt)*], $nextarg:tt) => {
421        $macroname![$($baseargs)* $nextarg]
422    };
423    ($macroname:tt, {$($baseargs:tt)*}, $nextarg:tt) => {
424        $macroname!{$($baseargs)* $nextarg}
425    };
426}
427
428macro_rules! impl_fmt_variants {
429    // Here we implement stuff like
430    //
431    //   - PartialEq<&i16> for Int
432    //   - PartialEq<i16> for &Int
433    //
434    // so that you don't have to call the * operator yourself as much. But we
435    // don't implement PartialEq<&i16> for &Int because the generic implementation
436    // already takes care of that.
437    //
438    // These functions are very simple (a dereference and a function call), so it
439    // seems reasonable to suggest that they should be inlined.
440    ($trait:path, $selftype:ty) => {
441        impl $trait for $selftype {
442            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
443                match self.0.get_ref() {
444                    Left(x) => <<$selftype as SmallBig>::Small as $trait>::fmt(&x, f),
445                    Right(b) => <<$selftype as SmallBig>::Big as $trait>::fmt(b, f),
446                }
447            }
448        }
449    };
450}
451
452call_with_args! {impl_fmt_variants, {std::fmt::Binary, }, [Uint, Int]}
453call_with_args! {impl_fmt_variants, {std::fmt::Debug, }, [Uint, Int]}
454call_with_args! {impl_fmt_variants, {std::fmt::Display, }, [Uint, Int]}
455call_with_args! {impl_fmt_variants, {std::fmt::LowerHex, }, [Uint, Int]}
456call_with_args! {impl_fmt_variants, {std::fmt::Octal, }, [Uint, Int]}
457call_with_args! {impl_fmt_variants, {std::fmt::UpperHex, }, [Uint, Int]}
458
459// Not yet implemented upstream:
460// call_with_args! {impl_fmt_variants, {std::fmt::LowerExp, }, [Uint, Int]}
461// call_with_args! {impl_fmt_variants, {std::fmt::UpperExp, }, [Uint, Int]}
462
463impl From<BigUint> for Uint {
464    fn from(v: BigUint) -> Self {
465        Uint::mk(Right(Box::new(v)))
466    }
467}
468impl From<Uint> for BigUint {
469    fn from(v: Uint) -> BigUint {
470        match v.0.get() {
471            Left(x) => x.into(),
472            Right(b) => *b,
473        }
474    }
475}
476
477impl From<BigInt> for Int {
478    fn from(v: BigInt) -> Self {
479        Int::mk(Right(Box::new(v)))
480    }
481}
482impl From<Int> for BigInt {
483    fn from(v: Int) -> BigInt {
484        match v.0.get() {
485            Left(x) => x.into(),
486            Right(b) => *b,
487        }
488    }
489}
490
491impl FromStr for Uint {
492    type Err = ParseBigIntError;
493    fn from_str(s: &str) -> Result<Self, ParseBigIntError> {
494        Ok(Uint::big(BigUint::from_str(s)?).normalize())
495    }
496}
497
498impl FromStr for Int {
499    type Err = ParseBigIntError;
500    fn from_str(s: &str) -> Result<Self, ParseBigIntError> {
501        Ok(Int::big(BigInt::from_str(s)?).normalize())
502    }
503}
504
505impl Hash for Uint {
506    fn hash<H: Hasher>(&self, state: &mut H) {
507        match self.normalize_ref().get_ref() {
508            Left(x) => x.hash(state),
509            Right(b) => b.hash(state),
510        }
511    }
512}
513
514impl Hash for Int {
515    fn hash<H: Hasher>(&self, state: &mut H) {
516        match self.normalize_ref().get_ref() {
517            Left(x) => x.hash(state),
518            Right(b) => b.hash(state),
519        }
520    }
521}
522
523impl Neg for Int {
524    type Output = Int;
525    fn neg(self) -> Int {
526        Int::big(BigInt::from(self).neg()).normalize()
527    }
528}
529
530impl Neg for &Int {
531    type Output = Int;
532    fn neg(self) -> Int {
533        let self1 = self.cow_big();
534        let self2: &BigInt = self1.deref();
535        Int::big(self2.neg()).normalize()
536    }
537}
538
539// -- Basic stuff between both same and different signedness --
540
541impl Ord for Uint {
542    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
543        if let (Left(x), Left(y)) = (self.get_ref(), other.get_ref()) {
544            x.cmp(&y)
545        } else {
546            let self1 = self.cow_big();
547            let self2: &BigUint = self1.deref();
548            let other1 = other.cow_big();
549            let other2: &BigUint = other1.deref();
550            self2.cmp(other2.deref())
551        }
552    }
553}
554
555impl PartialOrd<Uint> for Uint {
556    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
557        if let (Left(x), Left(y)) = (self.get_ref(), other.get_ref()) {
558            x.partial_cmp(&y)
559        } else {
560            let self1 = self.cow_big();
561            let self2: &BigUint = self1.deref();
562            let other1 = other.cow_big();
563            let other2: &BigUint = other1.deref();
564            self2.partial_cmp(other2.deref())
565        }
566    }
567}
568
569impl Ord for Int {
570    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
571        if let (Left(x), Left(y)) = (self.get_ref(), other.get_ref()) {
572            x.cmp(&y)
573        } else {
574            let self1 = self.cow_big();
575            let self2: &BigInt = self1.deref();
576            let other1 = other.cow_big();
577            let other2: &BigInt = other1.deref();
578            self2.cmp(other2.deref())
579        }
580    }
581}
582
583impl PartialOrd<Int> for Int {
584    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
585        if let (Left(x), Left(y)) = (self.get_ref(), other.get_ref()) {
586            x.partial_cmp(&y)
587        } else {
588            let self1 = self.cow_big();
589            let self2: &BigInt = self1.deref();
590            let other1 = other.cow_big();
591            let other2: &BigInt = other1.deref();
592            self2.partial_cmp(other2.deref())
593        }
594    }
595}
596
597impl PartialOrd<Uint> for Int {
598    fn partial_cmp(&self, other: &Uint) -> Option<std::cmp::Ordering> {
599        self.partial_cmp(&Int::from(other.clone()))
600    }
601}
602
603impl PartialOrd<Int> for Uint {
604    fn partial_cmp(&self, other: &Int) -> Option<std::cmp::Ordering> {
605        Int::from(self.clone()).partial_cmp(other)
606    }
607}
608
609impl PartialEq<Uint> for Uint {
610    fn eq(&self, other: &Self) -> bool {
611        if let (Left(x), Left(y)) = (self.get_ref(), other.get_ref()) {
612            x == y
613        } else {
614            let self1 = self.cow_big();
615            let self2: &BigUint = self1.deref();
616            let other1 = other.cow_big();
617            let other2: &BigUint = other1.deref();
618            self2.eq(other2.deref())
619        }
620    }
621}
622impl PartialEq<Int> for Uint {
623    /// Cannot use the small-int optimization, and copies the [`Uint`] into a [`BigInt`].
624    fn eq(&self, other: &Int) -> bool {
625        let self_bigint = BigInt::from(BigUint::from(self.clone()));
626        let other1 = other.cow_big();
627        let other2: &BigInt = other1.deref();
628        self_bigint.eq(other2.deref())
629    }
630}
631impl Eq for Uint {}
632
633impl PartialEq<Int> for Int {
634    fn eq(&self, other: &Self) -> bool {
635        if let (Left(x), Left(y)) = (self.get_ref(), other.get_ref()) {
636            x == y
637        } else {
638            let self1 = self.cow_big();
639            let self2: &BigInt = self1.deref();
640            let other1 = other.cow_big();
641            let other2: &BigInt = other1.deref();
642            self2.eq(other2.deref())
643        }
644    }
645}
646impl PartialEq<Uint> for Int {
647    /// Cannot use the small-int optimization, and copies the [`Uint`] into a [`BigInt`].
648    fn eq(&self, other: &Uint) -> bool {
649        let other_bigint = BigInt::from(BigUint::from(other.clone()));
650        let self1 = self.cow_big();
651        let self2: &BigInt = self1.deref();
652        other_bigint.eq(self2.deref())
653    }
654}
655impl Eq for Int {}
656
657macro_rules! impl_ref_variants {
658    // Here we implement stuff like
659    //
660    //   - PartialEq<&i16> for Int
661    //   - PartialEq<i16> for &Int
662    //
663    // so that you don't have to call the * operator yourself as much. But we
664    // don't implement PartialEq<&i16> for &Int because the generic implementation
665    // already takes care of that.
666    //
667    // These functions are very simple (a dereference and a function call), so it
668    // seems reasonable to suggest that they should be inlined.
669    ($trait:tt, $method:tt, $selftype:ty, $othtype:ty, $resulttype:ty) => {
670        impl $trait<&$othtype> for $selftype {
671            #[inline]
672            fn $method(&self, other: &&$othtype) -> $resulttype {
673                self.$method(*other)
674            }
675        }
676        impl $trait<$othtype> for &$selftype {
677            #[inline]
678            fn $method(&self, other: &$othtype) -> $resulttype {
679                (*self).$method(other)
680            }
681        }
682    };
683}
684
685impl_ref_variants! { PartialEq, eq, Uint, Uint, bool }
686impl_ref_variants! { PartialEq, eq, Int, Uint, bool }
687impl_ref_variants! { PartialEq, eq, Uint, Int, bool }
688impl_ref_variants! { PartialEq, eq, Int, Int, bool }
689impl_ref_variants! { PartialOrd, partial_cmp, Uint, Uint, Option<Ordering> }
690impl_ref_variants! { PartialOrd, partial_cmp, Int, Uint, Option<Ordering> }
691impl_ref_variants! { PartialOrd, partial_cmp, Uint, Int, Option<Ordering> }
692impl_ref_variants! { PartialOrd, partial_cmp, Int, Int, Option<Ordering> }
693
694// -- Basic stuff between different signedness --
695
696impl Uint {
697    /// Convert owned to [`Int`].
698    pub fn into_int(self) -> Int {
699        match self.get() {
700            Left(x) => {
701                if let Ok(x1) = x.try_into() {
702                    Int::mk(Left(x1))
703                } else {
704                    Int::mk(Right(Box::new(x.into())))
705                }
706            }
707            Right(b) => Int::mk(Right(Box::new((*b).into()))),
708        }
709    }
710    /// Convert reference to [`Int`].
711    pub fn to_int(&self) -> Int {
712        match self.0.get_ref() {
713            Left(x) => {
714                if let Ok(x1) = x.try_into() {
715                    Int::mk(Left(x1))
716                } else {
717                    Int::mk(Right(Box::new(x.into())))
718                }
719            }
720            Right(b) => Int::mk(Right(Box::new(
721                b.to_bigint()
722                    .expect("ToBigInt on BigUint should always succeed"),
723            ))),
724        }
725    }
726}
727/// An alias for `.into_uint()`.
728impl From<Uint> for Int {
729    fn from(v: Uint) -> Self {
730        v.into_int()
731    }
732}
733
734impl Int {
735    /// Convert owned to [`Uint`] if nonnegative, otherwise None.
736    ///
737    /// As there is not yet such a method on [`BigUint`], for now this clones
738    /// the underlying storage.
739    /// <https://github.com/rust-num/num-bigint/issues/120>
740    pub fn into_uint(self) -> Option<Uint> {
741        match self.get() {
742            Left(x) => {
743                if let Ok(x1) = x.try_into() {
744                    Some(Uint::mk(Left(x1)))
745                } else {
746                    Some(Uint::mk(Right(Box::new(x.to_biguint()?))))
747                }
748            }
749            Right(x) => Some(Uint::mk(Right(Box::new(x.to_biguint()?)))),
750        }
751    }
752    /// Convert reference to [`Uint`] if nonnegative, otherwise None.
753    pub fn to_uint(&self) -> Option<Uint> {
754        match self.0.get_ref() {
755            Left(x) => {
756                if let Ok(x1) = x.try_into() {
757                    Some(Uint::mk(Left(x1)))
758                } else {
759                    Some(Uint::mk(Right(Box::new(x.to_biguint()?))))
760                }
761            }
762            Right(x) => Some(Uint::mk(Right(Box::new(x.to_biguint()?)))),
763        }
764    }
765}
766#[non_exhaustive]
767#[derive(Debug)]
768pub struct IntIsNegativeError();
769
770/// An alias for `.into_int()`.
771impl TryFrom<Int> for Uint {
772    type Error = IntIsNegativeError;
773    /// Fails on negative numbers.
774    fn try_from(v: Int) -> Result<Self, Self::Error> {
775        v.into_uint().ok_or(IntIsNegativeError())
776    }
777}
778
779// -- Conversions from/to primitives --
780
781impl From<u128> for Uint {
782    fn from(x: u128) -> Self {
783        if let Ok(x) = x.try_into() {
784            Uint::mk(Left(x))
785        } else {
786            Uint::mk(Right(Box::new(x.into())))
787        }
788    }
789}
790impl TryFrom<i128> for Uint {
791    type Error = IntIsNegativeError;
792    fn try_from(x: i128) -> Result<Self, Self::Error> {
793        if let Ok(x) = x.try_into() {
794            Ok(Uint::mk(Left(x)))
795        } else {
796            Ok(Uint::mk(Right(Box::new(
797                BigInt::from(x).to_biguint().ok_or(IntIsNegativeError())?,
798            ))))
799        }
800    }
801}
802impl From<u64> for Uint {
803    fn from(x: u64) -> Self {
804        if let Ok(x) = x.try_into() {
805            Uint::mk(Left(x))
806        } else {
807            Uint::mk(Right(Box::new(x.into())))
808        }
809    }
810}
811impl TryFrom<i64> for Uint {
812    type Error = IntIsNegativeError;
813    fn try_from(x: i64) -> Result<Self, Self::Error> {
814        if let Ok(x) = x.try_into() {
815            Ok(Uint::mk(Left(x)))
816        } else {
817            Ok(Uint::mk(Right(Box::new(
818                BigInt::from(x).to_biguint().ok_or(IntIsNegativeError())?,
819            ))))
820        }
821    }
822}
823impl From<u32> for Uint {
824    fn from(x: u32) -> Self {
825        if let Ok(x) = x.try_into() {
826            Uint::mk(Left(x))
827        } else {
828            Uint::mk(Right(Box::new(x.into())))
829        }
830    }
831}
832impl TryFrom<i32> for Uint {
833    type Error = IntIsNegativeError;
834    fn try_from(x: i32) -> Result<Self, Self::Error> {
835        if let Ok(x) = x.try_into() {
836            Ok(Uint::mk(Left(x)))
837        } else {
838            Ok(Uint::mk(Right(Box::new(
839                BigInt::from(x).to_biguint().ok_or(IntIsNegativeError())?,
840            ))))
841        }
842    }
843}
844
845impl From<u16> for Uint {
846    fn from(x: u16) -> Self {
847        if let Ok(x) = x.try_into() {
848            Uint::mk(Left(x))
849        } else {
850            Uint::mk(Right(Box::new(x.into())))
851        }
852    }
853}
854impl TryFrom<i16> for Uint {
855    type Error = IntIsNegativeError;
856    fn try_from(x: i16) -> Result<Self, Self::Error> {
857        if let Ok(x) = x.try_into() {
858            Ok(Uint::mk(Left(x)))
859        } else {
860            Ok(Uint::mk(Right(Box::new(
861                BigInt::from(x).to_biguint().ok_or(IntIsNegativeError())?,
862            ))))
863        }
864    }
865}
866
867impl From<u8> for Uint {
868    fn from(x: u8) -> Self {
869        if let Ok(x) = x.try_into() {
870            Uint::mk(Left(x))
871        } else {
872            Uint::mk(Right(Box::new(x.into())))
873        }
874    }
875}
876impl TryFrom<i8> for Uint {
877    type Error = IntIsNegativeError;
878    fn try_from(x: i8) -> Result<Self, Self::Error> {
879        if let Ok(x) = x.try_into() {
880            Ok(Uint::mk(Left(x)))
881        } else {
882            Ok(Uint::mk(Right(Box::new(
883                BigInt::from(x).to_biguint().ok_or(IntIsNegativeError())?,
884            ))))
885        }
886    }
887}
888
889impl From<usize> for Uint {
890    fn from(x: usize) -> Self {
891        if let Ok(x) = x.try_into() {
892            Uint::mk(Left(x))
893        } else {
894            Uint::mk(Right(Box::new(x.into())))
895        }
896    }
897}
898impl TryFrom<isize> for Uint {
899    type Error = IntIsNegativeError;
900    fn try_from(x: isize) -> Result<Self, Self::Error> {
901        if let Ok(x) = x.try_into() {
902            Ok(Uint::mk(Left(x)))
903        } else {
904            Ok(Uint::mk(Right(Box::new(
905                BigInt::from(x).to_biguint().ok_or(IntIsNegativeError())?,
906            ))))
907        }
908    }
909}
910
911impl FromPrimitive for Uint {
912    fn from_u128(x: u128) -> Option<Self> {
913        if let Ok(x) = x.try_into() {
914            Some(Uint::mk(Left(x)))
915        } else {
916            Some(Uint::mk(Right(Box::new(x.into()))))
917        }
918    }
919    fn from_i128(x: i128) -> Option<Self> {
920        if let Ok(x) = x.try_into() {
921            Some(Uint::mk(Left(x)))
922        } else {
923            Some(Uint::mk(Right(Box::new(BigInt::from(x).to_biguint()?))))
924        }
925    }
926    fn from_u64(x: u64) -> Option<Self> {
927        if let Ok(x) = x.try_into() {
928            Some(Uint::mk(Left(x)))
929        } else {
930            Some(Uint::mk(Right(Box::new(x.into()))))
931        }
932    }
933    fn from_i64(x: i64) -> Option<Self> {
934        if let Ok(x) = x.try_into() {
935            Some(Uint::mk(Left(x)))
936        } else {
937            Some(Uint::mk(Right(Box::new(BigInt::from(x).to_biguint()?))))
938        }
939    }
940    fn from_u32(x: u32) -> Option<Self> {
941        if let Ok(x) = x.try_into() {
942            Some(Uint::mk(Left(x)))
943        } else {
944            Some(Uint::mk(Right(Box::new(x.into()))))
945        }
946    }
947    fn from_i32(x: i32) -> Option<Self> {
948        if let Ok(x) = x.try_into() {
949            Some(Uint::mk(Left(x)))
950        } else {
951            Some(Uint::mk(Right(Box::new(BigInt::from(x).to_biguint()?))))
952        }
953    }
954}
955
956impl From<u128> for Int {
957    fn from(x: u128) -> Self {
958        if let Ok(x) = x.try_into() {
959            Int::mk(Left(x))
960        } else {
961            Int::mk(Right(Box::new(x.into())))
962        }
963    }
964}
965impl From<i128> for Int {
966    fn from(x: i128) -> Self {
967        if let Ok(x) = x.try_into() {
968            Int::mk(Left(x))
969        } else {
970            Int::mk(Right(Box::new(x.into())))
971        }
972    }
973}
974impl From<u64> for Int {
975    fn from(x: u64) -> Self {
976        if let Ok(x) = x.try_into() {
977            Int::mk(Left(x))
978        } else {
979            Int::mk(Right(Box::new(x.into())))
980        }
981    }
982}
983impl From<i64> for Int {
984    fn from(x: i64) -> Self {
985        if let Ok(x) = x.try_into() {
986            Int::mk(Left(x))
987        } else {
988            Int::mk(Right(Box::new(x.into())))
989        }
990    }
991}
992impl From<u32> for Int {
993    fn from(x: u32) -> Self {
994        if let Ok(x) = x.try_into() {
995            Int::mk(Left(x))
996        } else {
997            Int::mk(Right(Box::new(x.into())))
998        }
999    }
1000}
1001impl From<i32> for Int {
1002    fn from(x: i32) -> Self {
1003        if let Ok(x) = x.try_into() {
1004            Int::mk(Left(x))
1005        } else {
1006            Int::mk(Right(Box::new(x.into())))
1007        }
1008    }
1009}
1010
1011impl From<u16> for Int {
1012    fn from(x: u16) -> Self {
1013        if let Ok(x) = x.try_into() {
1014            Int::mk(Left(x))
1015        } else {
1016            Int::mk(Right(Box::new(x.into())))
1017        }
1018    }
1019}
1020impl From<i16> for Int {
1021    fn from(x: i16) -> Self {
1022        if let Ok(x) = x.try_into() {
1023            Int::mk(Left(x))
1024        } else {
1025            Int::mk(Right(Box::new(x.into())))
1026        }
1027    }
1028}
1029
1030impl From<u8> for Int {
1031    fn from(x: u8) -> Self {
1032        if let Ok(x) = x.try_into() {
1033            Int::mk(Left(x))
1034        } else {
1035            Int::mk(Right(Box::new(x.into())))
1036        }
1037    }
1038}
1039impl From<i8> for Int {
1040    fn from(x: i8) -> Self {
1041        if let Ok(x) = x.try_into() {
1042            Int::mk(Left(x))
1043        } else {
1044            Int::mk(Right(Box::new(x.into())))
1045        }
1046    }
1047}
1048
1049impl From<usize> for Int {
1050    fn from(x: usize) -> Self {
1051        if let Ok(x) = x.try_into() {
1052            Int::mk(Left(x))
1053        } else {
1054            Int::mk(Right(Box::new(x.into())))
1055        }
1056    }
1057}
1058impl From<isize> for Int {
1059    fn from(x: isize) -> Self {
1060        if let Ok(x) = x.try_into() {
1061            Int::mk(Left(x))
1062        } else {
1063            Int::mk(Right(Box::new(x.into())))
1064        }
1065    }
1066}
1067
1068impl FromPrimitive for Int {
1069    fn from_u128(x: u128) -> Option<Self> {
1070        if let Ok(x) = x.try_into() {
1071            Some(Int::mk(Left(x)))
1072        } else {
1073            Some(Int::mk(Right(Box::new(x.into()))))
1074        }
1075    }
1076    fn from_i128(x: i128) -> Option<Self> {
1077        if let Ok(x) = x.try_into() {
1078            Some(Int::mk(Left(x)))
1079        } else {
1080            Some(Int::mk(Right(Box::new(x.into()))))
1081        }
1082    }
1083    fn from_u64(x: u64) -> Option<Self> {
1084        if let Ok(x) = x.try_into() {
1085            Some(Int::mk(Left(x)))
1086        } else {
1087            Some(Int::mk(Right(Box::new(x.into()))))
1088        }
1089    }
1090    fn from_i64(x: i64) -> Option<Self> {
1091        if let Ok(x) = x.try_into() {
1092            Some(Int::mk(Left(x)))
1093        } else {
1094            Some(Int::mk(Right(Box::new(x.into()))))
1095        }
1096    }
1097    fn from_u32(x: u32) -> Option<Self> {
1098        if let Ok(x) = x.try_into() {
1099            Some(Int::mk(Left(x)))
1100        } else {
1101            Some(Int::mk(Right(Box::new(x.into()))))
1102        }
1103    }
1104    fn from_i32(x: i32) -> Option<Self> {
1105        if let Ok(x) = x.try_into() {
1106            Some(Int::mk(Left(x)))
1107        } else {
1108            Some(Int::mk(Right(Box::new(x.into()))))
1109        }
1110    }
1111}
1112
1113impl ToPrimitive for Int {
1114    fn to_u128(&self) -> Option<u128> {
1115        match self.0.get_ref() {
1116            Left(x) => x.try_into().ok(),
1117            Right(b) => b.to_u128(),
1118        }
1119    }
1120    fn to_i128(&self) -> Option<i128> {
1121        match self.0.get_ref() {
1122            Left(x) => x.try_into().ok(),
1123            Right(b) => b.to_i128(),
1124        }
1125    }
1126    fn to_u64(&self) -> Option<u64> {
1127        match self.0.get_ref() {
1128            Left(x) => x.try_into().ok(),
1129            Right(b) => b.to_u64(),
1130        }
1131    }
1132    fn to_i64(&self) -> Option<i64> {
1133        match self.0.get_ref() {
1134            Left(x) => x.try_into().ok(),
1135            Right(b) => b.to_i64(),
1136        }
1137    }
1138    fn to_u32(&self) -> Option<u32> {
1139        match self.0.get_ref() {
1140            Left(x) => x.try_into().ok(),
1141            Right(b) => b.to_u32(),
1142        }
1143    }
1144    fn to_i32(&self) -> Option<i32> {
1145        match self.0.get_ref() {
1146            Left(x) => x.try_into().ok(),
1147            Right(b) => b.to_i32(),
1148        }
1149    }
1150}
1151
1152impl ToPrimitive for Uint {
1153    fn to_u128(&self) -> Option<u128> {
1154        match self.0.get_ref() {
1155            Left(x) => x.try_into().ok(),
1156            Right(b) => b.to_u128(),
1157        }
1158    }
1159    fn to_i128(&self) -> Option<i128> {
1160        match self.0.get_ref() {
1161            Left(x) => x.try_into().ok(),
1162            Right(b) => b.to_i128(),
1163        }
1164    }
1165    fn to_u64(&self) -> Option<u64> {
1166        match self.0.get_ref() {
1167            Left(x) => x.try_into().ok(),
1168            Right(b) => b.to_u64(),
1169        }
1170    }
1171    fn to_i64(&self) -> Option<i64> {
1172        match self.0.get_ref() {
1173            Left(x) => x.try_into().ok(),
1174            Right(b) => b.to_i64(),
1175        }
1176    }
1177    fn to_u32(&self) -> Option<u32> {
1178        match self.0.get_ref() {
1179            Left(x) => x.try_into().ok(),
1180            Right(b) => b.to_u32(),
1181        }
1182    }
1183    fn to_i32(&self) -> Option<i32> {
1184        match self.0.get_ref() {
1185            Left(x) => x.try_into().ok(),
1186            Right(b) => b.to_i32(),
1187        }
1188    }
1189}
1190
1191macro_rules! call_with_all_signed_base_types {
1192    ($macroname:ident, $($token:tt)*) => {
1193        $macroname!{$($token)* i8}
1194        $macroname!{$($token)* i16}
1195        $macroname!{$($token)* i32}
1196        $macroname!{$($token)* i64}
1197        $macroname!{$($token)* i128}
1198        $macroname!{$($token)* isize}
1199    };
1200}
1201
1202macro_rules! call_with_all_unsigned_base_types {
1203    ($macroname:ident, $($token:tt)*) => {
1204        $macroname!{$($token)* u8}
1205        $macroname!{$($token)* u16}
1206        $macroname!{$($token)* u32}
1207        $macroname!{$($token)* u64}
1208        $macroname!{$($token)* u128}
1209        $macroname!{$($token)* usize}
1210    };
1211}
1212
1213// The first macro name represents a macro to define e.g. Add; the second represents
1214// a macro to define e.g. AddAssign.
1215//
1216// There are a number of ways to use this macro; the mode is indicated by the last argument,
1217// which is merely a textual mode indicator. This macro can help with implementing four kinds
1218// of things:
1219//
1220// (1a) impl Add<Int> for Int (and various &-combinations)
1221// (1b) impl AddAssign<Int> for Int (and AddAssign<&Int>)
1222// (1a) impl Add<i16> for Int (and various &-combinations, and other base types)
1223// (1b) impl AddAssign<i16> for Int (and AddAssign<&i16>, and other base types)
1224//
1225// I advise you to look at the invocations of this macro, and perhaps also at the macroexpansions.
1226//
1227// Example parameter values:
1228//
1229//   macroname_value = trait_add_value
1230//   macroname_mut   = trait_add_mut
1231//   type     = Int
1232//   basetype = int (type alias for i32)
1233//   bigtype  = BigInt
1234macro_rules! call_with_cow_permutations {
1235    ($macroname_value:ident, $macroname_mut:ident, $type:tt, $basetype:tt, $bigtype:tt, both signed and unsigned) => {
1236        call_with_cow_permutations!{$macroname_value, $macroname_mut, $type, $basetype, $bigtype, self case}
1237        call_with_all_signed_base_types!{
1238            call_with_cow_permutations,
1239            $macroname_value, $macroname_mut, $type, $basetype, $bigtype, base type
1240        }
1241        call_with_all_unsigned_base_types!{
1242            call_with_cow_permutations,
1243            $macroname_value, $macroname_mut, $type, $basetype, $bigtype, base type
1244        }
1245    };
1246    ($macroname_value:ident, $macroname_mut:ident, $type:tt, $basetype:tt, $bigtype:tt, only unsigned) => {
1247        call_with_cow_permutations!{$macroname_value, $macroname_mut, $type, $basetype, $bigtype, self case}
1248        call_with_all_unsigned_base_types!{
1249            call_with_cow_permutations,
1250            $macroname_value, $macroname_mut, $type, $basetype, $bigtype, base type
1251        }
1252    };
1253    ($macroname_value:ident, $macroname_mut:ident, $type:tt, $basetype:tt, $bigtype:tt) => {
1254        call_with_cow_permutations!{$macroname_value, $macroname_mut, $type, $basetype, $bigtype, self case}
1255    };
1256
1257    // Calls the implementing macros for a number of cases. For example for Add/AddAssign, this would
1258    // call macros to implement, in order:
1259    //
1260    // - Add<Int> for Int
1261    // - Add<&Int> for Int
1262    // - Add<Int> for &Int
1263    // - Add<&Int> for &Int
1264    //
1265    // In all cases, the implementing macro would have two cases, one for when self and other are
1266    // small, one for when one of them is big. The latter case takes a &BigInt, which is provided
1267    // using .cow_big(). The code fragment argument is inserted to make an expression for &BigInt
1268    // possible.
1269    //
1270    // Also, calls macros to implement AddAssign<Int> and AddAssign<&Int>.
1271    ($macroname_value:ident, $macroname_mut:ident, $type:tt, $basetype:tt, $bigtype:tt, self case) => {
1272        $macroname_value!{
1273            $type, $basetype, $bigtype, self, v, $type, $type, v.get_ref(), {},
1274            $bigtype::from(self), $bigtype::from(v)
1275        }
1276        $macroname_value!{
1277            $type, $basetype, $bigtype, self, v, $type, &$type, v.get_ref(), {
1278                let v1 = v.cow_big()
1279                let v2: &$bigtype = v1.deref()
1280            }, $bigtype::from(self), v2
1281        }
1282        $macroname_value!{
1283            $type, $basetype, $bigtype, self, v, &$type, $type, v.get_ref(), {
1284                let self1 = self.cow_big()
1285                let self2: &$bigtype = self1.deref()
1286            }, self2, $bigtype::from(v)
1287        }
1288        $macroname_value!{
1289            $type, $basetype, $bigtype, self, v, &$type, &$type, v.get_ref(), {
1290                let self1 = self.cow_big()
1291                let self2: &$bigtype = self1.deref()
1292                let v1 = v.cow_big()
1293                let v2: &$bigtype = v1.deref()
1294            }, self2, v2
1295        }
1296        $macroname_mut!{$type, $type}
1297        $macroname_mut!{$type, &$type}
1298    };
1299
1300    // Calls the implementing macros for the base types (e.g. Add<i128> for Int), with expressions
1301    // that first call $bigtype::from(..) on the i128 to convert to &Int.
1302    ($macroname_value:ident, $macroname_mut:ident, $type:tt, $basetype:ty, $bigtype:tt, base type $baseothertype:ty) => {
1303        $macroname_value!{
1304            $type, $basetype, $bigtype, self, v, $type, $baseothertype, Either::<$baseothertype, $type>::Left(v), {},
1305            $bigtype::from(self), v
1306        }
1307        $macroname_value!{
1308            $type, $basetype, $bigtype, self, v, $type, &$baseothertype, Either::<$baseothertype, $type>::Left(*v), {},
1309            $bigtype::from(self), *v
1310        }
1311        $macroname_value!{
1312            $type, $basetype, $bigtype, self, v, &$type, $baseothertype, Either::<$baseothertype, $type>::Left(v), {
1313                let self1 = self.cow_big()
1314                let self2: &$bigtype = self1.deref()
1315            }, self2, v
1316        }
1317        $macroname_value!{
1318            $type, $basetype, $bigtype, self, v, &$type, &$baseothertype, Either::<$baseothertype, $type>::Left(*v), {
1319                let self1 = self.cow_big()
1320                let self2: &$bigtype = self1.deref()
1321            }, self2, *v
1322        }
1323        $macroname_mut!{$type, $baseothertype}
1324        $macroname_mut!{$type, &$baseothertype}
1325    };
1326}
1327
1328macro_rules! trait_add_value {
1329    ($type:tt, $basetype:ty, $bigtype:ty, $selfvar:tt, $othvar:ident,
1330        $selftype:ty, $othtype:ty, $otheitherref:expr,
1331        {$($makecows:stmt)*}, $bigexpr1:expr, $bigexpr2:expr) => {
1332            impl Add<$othtype> for $selftype {
1333                type Output = $type;
1334                fn add($selfvar, $othvar: $othtype) -> $type {
1335                    if let (Left(x), Left(y)) = ($selfvar.get_ref(), $otheitherref) {
1336                        if let Ok(y_base) = <$basetype>::try_from(y) {
1337                            if let Some(z) = <$basetype>::checked_add(x, y_base) {
1338                                return $type::small(z);
1339                            }
1340                        }
1341                    }
1342                    $($makecows)*
1343                    $type::big($bigexpr1.add($bigexpr2))
1344                }
1345            }
1346    };
1347}
1348
1349macro_rules! trait_add_mut {
1350    ($type:tt, $othtype:ty) => {
1351        impl AddAssign<$othtype> for $type {
1352            fn add_assign(&mut self, other: $othtype) {
1353                self.transform(|sf| sf.add(other));
1354            }
1355        }
1356    };
1357}
1358
1359call_with_cow_permutations! {trait_add_value, trait_add_mut, Int, int, BigInt, both signed and unsigned}
1360call_with_cow_permutations! {trait_add_value, trait_add_mut, Uint, uint, BigUint, only unsigned}
1361
1362macro_rules! trait_div_value {
1363    ($type:tt, $basetype:ty, $bigtype:ty, $selfvar:tt, $othvar:ident,
1364        $selftype:ty, $othtype:ty, $otheitherref:expr,
1365        {$($makecows:stmt)*}, $bigexpr1:expr, $bigexpr2:expr) => {
1366        impl Div<$othtype> for $selftype {
1367            type Output = $type;
1368            fn div($selfvar, $othvar: $othtype) -> $type {
1369                if let (Left(x), Left(y)) = ($selfvar.get_ref(), $otheitherref) {
1370                    if let Ok(y_base) = <$basetype>::try_from(y) {
1371                        if let Some(z) = <$basetype>::checked_div(x, y_base) {
1372                            return $type::small(z);
1373                        }
1374                    }
1375                }
1376                $($makecows)*
1377                $type::big($bigexpr1.div($bigexpr2))
1378            }
1379        }
1380    };
1381}
1382
1383macro_rules! trait_div_mut {
1384    ($type:tt, $othtype:ty) => {
1385        impl DivAssign<$othtype> for $type {
1386            fn div_assign(&mut self, other: $othtype) {
1387                self.transform(|sf| sf.div(other));
1388            }
1389        }
1390    };
1391}
1392
1393call_with_cow_permutations! {trait_div_value, trait_div_mut, Int, int, BigInt, both signed and unsigned}
1394call_with_cow_permutations! {trait_div_value, trait_div_mut, Uint, uint, BigUint, only unsigned}
1395
1396macro_rules! trait_mul_value {
1397    ($type:tt, $basetype:ty, $bigtype:ty, $selfvar:tt, $othvar:ident,
1398        $selftype:ty, $othtype:ty, $otheitherref:expr,
1399        {$($makecows:stmt)*}, $bigexpr1:expr, $bigexpr2:expr) => {
1400        impl Mul<$othtype> for $selftype {
1401            type Output = $type;
1402            fn mul($selfvar, $othvar: $othtype) -> $type {
1403                if let (Left(x), Left(y)) = ($selfvar.get_ref(), $otheitherref) {
1404                    if let Ok(y_base) = <$basetype>::try_from(y) {
1405                        if let Some(z) = <$basetype>::checked_mul(x, y_base) {
1406                            return $type::small(z);
1407                        }
1408                    }
1409                }
1410                $($makecows)*
1411                $type::big($bigexpr1.mul($bigexpr2))
1412            }
1413        }
1414    };
1415}
1416
1417macro_rules! trait_mul_mut {
1418    ($type:tt, $othtype:ty) => {
1419        impl MulAssign<$othtype> for $type {
1420            fn mul_assign(&mut self, other: $othtype) {
1421                self.transform(|sf| sf.mul(other));
1422            }
1423        }
1424    };
1425}
1426
1427call_with_cow_permutations! {trait_mul_value, trait_mul_mut, Int, int, BigInt, both signed and unsigned}
1428call_with_cow_permutations! {trait_mul_value, trait_mul_mut, Uint, uint, BigUint, only unsigned}
1429
1430macro_rules! trait_rem_value {
1431    ($type:tt, $basetype:ty, $bigtype:ty, $selfvar:tt, $othvar:ident,
1432        $selftype:ty, $othtype:ty, $otheitherref:expr,
1433        {$($makecows:stmt)*}, $bigexpr1:expr, $bigexpr2:expr) => {
1434        impl Rem<$othtype> for $selftype {
1435            type Output = $type;
1436            fn rem($selfvar, $othvar: $othtype) -> $type {
1437                if let (Left(x), Left(y)) = ($selfvar.get_ref(), $otheitherref) {
1438                    if let Ok(y_base) = <$basetype>::try_from(y) {
1439                        if let Some(z) = <$basetype>::checked_rem(x, y_base) {
1440                            return $type::small(z);
1441                        }
1442                    }
1443                }
1444                $($makecows)*
1445                $type::big($bigexpr1.rem($bigexpr2))
1446            }
1447        }
1448    };
1449}
1450
1451macro_rules! trait_rem_mut {
1452    ($type:tt, $othtype:ty) => {
1453        impl RemAssign<$othtype> for $type {
1454            fn rem_assign(&mut self, other: $othtype) {
1455                self.transform(|sf| sf.rem(other));
1456            }
1457        }
1458    };
1459}
1460
1461call_with_cow_permutations! {trait_rem_value, trait_rem_mut, Int, int, BigInt, both signed and unsigned}
1462call_with_cow_permutations! {trait_rem_value, trait_rem_mut, Uint, uint, BigUint, only unsigned}
1463
1464macro_rules! trait_sub_value {
1465    ($type:tt, $basetype:ty, $bigtype:ty, $selfvar:tt, $othvar:ident,
1466        $selftype:ty, $othtype:ty, $otheitherref:expr,
1467        {$($makecows:stmt)*}, $bigexpr1:expr, $bigexpr2:expr) => {
1468        impl Sub<$othtype> for $selftype {
1469            type Output = $type;
1470            fn sub($selfvar, $othvar: $othtype) -> $type {
1471                if let (Left(x), Left(y)) = ($selfvar.get_ref(), $otheitherref) {
1472                    if let Ok(y_base) = <$basetype>::try_from(y) {
1473                        if let Some(z) = <$basetype>::checked_sub(x, y_base) {
1474                            return $type::small(z);
1475                        }
1476                    }
1477                }
1478                $($makecows)*
1479                $type::big($bigexpr1.sub($bigexpr2))
1480            }
1481        }
1482    };
1483}
1484
1485macro_rules! trait_sub_mut {
1486    ($type:tt, $othtype:ty) => {
1487        impl SubAssign<$othtype> for $type {
1488            fn sub_assign(&mut self, other: $othtype) {
1489                self.transform(|sf| sf.sub(other));
1490            }
1491        }
1492    };
1493}
1494
1495call_with_cow_permutations! {trait_sub_value, trait_sub_mut, Int, int, BigInt, both signed and unsigned}
1496call_with_cow_permutations! {trait_sub_value, trait_sub_mut, Uint, uint, BigUint, only unsigned}
1497
1498// The checked traits are always a function from (&Self, &Self) to Option<Self>.
1499// We implement them by first trying them on the base type; if that works, falling
1500// back to the big type. This could be improved: for certain traits we could give
1501// an optimized implementation.
1502
1503macro_rules! checked_trait {
1504    ($trait:tt, $method:tt, $type:tt) => {
1505        impl $trait for $type {
1506            fn $method(&self, other: &Self) -> Option<Self> {
1507                // Try to do it on the base type.
1508                if let (Left(x), Left(y)) = (self.get_ref(), other.get_ref()) {
1509                    if let Some(res) = x.$method(y) {
1510                        return Some($type::small(res));
1511                    }
1512                }
1513                // If it fails, try again on the big type, otherwise really fail.
1514                let x_big = self.cow_big();
1515                let y_big = other.cow_big();
1516                if let Some(z_big) = x_big.$method(y_big.deref()) {
1517                    return Some($type::big(z_big));
1518                } else {
1519                    return None;
1520                }
1521            }
1522        }
1523    };
1524}
1525
1526call_with_args! {checked_trait, {CheckedAdd, checked_add, }, [Uint, Int]}
1527call_with_args! {checked_trait, {CheckedDiv, checked_div, }, [Uint, Int]}
1528call_with_args! {checked_trait, {CheckedMul, checked_mul, }, [Uint, Int]}
1529// These don't yet exist for num_bigint.
1530//   call_with_args! {checked_trait, {CheckedNeg, checked_neg, }, [Uint, Int]}
1531//   call_with_args! {checked_trait, {CheckedRem, checked_rem, }, [Uint, Int]}
1532//   call_with_args! {checked_trait, {CheckedShl, checked_shl, }, [Uint, Int]}
1533//   call_with_args! {checked_trait, {CheckedShr, checked_shr, }, [Uint, Int]}
1534call_with_args! {checked_trait, {CheckedSub, checked_sub, }, [Uint, Int]}
1535
1536macro_rules! trait_partialeq {
1537    (base, $type:tt, $basetype:ty) => {
1538        // One way
1539        impl PartialEq<$basetype> for $type {
1540            fn eq(&self, other: &$basetype) -> bool {
1541                ToGeneric::<$basetype>::to_generic(self).map_or(false, |x| x.eq(other))
1542            }
1543        }
1544
1545        // The other way
1546        impl PartialEq<$type> for $basetype {
1547            fn eq(&self, other: &$type) -> bool {
1548                ToGeneric::<$basetype>::to_generic(other).map_or(false, |x| x.eq(self))
1549            }
1550        }
1551
1552        // These are just lazy variants so you don't have to do * yourself when
1553        // one is a reference and one isn't.
1554        impl_ref_variants! {PartialEq, eq, $type, $basetype, bool}
1555        impl_ref_variants! {PartialEq, eq, $basetype, $type, bool}
1556    };
1557}
1558
1559call_with_all_unsigned_base_types!(trait_partialeq, base, Uint,);
1560call_with_all_unsigned_base_types!(trait_partialeq, base, Int,);
1561call_with_all_signed_base_types!(trait_partialeq, base, Uint,);
1562call_with_all_signed_base_types!(trait_partialeq, base, Int,);
1563
1564macro_rules! trait_partialord_straight {
1565    ($type:tt $basetype:tt) => {
1566        // One way
1567        impl PartialOrd<$basetype> for $type {
1568            fn partial_cmp(&self, other: &$basetype) -> Option<Ordering> {
1569                // First, try to do it on the base type
1570                match ToGeneric::<$basetype>::to_generic(self) {
1571                    Some(x) => x.partial_cmp(other),
1572                    None => {
1573                        // If that fails, then do it on our type.
1574                        match $type::try_from(other.clone()) {
1575                            Ok(other2) => self.partial_cmp(&other2),
1576                            Err(_) => {
1577                                // Size is never an issue for TryFrom. This can only
1578                                // happen because we're trying to convert a negative
1579                                // number to unsigned.
1580                                Some(Ordering::Greater)
1581                            }
1582                        }
1583                    }
1584                }
1585            }
1586        }
1587
1588        // The other way
1589        impl PartialOrd<$type> for $basetype {
1590            fn partial_cmp(&self, other: &$type) -> Option<Ordering> {
1591                other.partial_cmp(self).map(|ord| ord.reverse())
1592            }
1593        }
1594
1595        impl_ref_variants! {PartialOrd, partial_cmp, $type, $basetype, Option<Ordering>}
1596        impl_ref_variants! {PartialOrd, partial_cmp, $basetype, $type, Option<Ordering>}
1597    };
1598}
1599
1600call_with_all_unsigned_base_types!(trait_partialord_straight, Uint);
1601call_with_all_unsigned_base_types!(trait_partialord_straight, Int);
1602call_with_all_signed_base_types!(trait_partialord_straight, Uint);
1603call_with_all_signed_base_types!(trait_partialord_straight, Int);
1604
1605#[cfg(test)]
1606mod test {
1607    #![allow(clippy::redundant_clone, clippy::cognitive_complexity, clippy::op_ref)]
1608
1609    use super::*;
1610    #[test]
1611    fn test_unsigned() {
1612        println!("Size of Uint: {}", std::mem::size_of::<Uint>());
1613
1614        let eleven = Uint::small(11);
1615        assert_eq!(eleven, 11u8);
1616        assert_eq!(&eleven, 11u8);
1617        assert_eq!(eleven, &11u8);
1618        assert_ne!(eleven, 10u8);
1619        assert_eq!(11u8, eleven);
1620        assert_ne!(10u8, eleven);
1621        assert_eq!(eleven, 11i8);
1622        assert_ne!(eleven, 10i8);
1623        assert_eq!(11i8, eleven);
1624        assert_ne!(10i8, eleven);
1625        assert!(eleven.get_ref().is_left());
1626        assert!(eleven.clone().get_ref().is_left());
1627        assert!(eleven.clone().normalize().get_ref().is_left());
1628
1629        let eleven_pow11 = &eleven
1630            * &eleven
1631            * &eleven
1632            * &eleven
1633            * &eleven
1634            * &eleven
1635            * &eleven
1636            * &eleven
1637            * &eleven
1638            * &eleven
1639            * &eleven;
1640        assert!(eleven_pow11.get_ref().is_right());
1641        assert!(eleven_pow11.clone().get_ref().is_right());
1642        assert!(eleven_pow11.clone().normalize().get_ref().is_right());
1643        assert!(eleven < eleven_pow11);
1644        assert!(&eleven < eleven_pow11);
1645        assert!(eleven < &eleven_pow11);
1646        assert!(11u8 < eleven_pow11);
1647        assert!(11i8 < eleven_pow11);
1648        let eleven_big = Uint::big(BigUint::from(11u8));
1649        let eleven_big_norm = eleven_big.clone().normalize();
1650        let eleven_big_norm_ref = eleven_big.normalize_ref();
1651        assert_eq!(eleven, eleven_big);
1652        assert_eq!(&eleven, eleven_big);
1653        assert_eq!(eleven, &eleven_big);
1654        assert_eq!(eleven, eleven_big_norm);
1655        assert_eq!(eleven, *eleven_big_norm_ref);
1656        assert_eq!(eleven_big.is_stored_as_big(), true);
1657        assert_eq!(eleven_big_norm.is_stored_as_big(), false);
1658        assert_eq!(eleven_big_norm_ref.is_stored_as_big(), false);
1659        let eleven_pow11_norm = eleven_pow11.clone().normalize();
1660        let eleven_pow11_norm_ref = eleven_pow11.normalize_ref();
1661        assert_eq!(eleven_pow11, eleven_pow11_norm);
1662        assert_eq!(eleven_pow11, *eleven_pow11_norm_ref);
1663        assert_eq!(
1664            &eleven_pow11 + &eleven_pow11,
1665            eleven_pow11.checked_add(&eleven_pow11).unwrap()
1666        );
1667
1668        for x in &[
1669            &eleven,
1670            &eleven_pow11,
1671            &eleven_big,
1672            &eleven_big_norm,
1673            &eleven_big_norm_ref,
1674        ] {
1675            let x_big: BigUint = (*x).clone().into_big();
1676
1677            assert_eq!(format!("{}", x), format!("{}", x_big),);
1678            assert_eq!(format!("{:3.2}", x), format!("{:3.2}", x_big),);
1679            assert_eq!(format!("{:b}", x), format!("{:b}", x_big),);
1680            assert_eq!(format!("{:3.2b}", x), format!("{:3.2b}", x_big),);
1681            assert_eq!(format!("{:x}", x), format!("{:x}", x_big),);
1682            assert_eq!(format!("{:3.2x}", x), format!("{:3.2x}", x_big),);
1683            assert_eq!(format!("{:o}", x), format!("{:o}", x_big),);
1684            assert_eq!(format!("{:3.2o}", x), format!("{:3.2o}", x_big),);
1685        }
1686    }
1687    #[test]
1688    fn test_signed() {
1689        println!("Size of Int: {}", std::mem::size_of::<Int>());
1690
1691        let eleven = Int::small(11);
1692        assert_eq!(eleven, 11u8);
1693        assert_eq!(&eleven, 11u8);
1694        assert_eq!(eleven, &11u8);
1695        assert_ne!(eleven, 10u8);
1696        assert_eq!(11u8, eleven);
1697        assert_ne!(10u8, eleven);
1698        assert_eq!(eleven, 11i8);
1699        assert_ne!(eleven, 10i8);
1700        assert_eq!(11i8, eleven);
1701        assert_ne!(10i8, eleven);
1702        assert!(eleven.get_ref().is_left());
1703        assert!(eleven.clone().get_ref().is_left());
1704        assert!(eleven.clone().normalize().get_ref().is_left());
1705
1706        let eleven_pow11 = &eleven
1707            * &eleven
1708            * &eleven
1709            * &eleven
1710            * &eleven
1711            * &eleven
1712            * &eleven
1713            * &eleven
1714            * &eleven
1715            * &eleven
1716            * &eleven;
1717        assert!(eleven_pow11.get_ref().is_right());
1718        assert!(eleven_pow11.clone().get_ref().is_right());
1719        assert!(eleven_pow11.clone().normalize().get_ref().is_right());
1720        assert!(eleven < eleven_pow11);
1721        assert!(&eleven < eleven_pow11);
1722        assert!(eleven < &eleven_pow11);
1723        assert!(-eleven.clone() < eleven_pow11);
1724        assert!(-eleven_pow11.clone() < eleven);
1725        assert!(-eleven_pow11.clone() < -eleven.clone());
1726        assert!(11u8 < eleven_pow11);
1727        assert!(11i8 < eleven_pow11);
1728        assert!(-11i8 < eleven_pow11);
1729        assert!(-eleven_pow11.clone() < 11i8);
1730        assert!(-eleven_pow11.clone() < -11i8);
1731        let eleven_big = Int::big(BigInt::from(11i8));
1732        let eleven_big_norm = eleven_big.clone().normalize();
1733        let eleven_big_norm_ref = eleven_big.normalize_ref();
1734        assert_eq!(eleven, eleven_big);
1735        assert_eq!(&eleven, eleven_big);
1736        assert_eq!(eleven, &eleven_big);
1737        assert_eq!(eleven, eleven_big_norm);
1738        assert_eq!(eleven, *eleven_big_norm_ref);
1739        assert_eq!(eleven_big.is_stored_as_big(), true);
1740        assert_eq!(eleven_big_norm.is_stored_as_big(), false);
1741        assert_eq!(eleven_big_norm_ref.is_stored_as_big(), false);
1742        let eleven_pow11_norm = eleven_pow11.clone().normalize();
1743        let eleven_pow11_norm_ref = eleven_pow11.normalize_ref();
1744        assert_eq!(eleven_pow11, eleven_pow11_norm);
1745        assert_eq!(eleven_pow11, *eleven_pow11_norm_ref);
1746        assert_eq!(
1747            &eleven_pow11 + &eleven_pow11,
1748            eleven_pow11.checked_add(&eleven_pow11).unwrap()
1749        );
1750
1751        for x in &[
1752            &eleven,
1753            &eleven_pow11,
1754            &eleven_big,
1755            &eleven_big_norm,
1756            &eleven_big_norm_ref,
1757        ] {
1758            let x_big: BigInt = (*x).clone().into_big();
1759
1760            assert_eq!(format!("{}", x), format!("{}", x_big),);
1761            assert_eq!(format!("{:3.2}", x), format!("{:3.2}", x_big),);
1762            assert_eq!(format!("{:b}", x), format!("{:b}", x_big),);
1763            assert_eq!(format!("{:3.2b}", x), format!("{:3.2b}", x_big),);
1764            assert_eq!(format!("{:x}", x), format!("{:x}", x_big),);
1765            assert_eq!(format!("{:3.2x}", x), format!("{:3.2x}", x_big),);
1766            assert_eq!(format!("{:o}", x), format!("{:o}", x_big),);
1767            assert_eq!(format!("{:3.2o}", x), format!("{:3.2o}", x_big),);
1768        }
1769    }
1770}