reweb3-num 0.2.4

Arbitrary precision, fixed-size signed and unsigned integer types for ethereum, this a fork of bnum crate.
Documentation
macro_rules! bint_as {
    ($BInt: ident, $Digit: ident; $($int: ty), *) => {
        $(
            impl_const! {
                impl<const N: usize> const CastFrom<$BInt<N>> for $int {
                    #[inline]
                    fn cast_from(from: $BInt<N>) -> Self {
                        if from.is_negative() {
                            let digits = from.bits.digits;
                            let mut out = !0;
                            let mut i = 0;
                            while i << digit::$Digit::BIT_SHIFT < <$int>::BITS as usize && i < N {
                                out &= !((!digits[i]) as $int << (i << digit::$Digit::BIT_SHIFT));
                                i += 1;
                            }
                            out
                        } else {
                            <$int>::cast_from(from.bits)
                        }
                    }
                }
            }
        )*
    };
}

macro_rules! as_bint {
    ($BInt: ident, $BUint: ident; $($ty: ty), *) => {
        $(impl_const! {
            impl<const N: usize> const CastFrom<$ty> for $BInt<N> {
                #[inline]
                fn cast_from(from: $ty) -> Self {
                    Self::from_bits($BUint::cast_from(from))
                }
            }
        })*
    }
}

macro_rules! bint_cast_from_float {
    ($f: ty, $BUint: ident <$N: ident>) => {
        #[inline]
        fn cast_from(from: $f) -> Self {
            if from.is_sign_negative() {
                let u = $BUint::<$N>::cast_from(-from);
                if u >= Self::MIN.to_bits() {
                    Self::MIN
                } else {
                    -Self::from_bits(u)
                }
            } else {
                let u = $BUint::<$N>::cast_from(from);
                let i = Self::from_bits(u);
                if i.is_negative() {
                    Self::MAX
                } else {
                    i
                }
            }
        }
    };
}

pub(crate) use bint_cast_from_float;

use crate::cast::CastFrom;
use crate::digit;
use crate::nightly::impl_const;

macro_rules! cast {
    ($BUint: ident, $BInt: ident, $Digit: ident) => {
        bint_as!($BInt, $Digit; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);

        impl<const N: usize> CastFrom<$BInt<N>> for f32 {
            #[inline]
            fn cast_from(from: $BInt<N>) -> Self {
                let f = f32::cast_from(from.unsigned_abs());
                if from.is_negative() {
                    -f
                } else {
                    f
                }
            }
        }

        impl<const N: usize> CastFrom<$BInt<N>> for f64 {
            #[inline]
            fn cast_from(from: $BInt<N>) -> Self {
                let f = f64::cast_from(from.unsigned_abs());
                if from.is_negative() {
                    -f
                } else {
                    f
                }
            }
        }

        as_bint!($BInt, $BUint; u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, bool, char);

        impl_const! {
            impl<const N: usize, const M: usize> const CastFrom<$BUint<M>> for $BInt<N> {
                #[inline]
                fn cast_from(from: $BUint<M>) -> Self {
                    Self::from_bits($BUint::cast_from(from))
                }
            }
        }

        impl_const! {
            impl<const N: usize, const M: usize> const CastFrom<$BInt<M>> for $BInt<N> {
                #[inline]
                fn cast_from(from: $BInt<M>) -> Self {
                    Self::from_bits($BUint::cast_from(from))
                }
            }
        }

        impl<const N: usize> CastFrom<f32> for $BInt<N> {
            crate::bint::cast::bint_cast_from_float!(f32, $BUint<N>);
        }

        impl<const N: usize> CastFrom<f64> for $BInt<N> {
            crate::bint::cast::bint_cast_from_float!(f64, $BUint<N>);
        }
    };
}

crate::macro_impl!(cast);

macro_rules! bint_as_different_digit_bigint {
    ($BUint: ident, $BInt: ident, $Digit: ident; $(($OtherBInt: ident, $OtherDigit: ident)), *) => {
        $(
            crate::nightly::const_impl! {
                impl<const N: usize, const M: usize> const crate::cast::CastFrom<$OtherBInt<M>> for $BUint<N> {
                    #[must_use = doc::must_use_op!()]
                    #[inline]
                    fn cast_from(from: $OtherBInt<M>) -> Self {
                        if !from.is_negative() || M * $OtherDigit::BITS as usize >= N * $Digit::BITS as usize { // $OtherBInt::BITS <= $Int::BITS
                            Self::cast_from(from.to_bits())
                        } else {
                            let mut out = Self::MAX;
                            if $Digit::BITS < $OtherDigit::BITS {
                                const DIVIDE_COUNT: usize = ($OtherDigit::BITS / $Digit::BITS) as usize;
                                let stop_index: usize = if <$OtherBInt<M>>::BITS > <$BUint<N>>::BITS {
                                    N
                                } else {
                                    M * DIVIDE_COUNT
                                };
                                let mut i = 0;
                                while i < stop_index {
                                    let wider_digit = from.bits.digits[i / DIVIDE_COUNT];
                                    let mini_shift = i % DIVIDE_COUNT;
                                    let digit = (wider_digit >> (mini_shift << digit::$Digit::BIT_SHIFT)) as $Digit;
                                    out.digits[i] = digit;
                                    i += 1;
                                }
                            } else {
                                const DIVIDE_COUNT: usize = ($Digit::BITS / $OtherDigit::BITS) as usize;
                                let stop_index: usize = if <$OtherBInt<M>>::BITS > <$BUint<N>>::BITS {
                                    N * DIVIDE_COUNT
                                } else {
                                    M
                                };
                                let mut current_digit: $Digit = $Digit::MAX;
                                let mut i = 0;
                                while i < stop_index {
                                    let mini_shift = i % DIVIDE_COUNT;
                                    current_digit &= !((!from.bits.digits[i] as $Digit) << (mini_shift << digit::$OtherDigit::BIT_SHIFT));
                                    if mini_shift == DIVIDE_COUNT - 1 || i == stop_index - 1 {
                                        out.digits[i / DIVIDE_COUNT] = current_digit;
                                        current_digit = $Digit::MAX;
                                    }
                                    i += 1;
                                }
                            }
                            out
                        }
                    }
                }
            }

            crate::nightly::const_impl! {
                impl<const N: usize, const M: usize> const crate::cast::CastFrom<$OtherBInt<M>> for $BInt<N> {
                    #[must_use = doc::must_use_op!()]
                    #[inline]
                    fn cast_from(from: $OtherBInt<M>) -> Self {
                        Self::from_bits($BUint::<N>::cast_from(from))
                    }
                }
            }
        )*
    };
}

pub(crate) use bint_as_different_digit_bigint;