use crate::repr::{Repr, TypedRepr, TypedReprRef};
#[derive(Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct UBig(pub(crate) Repr);
impl UBig {
#[rustversion::attr(since(1.64), const)]
#[inline]
pub(crate) fn repr(&self) -> TypedReprRef<'_> {
self.0.as_typed()
}
#[inline]
pub(crate) fn into_repr(self) -> TypedRepr {
self.0.into_typed()
}
pub const ZERO: Self = Self(Repr::zero());
pub const ONE: Self = Self(Repr::one());
#[inline]
pub fn as_words(&self) -> &[crate::Word] {
let (sign, words) = self.0.as_sign_slice();
debug_assert!(matches!(sign, crate::Sign::Positive));
words
}
#[inline]
pub const fn from_word(word: crate::Word) -> Self {
Self(Repr::from_word(word))
}
#[inline]
pub const fn from_dword(dword: crate::DoubleWord) -> Self {
Self(Repr::from_dword(dword))
}
#[inline]
pub fn from_words(words: &[crate::Word]) -> Self {
Self(Repr::from_buffer(words.into()))
}
#[doc(hidden)]
#[inline]
pub const unsafe fn from_static_words(words: &'static [crate::Word]) -> Self {
Self(Repr::from_static_words(words))
}
#[inline]
pub const fn is_zero(&self) -> bool {
self.0.is_zero()
}
#[inline]
pub const fn is_one(&self) -> bool {
self.0.is_one()
}
}
impl Clone for UBig {
#[inline]
fn clone(&self) -> UBig {
UBig(self.0.clone())
}
#[inline]
fn clone_from(&mut self, source: &UBig) {
self.0.clone_from(&source.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{buffer::Buffer, DoubleWord, Word};
impl UBig {
#[inline]
fn capacity(&self) -> usize {
self.0.capacity()
}
}
fn gen_ubig(num_words: u16) -> UBig {
let mut buf = Buffer::allocate(num_words.into());
for i in 0..num_words {
buf.push(i.into());
}
UBig(Repr::from_buffer(buf))
}
#[test]
fn test_buffer_to_ubig() {
let buf = Buffer::allocate(5);
let num = UBig(Repr::from_buffer(buf));
assert_eq!(num, UBig::ZERO);
let mut buf = Buffer::allocate(5);
buf.push(7);
let num = UBig(Repr::from_buffer(buf));
assert_eq!(num, UBig::from(7u8));
let mut buf = Buffer::allocate(100);
buf.push(7);
buf.push(0);
buf.push(0);
let num = UBig(Repr::from_buffer(buf));
assert_eq!(num, UBig::from(7u8));
let mut buf = Buffer::allocate(5);
buf.push(1);
buf.push(2);
buf.push(3);
buf.push(4);
let num = UBig(Repr::from_buffer(buf));
assert_eq!(num.capacity(), 7);
let mut buf = Buffer::allocate(100);
buf.push(1);
buf.push(2);
buf.push(3);
buf.push(4);
let num = UBig(Repr::from_buffer(buf));
assert_eq!(num.capacity(), 6);
}
#[test]
fn test_clone() {
let a = UBig::from(5u8);
assert_eq!(a.clone(), a);
let a = gen_ubig(10);
let b = a.clone();
assert_eq!(a, b);
assert_eq!(a.capacity(), b.capacity());
}
#[test]
fn test_clone_from() {
let num: UBig = gen_ubig(10);
let mut a = UBig::from(3u8);
a.clone_from(&num);
assert_eq!(a, num);
let b = UBig::from(7u8);
a.clone_from(&b);
assert_eq!(a, b);
a.clone_from(&b);
assert_eq!(a, b);
let mut a = gen_ubig(9);
let prev_cap = a.capacity();
a.clone_from(&num);
assert_eq!(a.capacity(), prev_cap);
assert_ne!(a.capacity(), num.capacity());
let mut a = gen_ubig(3);
let prev_cap = a.capacity();
a.clone_from(&num);
assert_ne!(a.capacity(), prev_cap);
assert_eq!(a.capacity(), num.capacity());
let mut a = gen_ubig(100);
let prev_cap = a.capacity();
a.clone_from(&num);
assert_ne!(a.capacity(), prev_cap);
assert_eq!(a.capacity(), num.capacity());
}
#[test]
fn test_const_generation() {
const ZERO: UBig = UBig::from_word(0);
const ONE_SINGLE: UBig = UBig::from_word(1);
const ONE_DOUBLE: UBig = UBig::from_dword(1);
const DMAX: UBig = UBig::from_dword(DoubleWord::MAX);
const CDATA: [Word; 3] = [Word::MAX, Word::MAX, Word::MAX];
static CONST_TMAX: UBig = unsafe { UBig::from_static_words(&CDATA) };
static DATA: [Word; 3] = [Word::MAX, Word::MAX, Word::MAX];
static STATIC_TMAX: UBig = unsafe { UBig::from_static_words(&DATA) };
assert_eq!(ZERO, UBig::ZERO);
assert_eq!(ONE_SINGLE, UBig::ONE);
assert_eq!(ONE_DOUBLE, UBig::ONE);
assert_eq!(DMAX.capacity(), 2);
assert_eq!(CONST_TMAX.capacity(), 3);
assert_eq!(STATIC_TMAX.capacity(), 3);
}
}