libspecr/int/
mod.rs

1use crate::*;
2
3mod ops;
4mod func;
5mod to;
6mod step;
7
8pub use to::ToInt;
9
10/// The external Bigint Type, which we use under the hood.
11pub(crate) use num_bigint::BigInt;
12use num_traits::ToPrimitive;
13
14#[derive(Copy, Clone, Hash, GcCompat)]
15/// Garbage collected big integer that implements `Copy` and supports construction in `const` contexts.
16pub struct Int(IntInner);
17
18// IntInner only exists to hide the enum implementation details.
19#[derive(Copy, Clone, Debug, Hash, GcCompat)]
20enum IntInner {
21    Big(GcCow<BigInt>),
22    /// i128 is used to contain u64 and i64.
23    Small(i128),
24}
25
26impl<T: ToInt> From<T> for Int {
27    fn from(t: T) -> Int {
28        t.to_int()
29    }
30}
31
32impl Int {
33    /// Create an `Int` from a regular Rust integer.
34    ///
35    /// `const fn` cannot be generic but it turns out `u64` is all we need.
36    pub const fn from_u64(i: u64) -> Int {
37        // `as` conversion is guaranteed lossless
38        Int(IntInner::Small(i as i128))
39    }
40}
41
42impl Int {
43    /// The number 0
44    pub const ZERO: Int = Int::from_u64(0);
45    /// The number 1
46    pub const ONE: Int = Int::from_u64(1);
47
48    pub(crate) fn into_inner(self) -> BigInt {
49        match self.0 {
50            IntInner::Big(x) => x.extract(),
51            IntInner::Small(x) => x.into(),
52        }
53    }
54
55    pub(crate) fn wrap(big: BigInt) -> Self {
56        match big.to_i128() {
57            Some(x) => Self(IntInner::Small(x)),
58            None => Self(IntInner::Big(GcCow::new(big)))
59        }
60    }
61}