use crate::MachineWord;
use const_num_traits::{Ct, Nct, Personality};
use core::marker::PhantomData;
mod arith;
mod bits;
mod bitwise;
mod bytes;
#[cfg(feature = "cios")]
mod cios;
mod cmp;
mod div_rem;
mod from_prim;
mod has_personality;
mod identities;
mod parity;
mod shift;
#[cfg(any(feature = "nightly", feature = "use-unsafe"))]
mod to_bytes;
#[cfg(feature = "zeroize")]
mod zeroize_impl;
pub struct HeaplessBigInt<T, const CAP: usize, P: Personality = Nct>
where
T: MachineWord,
{
pub(crate) limbs: [T; CAP],
pub(crate) len: u16,
pub(crate) _p: PhantomData<P>,
}
pub(crate) trait AssertCapFits {
const CHECK: ();
}
impl<T: MachineWord, const CAP: usize, P: Personality> AssertCapFits for HeaplessBigInt<T, CAP, P> {
const CHECK: () = assert!(
CAP <= u16::MAX as usize,
"HeaplessBigInt: CAP exceeds u16::MAX; len type cannot represent this capacity"
);
}
impl<T: MachineWord, const CAP: usize, P: Personality> HeaplessBigInt<T, CAP, P> {
#[inline]
pub fn new_zero_with_len(len: u16) -> Self {
let () = <Self as AssertCapFits>::CHECK;
assert!(
(len as usize) <= CAP,
"HeaplessBigInt::new_zero_with_len: len {} > CAP {}",
len,
CAP,
);
Self {
limbs: [zero::<T>(); CAP],
len,
_p: PhantomData,
}
}
#[inline]
pub fn zero_full_cap() -> Self {
Self::new_zero_with_len(CAP as u16)
}
#[inline]
pub fn from_limbs(limbs: [T; CAP], len: u16) -> Self {
let () = <Self as AssertCapFits>::CHECK;
assert!((len as usize) <= CAP);
let mut i = len as usize;
while i < CAP {
assert!(
is_zero(&limbs[i]),
"HeaplessBigInt::from_limbs: zero-tail invariant violated at index {}",
i
);
i += 1;
}
Self {
limbs,
len,
_p: PhantomData,
}
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> HeaplessBigInt<T, CAP, P> {
#[inline]
pub const fn len(&self) -> u16 {
self.len
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub const fn capacity(&self) -> usize {
CAP
}
#[inline]
#[must_use]
pub fn widened(&self, new_len: u16) -> Self {
assert!(
new_len >= self.len && new_len as usize <= CAP,
"widened: new_len {new_len} must be in [len {}, CAP {CAP}]",
self.len
);
let mut out = *self;
out.len = new_len;
out
}
#[inline]
pub fn limbs(&self) -> &[T] {
&self.limbs[..self.len as usize]
}
#[inline]
pub fn all_limbs(&self) -> &[T; CAP] {
&self.limbs
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> Clone for HeaplessBigInt<T, CAP, P> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T: MachineWord, const CAP: usize, P: Personality> Copy for HeaplessBigInt<T, CAP, P> {}
impl<T: MachineWord + core::fmt::Debug, const CAP: usize> core::fmt::Debug
for HeaplessBigInt<T, CAP, Nct>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"HeaplessBigInt<{}, {}, _>{{ limbs: {:?}, len: {} }}",
core::any::type_name::<T>(),
CAP,
&self.limbs[..self.len as usize],
self.len,
)
}
}
impl<T: MachineWord, const CAP: usize> core::fmt::Debug for HeaplessBigInt<T, CAP, Ct> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("HeaplessBigInt<…>")
}
}
#[inline]
pub(crate) fn zero<T: MachineWord>() -> T {
<T as const_num_traits::ConstZero>::ZERO
}
#[inline]
pub(crate) fn is_zero<T: MachineWord>(v: &T) -> bool {
<T as const_num_traits::Zero>::is_zero(v)
}