use crate::Integer;
use crate::cast::CastFrom;
use core::fmt::{self, Debug, Formatter};
use super::TestConvert;
use quickcheck::Arbitrary;
#[derive(Clone, Copy)]
pub struct BitInt<const S: bool, const B: usize> {
bits: [bool; B],
}
impl<const S: bool, const B: usize> BitInt<S, B> {
const ZERO: Self = Self { bits: [false; B] };
pub const MIN: Self = if S {
let mut bits = [false; B];
bits[B - 1] = true; Self { bits }
} else {
Self::ZERO
};
pub const MAX: Self = if S {
let mut bits = [true; B];
bits[B - 1] = false; Self { bits }
} else {
Self { bits: [true; B] }
};
pub fn set_bit(&mut self, index: usize, value: bool) {
self.bits[index] = value;
}
pub fn eq(&self, other: &Self) -> bool {
self.bits.iter().zip(other.bits.iter()).all(|(a, b)| a == b)
}
fn is_negative(&self) -> bool {
if S { self.bits[B - 1] } else { false }
}
pub fn overflowing_shr(self, n: usize) -> (Self, bool) {
let (n, overflow) = (n % B, n >= B);
let mut out = if self.is_negative() {
[true; B]
} else {
[false; B]
};
for i in n..B {
out[i - n] = self.bits[i];
}
(Self { bits: out }, overflow)
}
pub fn bit(&self, index: usize) -> bool {
self.bits[index]
}
pub fn rotate_left(mut self, n: usize) -> Self {
self.bits.rotate_right(n % B); self
}
pub fn rotate_right(mut self, n: usize) -> Self {
self.bits.rotate_left(n % B); self
}
pub fn overflowing_shl(self, n: usize) -> (Self, bool) {
let (n, overflow) = (n % B, n >= B);
let mut out = [false; B];
for i in 0..(B - n) {
out[i + n] = self.bits[i];
}
(Self { bits: out }, overflow)
}
pub fn trailing_ones(self) -> u32 {
let mut count = 0;
for &bit in self.bits.iter() {
if bit {
count += 1;
} else {
break;
}
}
count
}
pub fn leading_ones(self) -> u32 {
let mut count = 0;
for &bit in self.bits.iter().rev() {
if bit {
count += 1;
} else {
break;
}
}
count
}
pub fn leading_zeros(self) -> u32 {
self.not().leading_ones()
}
pub fn trailing_zeros(self) -> u32 {
self.not().trailing_ones()
}
pub fn count_ones(self) -> u32 {
self.bits.iter().filter(|&&b| b).count() as u32
}
pub fn count_zeros(self) -> u32 {
self.bits.iter().filter(|&&b| !b).count() as u32
}
pub fn reverse_bits(mut self) -> Self {
self.bits.reverse();
self
}
}
use crate::errors::ParseIntError;
use core::num::IntErrorKind;
use crate::cast::As;
impl<const B: usize> BitInt<false, B> {
pub fn from_str_radix(s: &str, radix: u32) -> Result<Self, crate::errors::ParseIntError> {
if radix < 2 || radix > 36 {
panic!("radix must be in the range 2..=36");
}
let mut out = Self::ZERO;
for c in s.chars() {
let digit = c.to_digit(radix).ok_or(ParseIntError { kind: IntErrorKind::InvalidDigit })?;
let (new_out, o1) = out.overflowing_mul(radix.as_());
let (new_out, o2) = new_out.overflowing_add(digit.as_());
if o1 || o2 {
return Err(ParseIntError { kind: IntErrorKind::PosOverflow });
}
out = new_out;
}
Ok(out)
}
pub fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
for i in (0..B).rev() {
if self.bits[i] != rhs.bits[i] {
return if self.bits[i] {
core::cmp::Ordering::Greater
} else {
core::cmp::Ordering::Less
};
}
}
core::cmp::Ordering::Equal
}
pub fn power_of_two(n: usize) -> Self {
let mut out = Self { bits: [false; B] };
out.set_bit(n, true);
out
}
pub fn is_power_of_two(self) -> bool {
self.count_ones() == 1
}
pub fn is_zero(&self) -> bool {
self.eq(&Self::ZERO)
}
pub fn is_one(&self) -> bool {
self.bit(0) && self.is_power_of_two()
}
pub fn widening_mul(self, rhs: Self) -> (Self, Self) {
let mut low = Self::ZERO;
let mut high = Self::ZERO;
for i in 0..B {
let mut carry = false;
for j in 0..B {
let index = i + j;
let c = if index < B {
low.bit(index)
} else {
high.bit(index - B)
};
let prod = (self.bits[i] & rhs.bits[j]) ^ carry ^ c; carry = ((self.bits[i] & rhs.bits[j]) as u8 + carry as u8 + c as u8) >= 2;
if index < B {
low.set_bit(index, prod);
} else {
high.set_bit(index - B, prod);
}
}
high.set_bit(i, carry);
}
(low, high)
}
pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
let (low, high) = self.widening_mul(rhs);
let overflow = !high.is_zero();
(low, overflow)
}
pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
let mut out = Self::ZERO;
let mut carry = false;
for i in 0..B {
let sum = (self.bits[i] as u8) + (rhs.bits[i] as u8) + (carry as u8);
out.bits[i] = (sum % 2) != 0;
carry = sum >= 2;
}
(out, carry)
}
pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
let mut out = Self::ZERO;
let mut borrow = false;
for i in 0..B {
out.bits[i] = self.bits[i] ^ rhs.bits[i] ^ borrow;
let sub = (self.bits[i] as i8) - (rhs.bits[i] as i8) - (borrow as i8);
borrow = sub < 0;
}
(out, borrow)
}
fn div_rem(self, rhs: Self) -> (Self, Self) {
let mut quotient = self;
let mut remainder = Self::ZERO;
for _ in 0..B {
let carry_bit = quotient.bit(B - 1);
remainder = remainder.overflowing_shl(1).0;
remainder.set_bit(0, carry_bit);
quotient = quotient.overflowing_shl(1).0;
let (new_rem, borrow) = remainder.overflowing_sub(rhs);
if !borrow {
remainder = new_rem;
quotient.set_bit(0, true); } else {
quotient.set_bit(0, false);
}
}
(quotient, remainder)
}
pub fn checked_div(self, rhs: Self) -> Option<Self> {
if rhs.is_zero() {
None
} else {
Some(self.div_rem(rhs).0)
}
}
pub fn checked_rem(self, rhs: Self) -> Option<Self> {
if rhs.is_zero() {
None
} else {
Some(self.div_rem(rhs).1)
}
}
}
impl<const S: bool, const B: usize, const R: bool, const A: usize> CastFrom<BitInt<R, A>> for BitInt<S, B> {
fn cast_from(value: BitInt<R, A>) -> Self {
let mut out = if value.is_negative() {
Self { bits: [true; B] }
} else {
Self { bits: [false; B] }
};
let min_bits = core::cmp::min(B, A);
for i in 0..min_bits {
out.set_bit(i, value.bit(i));
}
out
}
}
impl<const S: bool, const B: usize, const R: bool, const A: usize> TryFrom<&BitInt<R, A>> for BitInt<S, B> {
type Error = crate::errors::TryFromIntError;
fn try_from(value: &BitInt<R, A>) -> Result<Self, Self::Error> {
let value = *value;
match (R, S) {
(false, false) => {
if A - (value.leading_zeros() as usize) > B {
Err(crate::errors::TryFromIntError(()))
} else {
Ok(Self::cast_from(value))
}
},
(false, true) => {
if A - (value.leading_zeros() as usize) > B - 1 {
Err(crate::errors::TryFromIntError(()))
} else {
Ok(Self::cast_from(value))
}
},
(true, false) => {
if value.is_negative() || (A - (value.leading_zeros() as usize) > B) {
Err(crate::errors::TryFromIntError(()))
} else {
Ok(Self::cast_from(value))
}
},
(true, true) => {
if value.is_negative() {
if A - (value.leading_ones() as usize) > B - 1 {
Err(crate::errors::TryFromIntError(()))
} else {
Ok(Self::cast_from(value))
}
} else {
if A - (value.leading_zeros() as usize) > B - 1 {
Err(crate::errors::TryFromIntError(()))
} else {
Ok(Self::cast_from(value))
}
}
}
}
}
}
macro_rules! bitint_from_to_primitive_int {
($($ty:ty), *) => {
$(
#[allow(unused_comparisons)]
impl From<$ty> for BitInt<{<$ty>::MIN < 0}, {core::mem::size_of::<$ty>() * 8}> {
fn from(value: $ty) -> Self {
let mut out = Self { bits: [false; core::mem::size_of::<$ty>() * 8] };
for i in 0..(core::mem::size_of::<$ty>() * 8) {
out.set_bit(i, (value >> i) & 1 != 0);
}
out
}
}
#[allow(unused_comparisons)]
impl From<BitInt<{<$ty>::MIN < 0}, {core::mem::size_of::<$ty>() * 8}>> for $ty {
fn from(value: BitInt<{<$ty>::MIN < 0}, {core::mem::size_of::<$ty>() * 8}>) -> Self {
let mut out: $ty = 0;
for i in 0..(core::mem::size_of::<$ty>() * 8) {
if value.bit(i) {
out |= 1 << i;
}
}
out
}
}
impl<const S: bool, const B: usize> CastFrom<$ty> for BitInt<S, B> {
fn cast_from(value: $ty) -> Self {
Self::cast_from(BitInt::from(value))
}
}
impl<const S: bool, const B: usize> CastFrom<BitInt<S, B>> for $ty {
fn cast_from(value: BitInt<S, B>) -> Self {
Self::from(BitInt::cast_from(value))
}
}
)*
};
}
bitint_from_to_primitive_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
use core::ops::{BitAnd, BitOr, BitXor, Not};
impl<const S: bool, const B: usize> Not for BitInt<S, B> {
type Output = Self;
fn not(self) -> Self {
Self {
bits: self.bits.map(|b| !b),
}
}
}
impl<const S: bool, const B: usize> BitAnd for BitInt<S, B> {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
let mut out = Self::ZERO;
for i in 0..B {
out.bits[i] = self.bits[i] & rhs.bits[i];
}
out
}
}
impl<const S: bool, const B: usize> BitOr for BitInt<S, B> {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
let mut out = Self::ZERO;
for i in 0..B {
out.bits[i] = self.bits[i] | rhs.bits[i];
}
out
}
}
impl<const S: bool, const B: usize> BitXor for BitInt<S, B> {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
let mut out = Self::ZERO;
for i in 0..B {
out.bits[i] = self.bits[i] ^ rhs.bits[i];
}
out
}
}
impl<const S: bool, const B: usize> Arbitrary for BitInt<S, B> {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
let mut bits = [false; B];
for bit in bits.iter_mut() {
*bit = bool::arbitrary(g);
}
Self { bits }
}
}
impl<const S: bool, const B: usize> Debug for BitInt<S, B> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
for &bit in self.bits.iter().rev() {
write!(f, "{}", if bit { '1' } else { '0' })?;
}
Ok(())
}
}
use crate::literal_parse::get_size_params_from_bits;
macro_rules! integer_from_bit_int {
($($bits: literal), *) => {
$(
impl<const S: bool> From<BitInt<S, $bits>> for Integer<S, {get_size_params_from_bits($bits).0}, {get_size_params_from_bits($bits).1}> {
fn from(b: BitInt<S, $bits>) -> Self {
let mut out = if b.is_negative() {
Self::ALL_ONES
} else {
Self::ZERO
};
for i in 0..$bits {
out.set_bit(i as u32, b.bit(i));
}
out
}
}
impl<const S: bool> From<Integer<S, {get_size_params_from_bits($bits).0}, {get_size_params_from_bits($bits).1}>> for BitInt<S, $bits> {
fn from(b: Integer<S, {get_size_params_from_bits($bits).0}, {get_size_params_from_bits($bits).1}>) -> Self {
let mut out = Self::ZERO;
for i in 0..$bits {
out.set_bit(i, b.bit(i as u32));
}
out
}
}
impl<const S: bool> TestConvert for BitInt<S, $bits> {
type Output = Integer<S, {get_size_params_from_bits($bits).0}, {get_size_params_from_bits($bits).1}>;
#[inline]
fn into(self) -> Self::Output {
Integer::from(self)
}
}
)*
}
}
integer_from_bit_int!(
8, 16, 32, 64, 128, 256, 512, 56, 144, 160, 488, 2, 3, 4, 5, 7, 9, 11, 15, 23, 31, 43, 59, 61, 73, 89, 97, 101, 113, 127, 129, 173, 255, 289, 366,
402, 422 );