use digit;
use storage::Storage;
use bitpos::BitPos;
use apint::{ShiftAmount};
use errors::{Result, Error};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BitWidth(usize);
impl BitWidth {
#[inline]
pub fn w1() -> Self { BitWidth(1) }
#[inline]
pub fn w8() -> Self { BitWidth(8) }
#[inline]
pub fn w16() -> Self { BitWidth(16) }
#[inline]
pub fn w32() -> Self { BitWidth(32) }
#[inline]
pub fn w64() -> Self { BitWidth(64) }
#[inline]
pub fn w128() -> Self { BitWidth(128) }
pub fn new(width: usize) -> Result<Self> {
if width == 0 {
return Err(Error::invalid_zero_bitwidth())
}
Ok(BitWidth(width))
}
#[inline]
pub(crate) fn is_valid_pos<P>(self, pos: P) -> bool
where P: Into<BitPos>
{
pos.into().to_usize() < self.0
}
#[inline]
pub(crate) fn is_valid_shift_amount<S>(self, shift_amount: S) -> bool
where S: Into<ShiftAmount>
{
shift_amount.into().to_usize() < self.0
}
#[inline]
pub(crate) fn sign_bit_pos(self) -> BitPos {
BitPos::from(self.to_usize() - 1)
}
}
impl From<usize> for BitWidth {
fn from(width: usize) -> BitWidth {
BitWidth::new(width).unwrap()
}
}
impl BitWidth {
#[inline]
pub fn to_usize(self) -> usize {
self.0
}
pub(crate) fn excess_bits(self) -> Option<usize> {
match self.to_usize() % digit::BITS {
0 => None,
n => Some(n)
}
}
pub(crate) fn excess_width(self) -> Option<BitWidth> {
self.excess_bits().map(BitWidth::from)
}
#[inline]
pub(crate) fn storage(self) -> Storage {
Storage::from(self)
}
#[inline]
pub(crate) fn required_digits(&self) -> usize {
((self.to_usize() - 1) / digit::BITS) + 1
}
}
#[cfg(test)]
mod tests {
use super::*;
mod excess_bits {
use super::*;
#[test]
fn powers_of_two() {
assert_eq!(BitWidth::w1().excess_bits(), Some(1));
assert_eq!(BitWidth::w8().excess_bits(), Some(8));
assert_eq!(BitWidth::w16().excess_bits(), Some(16));
assert_eq!(BitWidth::w32().excess_bits(), Some(32));
assert_eq!(BitWidth::w64().excess_bits(), None);
assert_eq!(BitWidth::w128().excess_bits(), None);
}
#[test]
fn multiples_of_50() {
assert_eq!(BitWidth::new(50).unwrap().excess_bits(), Some(50));
assert_eq!(BitWidth::new(100).unwrap().excess_bits(), Some(36));
assert_eq!(BitWidth::new(150).unwrap().excess_bits(), Some(22));
assert_eq!(BitWidth::new(200).unwrap().excess_bits(), Some(8));
assert_eq!(BitWidth::new(250).unwrap().excess_bits(), Some(58));
assert_eq!(BitWidth::new(300).unwrap().excess_bits(), Some(44));
}
}
}