1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! Properties of a big number

use crate::digit::Digit;

pub mod impls;

pub trait IsBigInt {
    /// segment type, typically primitive integer type like u64, u32 
    type Dig: Digit + PartialEq;

    /// segment length in byte
    const DIG_BYTE_LEN: usize = Self::Dig::BYTE_LEN;
    /// number of segments
    const DIG_LEN: usize;

    /// segment length in bit
    const DIG_BIT_LEN: usize = Self::DIG_BYTE_LEN << 3;

    /// segment bit length mask, for example, if segment is u8 type, its bit length is 8, mask is 0b111 = (1 << 3) - 1
    const DIG_BIT_LEN_MSK: usize = Self::DIG_BIT_LEN - 1;
    /// segment bit length shift amount. uf segment is u8, this value is 3 since 1 << 3 = 8
    const DIG_BIT_LEN_SHT: usize = Self::DIG_BIT_LEN.trailing_zeros() as usize;
    /// segment byte length mask, u8 segment has 1 byte length, so mask is 0
    const DIG_BYTE_LEN_MSK: usize = Self::DIG_BYTE_LEN - 1;
    /// segment byte length mask, u8 segment has 1 byte length, so mask is 0
    const DIG_BYTE_LEN_SHT: usize = Self::DIG_BYTE_LEN.trailing_zeros() as usize;

    
    /// big integer length in byte
    const BYTE_LEN: usize = Self::DIG_LEN * Self::DIG_BYTE_LEN;
    /// big integer length in bit
    const BIT_LEN: usize = Self::BYTE_LEN << 3;

    const ONE: Self;
    const ZERO: Self;

    /// number of leading zeros in bit
    fn bit_nlz(&self) -> usize;
    /// big uint length in segment, excluding leading zeros
    fn seg_len(&self) -> usize;
    /// big uint length in bit, excluding leading zeros
    fn bit_len(&self) -> usize;
    /// get the idx-th bit of big integer
    fn bit(&self, idx: usize) -> bool;

    /// check if this biguint is negative, i.e. the MSB is 0
    fn is_negative(&self) -> bool;
    /// check if self is zero
    fn is_zero(&self) -> bool;
    /// check is self is odd
    fn is_odd(&self) -> bool;

    /// get a reference of slice of digs for this bigint
    fn as_slice(&self) -> &[Self::Dig; Self::DIG_LEN];
    fn from_slice(arr: &[Self::Dig; Self::DIG_LEN]) -> Self;

    fn to_array(self) -> [Self::Dig; Self::DIG_LEN];
    fn from_array(arr: [Self::Dig; Self::DIG_LEN]) -> Self;

    fn as_bytes(&self) -> &[u8]
    where
        [(); Self::BYTE_LEN]:
    ;

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

    #[cfg(feature = "rand")]
    fn rand(rng: &mut impl rand_core::CryptoRngCore) -> Self 
    where
        [(); Self::DIG_LEN]: ,
        Self: Sized
    {
        let mut out = [Self::Dig::ZERO; Self::DIG_LEN];
        out.iter_mut().for_each(|x| *x = Self::Dig::rand(rng));
        Self::from_array(out)
    }
}