cryptix-bigint 0.1.0

A bigint library for cryptix
Documentation
use core::{ops::{Add, Sub, Mul, Rem, Shl, Shr, BitOr, BitAnd, BitOrAssign}, fmt::Debug};
#[cfg(feature = "rand")]
use rand_core::CryptoRngCore;

pub trait Digit: 
    Add<Output = Self> + Sub<Output = Self> + 
    Mul<Output = Self> + Rem<Output = Self> + 
    Shl<usize, Output = Self> + Shr<usize, Output = Self> + 
    BitOr<Output = Self> + BitOrAssign + BitAnd<Output = Self> + 
    PartialEq + Ord + 
    Copy + Default + Debug
{
    const BYTE_LEN: usize;
    const ONE: Self;
    const ZERO: Self;

    /// number of leading zeros
    fn nlz(self) -> usize;
    fn bit(&self, idx: usize) -> bool;

    /// byte size
    fn size() -> usize;

    fn is_zero(self) -> bool;
    fn is_odd(self) -> bool;

    /// carrying add
    fn carry_add(self, rhs: Self, carry: bool) -> (Self, bool);
    /// overflowing add
    fn overflow_add(self, rhs: Self) -> (Self, bool);

    fn borrow_sub(self, rhs: Self, carry: bool) -> (Self, bool);
    fn overflow_sub(self, rhs: Self) -> (Self, bool);

    fn carry_mul(self, rhs: Self, carry: Self) -> (Self, Self);
    fn widen_mul(self, rhs: Self) -> (Self, Self);
    fn overflow_mul(self, rhs: Self) -> (Self, bool);

    fn from_bool(b: bool) -> Self;

    fn set_bit(self, idx: usize, b: bool) -> Self;

    #[cfg(feature = "rand")]
    fn rand(rng: &mut impl CryptoRngCore) -> Self;
}

impl Digit for u64 {
    const ONE: Self = 1;
    const ZERO: Self = 0;
    const BYTE_LEN: usize = core::mem::size_of::<u64>();

    fn nlz(self) -> usize {
        u64::leading_zeros(self) as usize
    }

    fn size() -> usize {
        core::mem::size_of::<u64>()
    }

    fn is_zero(self) -> bool {
        self == 0
    }

    fn is_odd(self) -> bool {
        self & 1 != 0
    }

    fn bit(&self, idx: usize) -> bool {
        self & (1 << idx) != 0
    }

    fn carry_add(self, rhs: Self, carry: bool) -> (Self, bool) {
        self.carrying_add(rhs, carry)
    }

    fn overflow_add(self, rhs: Self) -> (Self, bool) {
        self.overflowing_add(rhs)
    }

    fn borrow_sub(self, rhs: Self, carry: bool) -> (Self, bool) {
        self.borrowing_sub(rhs, carry)
    }

    fn overflow_sub(self, rhs: Self) -> (Self, bool) {
        self.overflowing_sub(rhs)
    }

    fn carry_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
        self.carrying_mul(rhs, carry)
    }

    fn widen_mul(self, rhs: Self) -> (Self, Self) {
        self.widening_mul(rhs)
    }

    fn overflow_mul(self, rhs: Self) -> (Self, bool) {
        self.overflowing_mul(rhs)
    }

    fn from_bool(b: bool) -> Self {
        b as u64
    }

    fn set_bit(self, idx: usize, b: bool) -> Self {
        let mask = 1 << idx;
        if b {
            self | mask
        } else {
            self & !mask
        }
    }

    #[cfg(feature = "rand")]
    fn rand(rng: &mut impl CryptoRngCore) -> Self {
        rng.next_u64()
    }
}

/// implement mul seg with carry trait for types
macro_rules! impl_digit {
    (@all $($t:ty),*) => {
        $(impl_digit!($t);)*
    };

    ($t:ty) => {
        impl Digit for $t {
            const ONE: Self = 1;
            const ZERO: Self = 0;
            const BYTE_LEN: usize = core::mem::size_of::<$t>();

            fn nlz(self) -> usize {
                <$t>::leading_zeros(self) as usize
            }

            fn size() -> usize {
                core::mem::size_of::<$t>()
            }

            fn is_zero(self) -> bool {
                self == 0
            }

            fn is_odd(self) -> bool {
                self & 1 != 0
            }

            fn bit(&self, idx: usize) -> bool {
                self & (1 << idx) != 0
            }

            fn carry_add(self, rhs: Self, carry: bool) -> (Self, bool) {
                <$t>::carrying_add(self, rhs, carry)
            }

            fn overflow_add(self, rhs: Self) -> (Self, bool) {
                <$t>::overflowing_add(self, rhs)
            }

            fn borrow_sub(self, rhs: Self, carry: bool) -> (Self, bool) {
                self.borrowing_sub(rhs, carry)
            }
        
            fn overflow_sub(self, rhs: Self) -> (Self, bool) {
                self.overflowing_sub(rhs)
            }
        
            fn carry_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
                self.carrying_mul(rhs, carry)
            }

            fn overflow_mul(self, rhs: Self) -> (Self, bool) {
                self.overflowing_mul(rhs)
            }

            fn from_bool(b: bool) -> Self {
                b as $t
            }

            fn widen_mul(self, rhs: Self) -> (Self, Self) {
                self.widening_mul(rhs)
            }

            fn set_bit(self, idx: usize, b: bool) -> Self {
                let mask = 1 << idx;
                if b {
                    self | mask
                } else {
                    self & !mask
                }
            }

            #[cfg(feature = "rand")]
            fn rand(rng: &mut impl CryptoRngCore) -> Self {
                rng.next_u64() as $t
            }
        }
    };
}

impl_digit!(@all u8, u16, u32);