use core::mem::{transmute, transmute_copy};
use crate::{BigUInt, digit::Digit};
use super::IsBigInt;
impl<T: Digit, const LEN: usize> IsBigInt for BigUInt<T, LEN> {
type Dig = T;
const DIG_LEN: usize = LEN;
const ONE: Self = {
let mut one = [T::ZERO; LEN];
one[0] = T::ONE;
BigUInt(one)
};
const ZERO: Self = BigUInt([T::ZERO; LEN]);
fn bit_nlz(&self) -> usize {
let mut cnt = 0;
let mut i = self.0.len() - 1;
loop {
let nlz = self.0[i].nlz();
cnt += nlz;
if nlz != Self::DIG_BIT_LEN { break }
if i == 0 { break }
i -= 1;
}
cnt
}
fn bit_len(&self) -> usize {
Self::BIT_LEN - self.bit_nlz()
}
fn seg_len(&self) -> usize {
(self.bit_len() + Self::DIG_BIT_LEN_MSK) >> Self::DIG_BIT_LEN_SHT
}
fn bit(&self, idx: usize) -> bool {
self.0[idx >> Self::DIG_BIT_LEN_SHT].bit(idx & Self::DIG_BIT_LEN_MSK)
}
fn is_negative(&self) -> bool {
self.bit(Self::BIT_LEN - 1)
}
fn is_odd(&self) -> bool {
self.0[0].is_odd()
}
fn is_zero(&self) -> bool {
let mut i = 0;
let mut flag = T::ZERO;
while i < self.0.len() {
flag = self.0[i] | flag;
i += 1;
}
flag.is_zero()
}
fn as_slice(&self) -> &[Self::Dig; Self::DIG_LEN] {
unsafe { transmute(&self.0) }
}
fn from_slice(arr: &[Self::Dig; Self::DIG_LEN]) -> Self {
Self(
unsafe { transmute_copy(arr) }
)
}
fn to_array(self) -> [Self::Dig; Self::DIG_LEN] {
unsafe { core::intrinsics::transmute_unchecked(self) }
}
fn from_array(arr: [Self::Dig; Self::DIG_LEN]) -> Self {
Self(
unsafe { core::intrinsics::transmute_unchecked(arr) }
)
}
fn as_bytes(&self) -> &[u8]
where
[(); Self::BYTE_LEN]:
{
unsafe {
core::slice::from_raw_parts(
self.as_ptr() as *const u8,
Self::BYTE_LEN
)
}
}
fn set_bit(mut self, idx: usize, bit: bool) -> Self {
let dig_idx = idx >> Self::DIG_BIT_LEN_SHT;
self.0[dig_idx] = self.0[dig_idx].set_bit(idx & Self::DIG_BIT_LEN_MSK, bit);
self
}
}