use super::{carry_mul, BigInt, FromNegErr};
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct UBigInt<const N: usize>(pub [u64; N]);
impl<const N: usize> core::fmt::Display for UBigInt<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::LowerHex::fmt(&self, f)
}
}
impl<const N: usize> core::fmt::LowerHex for UBigInt<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("0x")?;
for i in self.0.iter().rev() {
write!(f, "{:016x}", i)?
}
Ok(())
}
}
impl<const N: usize> core::fmt::UpperHex for UBigInt<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("0x")?;
for i in self.0.iter().rev() {
write!(f, "{:016X}", i)?
}
Ok(())
}
}
impl<const N: usize> core::fmt::Debug for UBigInt<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("{ ")?;
for i in self.0 {
write!(f, "{:016x}, ", i)?
}
f.write_str("}")?;
Ok(())
}
}
impl<const N: usize> UBigInt<N> {
pub const fn new(value: [u64; N]) -> Self {
Self(value)
}
pub const fn from_ref(value: &[u64; N]) -> &Self {
let ptr = value as *const [u64; N] as *const UBigInt<N>;
unsafe { &*ptr }
}
pub const fn from_ref_mut(value: &mut [u64; N]) -> &mut Self {
let ptr = value as *mut [u64; N] as *mut UBigInt<N>;
unsafe { &mut *ptr }
}
pub const ZERO: Self = Self([u64::MIN; N]);
pub const MAX: Self = Self([u64::MAX; N]);
pub const MIN: Self = Self::ZERO;
pub const ONE: Self = {
let mut one = Self::ZERO;
one.0[0] = 1;
one
};
pub fn overflowing_sub(&self, rhs: &Self) -> (Self, bool) {
let mut buf = *self;
let overflowed = buf.overflowing_sub_assign(rhs);
(buf, overflowed)
}
pub fn overflowing_sub_assign(&mut self, rhs: &Self) -> bool {
let mut carry = false;
for i in 0..N {
(self.0[i], carry) = super::carry_sub(self.0[i], rhs.0[i], carry);
}
carry
}
pub fn overflowing_add(&self, rhs: &Self) -> (Self, bool) {
let mut buf = *self;
let overflowed = buf.overflowing_add_assign(rhs);
(buf, overflowed)
}
pub fn overflowing_add_assign(&mut self, rhs: &Self) -> bool {
let mut carry = false;
for i in 0..N {
(self.0[i], carry) = super::carry_add(self.0[i], rhs.0[i], carry);
}
carry
}
pub fn count_digits_fast(&self) -> usize {
for (count, digit) in self.0.into_iter().rev().enumerate() {
if digit != 0 {
return N - count;
};
}
0
}
pub fn count_digits(&self) -> usize {
let mut num_digts = 0;
let mut digit_encounterd = false;
for digit in self.0.iter().rev() {
digit_encounterd |= *digit != 0;
num_digts += digit_encounterd as usize;
}
num_digts
}
pub fn add(&self, rhs: &Self) -> Self {
let mut buf = *self;
buf.add_assign(rhs);
buf
}
pub fn add_assign(&mut self, rhs: &Self) {
let mut carry = false;
for i in 0..N {
(self.0[i], carry) = super::carry_add(self.0[i], rhs.0[i], carry);
}
}
pub fn double(&self) -> Self {
self.add(self)
}
pub fn double_assign(&mut self) {
let mut carry = false;
for i in 0..N {
(self.0[i], carry) = super::carry_add(self.0[i], self.0[i], carry);
}
}
pub fn mul_digit_assign(&mut self, digit: u64) {
let mut carry = 0;
for i in self.0.iter_mut() {
(*i, carry) = carry_mul(*i, digit, carry);
}
}
pub fn mul_digit(&self, digit: u64) -> Self {
let mut buf = *self;
buf.mul_digit_assign(digit);
buf
}
pub fn overflowing_mul_digit(&self, digit: u64) -> (Self, u64) {
let mut buf = *self;
let overflow = buf.overflowing_mul_digit_assign(digit);
(buf, overflow)
}
pub fn overflowing_mul_digit_assign(&mut self, digit: u64) -> u64 {
let mut carry = 0;
for i in self.0.iter_mut() {
(*i, carry) = carry_mul(*i, digit, carry);
}
carry
}
pub fn sub(&self, rhs: &Self) -> Self {
let mut buf = *self;
buf.sub_assign(rhs);
buf
}
pub fn sub_assign(&mut self, rhs: &Self) {
let mut carry = false;
for i in 0..N {
(self.0[i], carry) = super::carry_sub(self.0[i], rhs.0[i], carry);
}
}
pub fn and_bool(&self, rhs: bool) -> Self {
let mut buf = *self;
buf.and_bool_assign(rhs);
buf
}
pub fn and_bool_assign(&mut self, rhs: bool) {
let mask = (rhs as u64).wrapping_neg();
for digit in self.0.iter_mut() {
*digit &= mask
}
}
pub fn left_align(&mut self) -> u64 {
let num_digits = self.count_digits();
assert_ne!(num_digits, 0);
let left_shift = self.0[num_digits - 1].leading_zeros() as u64;
self.shift_left_assign(left_shift);
left_shift
}
pub fn shift_right_assign(&mut self, mut rhs: u64) {
rhs %= 64;
let left_shift = (64 - rhs) % 64;
let mask = ((rhs != 0) as u64).wrapping_neg();
for i in 0..N - 1 {
self.0[i] >>= rhs;
self.0[i] |= (self.0[i + 1] << left_shift) & mask;
}
self.0[N - 1] >>= rhs;
}
pub fn shift_right(&self, rhs: u64) -> Self {
let mut buf = *self;
buf.shift_right_assign(rhs);
buf
}
pub fn shift_left_assign(&mut self, mut rhs: u64) {
rhs %= 64;
let right_shift = (64 - rhs) % 64;
let mask = ((rhs != 0) as u64).wrapping_neg();
for i in (1..N).rev() {
self.0[i] <<= rhs;
self.0[i] |= (self.0[i - 1] >> right_shift) & mask;
}
self.0[0] <<= rhs;
}
pub fn shift_left(&self, rhs: u64) -> Self {
let mut buf = *self;
buf.shift_left_assign(rhs);
buf
}
pub fn not_assign(&mut self) {
for digit in self.0.iter_mut() {
*digit = !*digit
}
}
pub fn not(&self) -> Self {
let mut buf = *self;
buf.not_assign();
buf
}
pub fn xor_assign(&mut self, rhs: &Self) {
for (digit, rhs_digit) in self.0.iter_mut().zip(rhs.0) {
*digit ^= rhs_digit;
}
}
pub fn xor(&self, rhs: &Self) -> Self {
let mut buf = *self;
buf.xor_assign(rhs);
buf
}
pub fn and_assign(&mut self, rhs: &Self) {
for (digit, rhs_digit) in self.0.iter_mut().zip(rhs.0) {
*digit &= rhs_digit;
}
}
pub fn and(&self, rhs: &Self) -> Self {
let mut buf = *self;
buf.and_assign(rhs);
buf
}
pub fn or_assign(&mut self, rhs: &Self) {
for (digit, rhs_digit) in self.0.iter_mut().zip(rhs.0) {
*digit |= rhs_digit;
}
}
pub fn or(&self, rhs: &Self) -> Self {
let mut buf = *self;
buf.or_assign(rhs);
buf
}
pub fn nor_assign(&mut self, rhs: &Self) {
for (digit, rhs_digit) in self.0.iter_mut().zip(rhs.0) {
*digit = !(*digit | rhs_digit);
}
}
pub fn nor(&self, rhs: &Self) -> Self {
let mut buf = *self;
buf.nor_assign(rhs);
buf
}
pub fn xnor_assign(&mut self, rhs: &Self) {
for (digit, rhs_digit) in self.0.iter_mut().zip(rhs.0) {
*digit = !(*digit ^ rhs_digit);
}
}
pub fn xnor(&self, rhs: &Self) -> Self {
let mut buf = *self;
buf.xnor_assign(rhs);
buf
}
pub fn nand_assign(&mut self, rhs: &Self) {
for (digit, rhs_digit) in self.0.iter_mut().zip(rhs.0) {
*digit = !(*digit & rhs_digit);
}
}
pub fn nand(&self, rhs: &Self) -> Self {
let mut buf = *self;
buf.nand_assign(rhs);
buf
}
#[allow(clippy::len_without_is_empty)]
pub const fn len(&self) -> usize {
self.0.len()
}
pub fn resize<const O: usize>(self) -> UBigInt<O> {
let min = core::cmp::min(O, N);
let mut new = UBigInt([0; O]);
new.0[..min].copy_from_slice(&self.0[..min]);
new
}
pub const fn get_bit(&self, bit: usize) -> bool {
assert!(bit < u64::BITS as usize * N);
self.0[bit / (u64::BITS as usize)] & 1 << (bit % (u64::BITS as usize)) != 0
}
pub fn set_bit(&mut self, bit: usize, value: bool) {
let digit = bit / (u64::BITS) as usize;
assert!(digit < N);
let bit = bit % u64::BITS as usize;
self.0[digit] &= !(1 << bit);
self.0[digit] |= (value as u64) << bit;
}
pub fn set_byte(&mut self, byte: usize, value: u8) {
let digit = byte / size_of::<u64>();
assert!(digit < N);
let byte = byte % size_of::<u64>() * u8::BITS as usize;
self.0[digit] &= !(0xff << byte);
self.0[digit] |= (value as u64) << byte;
}
pub fn count_bits(&self) -> usize {
let num_ditis = self.count_digits().saturating_sub(1);
let bits = u64::BITS as usize - self.0[num_ditis].leading_zeros() as usize;
num_ditis * u64::BITS as usize + bits
}
}
fn partial_div(m0: u64, m1: u64, d1: u64, d0: u64) -> u64 {
let mut r = ((m0 as u128) << 64) | m1 as u128;
let mut d = ((d0 as u128) << 64) | d1 as u128;
let mut q: u64 = 0;
for _ in 0..64 {
q <<= 1;
if r >= d {
q |= 1;
r -= d;
}
d >>= 1;
}
let mask = (q >> (64 - 1)).wrapping_neg();
q <<= 1;
q |= (r >= d) as u64;
q | mask
}
macro_rules! impl_non_generic {
($n:literal) => {
impl UBigInt<$n> {
const _POSITIVE_N: () = assert!($n > 0);
pub fn widening_mul(&self, rhs: &Self) -> UBigInt<{ $n * 2 }> {
let mut product = [0u64; $n * 2];
for i in 0..self.len() {
let mut carry = 0;
for j in 0..rhs.len() {
let partial_product;
(partial_product, carry) = super::carry_mul(self.0[i], rhs.0[j], carry);
let (sum, overflowed) = product[i + j].overflowing_add(partial_product);
product[i + j] = sum;
carry += overflowed as u64;
}
product[i + rhs.len()] = carry;
}
product.into()
}
pub fn widening_shift_left(&self, mut rhs: u64) -> UBigInt<{ $n + 1 }> {
rhs %= 64;
let mut expanded = [0u64; $n + 1];
let right_shift = (64 - rhs) % 64;
let mask = ((rhs != 0) as u64).wrapping_neg();
expanded[$n] = self.0[$n - 1] >> right_shift & mask;
for i in (1..$n).rev() {
expanded[i] = self.0[i] << rhs;
expanded[i] |= (self.0[i - 1] >> right_shift) & mask;
}
expanded[0] = self.0[0] << rhs;
expanded.into()
}
pub fn div(&self, rhs: &Self) -> (Self, Self) {
assert_ne!(*rhs, Self::ZERO);
let num_len = self.count_digits() + 1;
let div_len = rhs.count_digits();
let norm_shift;
let sdiv = {
let mut sdiv = *rhs;
norm_shift = sdiv.left_align();
sdiv
};
let mut snum = self.widening_shift_left(norm_shift);
let d0 = sdiv.0[div_len - 1];
let d1 = match div_len {
0 => unreachable!(),
1 => 0,
_ => sdiv.0[div_len - 2],
};
let num_loops = num_len.saturating_sub(div_len);
let mut quotient = Self::ZERO;
let mut quotient_pos = num_loops;
for (win_bot, win_top) in (0..num_loops).zip(num_len - num_loops..num_len).rev() {
let mut temp = UBigInt::<{ $n + 1 }>::ZERO;
let mut partial_quotient =
partial_div(snum.0[win_top], snum.0[win_top - 1], d1, d0);
let mut mul_carry = 0;
for i in 0..div_len {
(temp.0[i], mul_carry) =
super::carry_mul(sdiv.0[i], partial_quotient, mul_carry);
}
temp.0[div_len] = mul_carry;
let mut sub_carry = false;
for i in 0..div_len + 1 {
(snum.0[win_bot + i], sub_carry) =
super::carry_sub(snum.0[win_bot + i], temp.0[i], sub_carry);
}
partial_quotient -= sub_carry as u64;
let mask = (sub_carry as u64).wrapping_neg();
let mut add_carry = false;
for i in 0..div_len {
(snum.0[win_bot + i], add_carry) =
super::carry_add(snum.0[win_bot + i], sdiv.0[i] & mask, add_carry);
}
snum.0[win_top] = snum.0[win_top].wrapping_add(add_carry as u64);
debug_assert!(snum.0[win_top] == 0);
quotient_pos -= 1;
quotient.0[quotient_pos] = partial_quotient;
}
snum.shift_right_assign(norm_shift);
(quotient, snum.0[..$n].try_into().unwrap())
}
pub fn div_assign(&mut self, rhs: &Self) {
*self = self.div(rhs).0;
}
pub fn from_be_bytes(bytes: [u8; $n * size_of::<u64>()]) -> Self {
let mut output = [0; $n];
for (chunk, digit) in bytes.rchunks_exact(size_of::<u64>()).zip(output.iter_mut()) {
*digit = u64::from_be_bytes(chunk.try_into().unwrap())
}
output.into()
}
pub fn from_le_bytes(bytes: [u8; $n * size_of::<u64>()]) -> Self {
let mut output = [0; $n];
for (chunk, digit) in bytes.chunks_exact(size_of::<u64>()).zip(output.iter_mut()) {
*digit = u64::from_le_bytes(chunk.try_into().unwrap())
}
output.into()
}
pub fn to_be_bytes(self) -> [u8; $n * size_of::<u64>()] {
let mut output = [0; $n * size_of::<u64>()];
for (digit, chunk) in self
.0
.into_iter()
.zip(output.chunks_exact_mut(size_of::<u64>()).rev())
{
chunk.copy_from_slice(&digit.to_be_bytes());
}
output
}
pub fn to_le_bytes(self) -> [u8; $n * size_of::<u64>()] {
let mut output = [0; $n * size_of::<u64>()];
for (digit, chunk) in self
.0
.into_iter()
.zip(output.chunks_exact_mut(size_of::<u64>()))
{
chunk.copy_from_slice(&digit.to_le_bytes());
}
output
}
}
};
}
impl_non_generic!(2);
impl_non_generic!(3);
impl_non_generic!(4);
impl_non_generic!(8);
impl_non_generic!(5);
impl_non_generic!(6);
impl<const N: usize> Ord for UBigInt<N> {
fn cmp(&self, other: &Self) -> Ordering {
let overflowed = self.overflowing_sub(other).1;
if overflowed {
return Ordering::Less;
}
if self.0 == other.0 {
return Ordering::Equal;
}
Ordering::Greater
}
}
impl<const N: usize> PartialOrd for UBigInt<N> {
fn lt(&self, other: &Self) -> bool {
self.overflowing_sub(other).1
}
fn le(&self, other: &Self) -> bool {
!self.gt(other)
}
fn gt(&self, other: &Self) -> bool {
other.overflowing_sub(self).1
}
fn ge(&self, other: &Self) -> bool {
!self.lt(other)
}
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<const N: usize> From<[u64; N]> for UBigInt<N> {
fn from(value: [u64; N]) -> Self {
Self(value)
}
}
impl<const N: usize> From<UBigInt<N>> for [u64; N] {
fn from(value: UBigInt<N>) -> Self {
value.0
}
}
impl<const N: usize> From<u64> for UBigInt<N> {
fn from(value: u64) -> Self {
let mut big_int = [0u64; N];
big_int[0] = value;
big_int.into()
}
}
impl<const N: usize> Default for UBigInt<N> {
fn default() -> Self {
Self::ZERO
}
}
impl<const N: usize> TryFrom<&[u64]> for UBigInt<N> {
type Error = core::array::TryFromSliceError;
fn try_from(value: &[u64]) -> Result<Self, Self::Error> {
Ok(Self(<[u64; N]>::try_from(value)?))
}
}
impl<const N: usize> TryFrom<BigInt<N>> for UBigInt<N> {
type Error = FromNegErr;
fn try_from(value: BigInt<N>) -> Result<Self, Self::Error> {
if value.is_negative() {
return Err(FromNegErr);
};
Ok(value.digits)
}
}
impl<const N: usize> AsRef<[u64; N]> for UBigInt<N> {
fn as_ref(&self) -> &[u64; N] {
&self.0
}
}
impl<const N: usize> AsMut<[u64; N]> for UBigInt<N> {
fn as_mut(&mut self) -> &mut [u64; N] {
&mut self.0
}
}
impl<const N: usize> AsRef<UBigInt<N>> for [u64; N] {
fn as_ref(&self) -> &UBigInt<N> {
todo!()
}
}
impl<const N: usize> AsMut<UBigInt<N>> for [u64; N] {
fn as_mut(&mut self) -> &mut UBigInt<N> {
UBigInt::from_ref_mut(self)
}
}
#[cfg(test)]
mod tests {
use super::UBigInt;
#[test]
fn add() {
let x = UBigInt([
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
]);
let y = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
]);
assert_eq!(x.add(&y), UBigInt::MAX);
let x = UBigInt([
0xfedcba9876543211,
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
]);
assert_eq!(x.add(&y), UBigInt::ZERO);
}
#[test]
fn sub() {
let x = UBigInt([
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
]);
let y = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
]);
assert_eq!(UBigInt::MAX.sub(&x), y);
let x = UBigInt([
0xfedcba9876543211,
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
]);
assert_eq!(UBigInt::ZERO.sub(&y), x);
}
#[test]
fn widening_mul() {
let x = UBigInt([
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
0x1000000000000000,
]);
let y = UBigInt([
0x0000000000000000,
0x0000000000000000,
0x0000000000010000,
0x0000000000000000,
]);
let product = UBigInt([
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
0x0000000000001000,
0x0000000000000000,
]);
assert_eq!(x.widening_mul(&y), product);
let y = UBigInt([
0xfedcba9876543211,
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
]);
assert_eq!(y.widening_mul(&UBigInt::ONE), y.resize());
let a = UBigInt([0x124924924924924, 0, 0, 0]);
let b = UBigInt([
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
0x0000000000000000,
]);
let product = UBigInt([
0x80a670cd733d9a40,
0x7f584250f1dbea8b,
0x80a7bdaf0e241574,
81985529216486895,
]);
assert_eq!(a.widening_mul(&b).resize(), product);
}
#[test]
fn div() {
let y = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
]);
assert_eq!(y.div(&y), (UBigInt::ONE, UBigInt::ZERO));
let x = UBigInt([0, 1, 0, 0]);
let quotient = UBigInt([
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
0x0000000000000000,
]);
let remainder = UBigInt([0x0123456789abcdef, 0, 0, 0]);
assert_eq!(y.div(&x), (quotient, remainder));
assert_eq!(quotient.div(&y), (UBigInt::ZERO, quotient));
let a = UBigInt([
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
]);
let b = UBigInt([
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
0x0000000000000000,
]);
let quotient = UBigInt([0x124924924924924, 0, 0, 0]);
let remainder = UBigInt([
0x7e3649cb031697d0,
0x81cb031697cfe364,
0x7e34fce968301c9b,
0x0000000000000000,
]);
assert_eq!(a.div(&b), (quotient, remainder));
}
#[test]
fn widening_shift_left() {
let x = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
]);
let shifted = UBigInt([
0x3456789abcdef000,
0xcba9876543210012,
0x3456789abcdeffed,
0xcba9876543210012,
0x0000000000000fed,
]);
assert_eq!(x.widening_shift_left(12), shifted);
let mut widened_x = UBigInt::ZERO;
widened_x.0[..x.len()].copy_from_slice(&x.0[..]);
assert_eq!(x.widening_shift_left(0), widened_x);
}
#[test]
fn left_align() {
let mut x = UBigInt([
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
0x0823456789abcdef,
]);
let shift_amount = x.left_align();
let aligned = UBigInt([
0xedcba98765432100,
0x123456789abcdeff,
0xedcba98765432100,
0x823456789abcdeff,
]);
assert_eq!(x, aligned);
assert_eq!(shift_amount, 4);
}
#[test]
fn count_digits_fast() {
let x = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
]);
assert_eq!(x.count_digits_fast(), 4);
let y = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0000000000000000,
0xfedcba9876543210,
]);
assert_eq!(y.count_digits_fast(), 4);
let z = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0x0000000000000000,
]);
assert_eq!(z.count_digits_fast(), 3);
assert_eq!(UBigInt::<4>::ZERO.count_digits_fast(), 0);
}
#[test]
fn count_digits() {
let x = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0xfedcba9876543210,
]);
assert_eq!(x.count_digits(), 4);
let y = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0000000000000000,
0xfedcba9876543210,
]);
assert_eq!(y.count_digits(), 4);
let z = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0x0000000000000000,
]);
assert_eq!(z.count_digits(), 3);
assert_eq!(UBigInt::<4>::ZERO.count_digits(), 0);
}
#[test]
fn get_bit() {
let z = UBigInt([
0x0000000000000000,
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
]);
assert!(!z.get_bit(0));
assert!(z.get_bit(64));
assert!(z.get_bit(248));
assert!(!z.get_bit(255));
}
#[test]
fn count_bits() {
let z = UBigInt([
0x0000000000000000,
0x0123456789abcdef,
0x0000000000000000,
0xf123456789abcdef,
]);
assert_eq!(z.count_bits(), 256);
let x = UBigInt([
0x0123456789abcdef,
0xfedcba9876543210,
0x0123456789abcdef,
0x0000000000000000,
]);
assert_eq!(x.count_bits(), 185);
assert_eq!(UBigInt::<4>::ZERO.count_bits(), 0);
assert_eq!(UBigInt::<4>::ONE.count_bits(), 1);
}
#[test]
fn from_le_bytes() {
let bytes = [
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20,
];
let num = UBigInt([
0x0807060504030201,
0x100f0e0d0c0b0a09,
0x1817161514131211,
0x201f1e1d1c1b1a19,
]);
assert_eq!(UBigInt::<4>::from_le_bytes(bytes), num);
}
#[test]
fn to_le_bytes() {
let num = UBigInt([
0x0807060504030201,
0x100f0e0d0c0b0a09,
0x1817161514131211,
0x201f1e1d1c1b1a19,
]);
let bytes = [
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20,
];
assert_eq!(num.to_le_bytes(), bytes);
}
}