use apint::ApInt;
use traits::Width;
use digit::Bit;
use bitwidth::BitWidth;
use errors::Result;
use apint::{ShiftAmount};
use bitpos::{BitPos};
use int::Int;
use utils::{try_forward_bin_mut_impl, forward_mut_impl, forward_bin_mut_impl};
#[cfg(feature = "rand_support")]
use rand;
use std::cmp::Ordering;
use std::ops::{
Not,
BitAnd,
BitOr,
BitXor,
BitAndAssign,
BitOrAssign,
BitXorAssign,
Add,
Sub,
Mul,
Div,
Rem,
AddAssign,
SubAssign,
MulAssign,
DivAssign,
RemAssign
};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct UInt {
value: ApInt,
}
impl From<ApInt> for UInt {
fn from(value: ApInt) -> UInt {
UInt { value }
}
}
impl UInt {
pub fn into_apint(self) -> ApInt {
self.value
}
pub fn into_signed(self) -> Int {
Int::from(self.value)
}
}
impl UInt {
pub fn from_bit<B>(bit: B) -> UInt
where
B: Into<Bit>,
{
UInt::from(ApInt::from_bit(bit))
}
#[inline]
pub fn from_u8(val: u8) -> UInt {
UInt::from(ApInt::from_u8(val))
}
#[inline]
pub fn from_u16(val: u16) -> UInt {
UInt::from(ApInt::from_u16(val))
}
#[inline]
pub fn from_u32(val: u32) -> UInt {
UInt::from(ApInt::from_u32(val))
}
#[inline]
pub fn from_u64(val: u64) -> UInt {
UInt::from(ApInt::from_u64(val))
}
pub fn from_u128(val: u128) -> UInt {
UInt::from(ApInt::from_u128(val))
}
pub fn zero(width: BitWidth) -> UInt {
UInt::from(ApInt::zero(width))
}
pub fn one(width: BitWidth) -> UInt {
UInt::from(ApInt::one(width))
}
pub fn all_unset(width: BitWidth) -> UInt {
UInt::zero(width)
}
pub fn all_set(width: BitWidth) -> UInt {
UInt::from(ApInt::all_set(width))
}
pub fn min_value(width: BitWidth) -> UInt {
UInt::from(ApInt::unsigned_min_value(width))
}
pub fn max_value(width: BitWidth) -> UInt {
UInt::from(ApInt::unsigned_max_value(width))
}
}
impl<B> From<B> for UInt
where B: Into<Bit>
{
#[inline]
fn from(bit: B) -> UInt {
UInt::from_bit(bit)
}
}
impl From<u8> for UInt {
fn from(val: u8) -> UInt {
UInt::from_u8(val)
}
}
impl From<u16> for UInt {
fn from(val: u16) -> UInt {
UInt::from_u16(val)
}
}
impl From<u32> for UInt {
fn from(val: u32) -> UInt {
UInt::from_u32(val)
}
}
impl From<u64> for UInt {
fn from(val: u64) -> UInt {
UInt::from_u64(val)
}
}
impl From<u128> for UInt {
fn from(val: u128) -> UInt {
UInt::from_u128(val)
}
}
macro_rules! impl_from_array_for_uint {
($n:expr) => {
impl From<[u64; $n]> for UInt {
fn from(val: [u64; $n]) -> UInt {
UInt::from(ApInt::from(val))
}
}
}
}
impl_from_array_for_uint!(2); impl_from_array_for_uint!(3); impl_from_array_for_uint!(4); impl_from_array_for_uint!(5); impl_from_array_for_uint!(6); impl_from_array_for_uint!(7); impl_from_array_for_uint!(8); impl_from_array_for_uint!(16); impl_from_array_for_uint!(32);
impl UInt {
pub fn is_zero(&self) -> bool {
self.value.is_zero()
}
pub fn is_one(&self) -> bool {
self.value.is_one()
}
pub fn is_even(&self) -> bool {
self.value.is_even()
}
pub fn is_odd(&self) -> bool {
self.value.is_odd()
}
}
impl UInt {
pub fn checked_lt(&self, rhs: &UInt) -> Result<bool> {
self.value.checked_ult(&rhs.value)
}
#[inline]
pub fn checked_le(&self, rhs: &UInt) -> Result<bool> {
self.value.checked_ule(&rhs.value)
}
#[inline]
pub fn checked_gt(&self, rhs: &UInt) -> Result<bool> {
self.value.checked_ugt(&rhs.value)
}
#[inline]
pub fn checked_ge(&self, rhs: &UInt) -> Result<bool> {
self.value.checked_uge(&rhs.value)
}
}
impl PartialOrd for UInt {
fn partial_cmp(&self, rhs: &UInt) -> Option<Ordering> {
if self.value.width() != rhs.value.width() {
return None;
}
if self.checked_lt(rhs).unwrap() {
return Some(Ordering::Less);
}
if self.value == rhs.value {
return Some(Ordering::Equal);
}
Some(Ordering::Greater)
}
fn lt(&self, rhs: &UInt) -> bool {
self.checked_lt(rhs).unwrap_or(false)
}
fn le(&self, rhs: &UInt) -> bool {
self.checked_le(rhs).unwrap_or(false)
}
fn gt(&self, rhs: &UInt) -> bool {
self.checked_gt(rhs).unwrap_or(false)
}
fn ge(&self, rhs: &UInt) -> bool {
self.checked_ge(rhs).unwrap_or(false)
}
}
impl UInt {
pub fn resize_to_bool(&self) -> bool {
self.value.resize_to_bool()
}
pub fn resize_to_u8(&self) -> u8 {
self.value.resize_to_u8()
}
pub fn resize_to_u16(&self) -> u16 {
self.value.resize_to_u16()
}
pub fn resize_to_u32(&self) -> u32 {
self.value.resize_to_u32()
}
pub fn resize_to_u64(&self) -> u64 {
self.value.resize_to_u64()
}
pub fn resize_to_u128(&self) -> u128 {
self.value.resize_to_u128()
}
}
impl UInt {
pub fn try_to_bool(&self) -> Result<bool> {
self.value.try_to_bool()
}
pub fn try_to_u8(&self) -> Result<u8> {
self.value.try_to_u8()
}
pub fn try_to_u16(&self) -> Result<u16> {
self.value.try_to_u16()
}
pub fn try_to_u32(&self) -> Result<u32> {
self.value.try_to_u32()
}
pub fn try_to_u64(&self) -> Result<u64> {
self.value.try_to_u64()
}
pub fn try_to_u128(&self) -> Result<u128> {
self.value.try_to_u128()
}
}
impl UInt {
pub fn checked_shl_assign<S>(&mut self, shift_amount: S) -> Result<()>
where S: Into<ShiftAmount>
{
self.value.checked_shl_assign(shift_amount)
}
pub fn into_checked_shl<S>(self, shift_amount: S) -> Result<UInt>
where S: Into<ShiftAmount>
{
self.value.into_checked_shl(shift_amount).map(UInt::from)
}
pub fn checked_shr_assign<S>(&mut self, shift_amount: S) -> Result<()>
where S: Into<ShiftAmount>
{
self.value.checked_lshr_assign(shift_amount)
}
pub fn into_checked_shr<S>(self, shift_amount: S) -> Result<UInt>
where S: Into<ShiftAmount>
{
self.value.into_checked_lshr(shift_amount).map(UInt::from)
}
}
use std::ops::{Shl, ShlAssign, Shr, ShrAssign};
impl<S> Shl<S> for UInt
where S: Into<ShiftAmount>
{
type Output = UInt;
fn shl(self, shift_amount: S) -> Self::Output {
self.into_checked_shl(shift_amount).unwrap()
}
}
impl<S> Shr<S> for UInt
where S: Into<ShiftAmount>
{
type Output = UInt;
fn shr(self, shift_amount: S) -> Self::Output {
self.into_checked_shr(shift_amount).unwrap()
}
}
impl<S> ShlAssign<S> for UInt
where S: Into<ShiftAmount>
{
fn shl_assign(&mut self, shift_amount: S) {
self.checked_shl_assign(shift_amount).unwrap()
}
}
impl<S> ShrAssign<S> for UInt
where S: Into<ShiftAmount>
{
fn shr_assign(&mut self, shift_amount: S) {
self.checked_shr_assign(shift_amount).unwrap()
}
}
#[cfg(feature = "rand_support")]
impl UInt {
pub fn random_with_width(width: BitWidth) -> UInt {
UInt::from(ApInt::random_with_width(width))
}
pub fn random_with_width_using<R>(width: BitWidth, rng: &mut R) -> UInt
where R: rand::Rng
{
UInt::from(ApInt::random_with_width_using(width, rng))
}
pub fn randomize(&mut self) {
self.value.randomize()
}
pub fn randomize_using<R>(&mut self, rng: &mut R)
where R: rand::Rng
{
self.value.randomize_using(rng)
}
}
impl UInt {
pub fn assign(&mut self, rhs: &UInt) {
self.value.assign(&rhs.value)
}
pub fn strict_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.strict_assign(&rhs.value)
}
}
impl UInt {
pub fn into_truncate<W>(self, target_width: W) -> Result<UInt>
where W: Into<BitWidth>
{
try_forward_bin_mut_impl(self, target_width, UInt::truncate)
}
pub fn truncate<W>(&mut self, target_width: W) -> Result<()>
where W: Into<BitWidth>
{
self.value.truncate(target_width)
}
pub fn into_extend<W>(self, target_width: W) -> Result<UInt>
where W: Into<BitWidth>
{
try_forward_bin_mut_impl(self, target_width, UInt::extend)
}
pub fn extend<W>(&mut self, target_width: W) -> Result<()>
where W: Into<BitWidth>
{
self.value.zero_extend(target_width)
}
pub fn into_resize<W>(self, target_width: W) -> UInt
where W: Into<BitWidth>
{
forward_bin_mut_impl(self, target_width, UInt::resize)
}
pub fn resize<W>(&mut self, target_width: W)
where W: Into<BitWidth>
{
self.value.zero_resize(target_width)
}
}
impl UInt {
pub fn into_bitnot(self) -> Self {
forward_mut_impl(self, UInt::bitnot)
}
pub fn bitnot(&mut self) {
self.value.bitnot()
}
pub fn into_checked_bitand(self, rhs: &UInt) -> Result<UInt> {
try_forward_bin_mut_impl(self, rhs, UInt::checked_bitand_assign)
}
pub fn checked_bitand_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.checked_bitand_assign(&rhs.value)
}
pub fn into_checked_bitor(self, rhs: &UInt) -> Result<UInt> {
try_forward_bin_mut_impl(self, rhs, UInt::checked_bitor_assign)
}
pub fn checked_bitor_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.checked_bitor_assign(&rhs.value)
}
pub fn into_checked_bitxor(self, rhs: &UInt) -> Result<UInt> {
try_forward_bin_mut_impl(self, rhs, UInt::checked_bitxor_assign)
}
pub fn checked_bitxor_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.checked_bitxor_assign(&rhs.value)
}
}
impl UInt {
pub fn get_bit_at<P>(&self, pos: P) -> Result<Bit>
where P: Into<BitPos>
{
self.value.get_bit_at(pos)
}
pub fn set_bit_at<P>(&mut self, pos: P) -> Result<()>
where P: Into<BitPos>
{
self.value.set_bit_at(pos)
}
pub fn unset_bit_at<P>(&mut self, pos: P) -> Result<()>
where P: Into<BitPos>
{
self.value.unset_bit_at(pos)
}
pub fn flip_bit_at<P>(&mut self, pos: P) -> Result<()>
where P: Into<BitPos>
{
self.value.flip_bit_at(pos)
}
pub fn set_all(&mut self) {
self.value.set_all()
}
pub fn is_all_set(&self) -> bool {
self.value.is_all_set()
}
pub fn unset_all(&mut self) {
self.value.unset_all()
}
pub fn is_all_unset(&self) -> bool {
self.value.is_all_unset()
}
pub fn flip_all(&mut self) {
self.value.flip_all()
}
}
impl UInt {
pub fn count_ones(&self) -> usize {
self.value.count_ones()
}
pub fn count_zeros(&self) -> usize {
self.value.count_zeros()
}
pub fn leading_zeros(&self) -> usize {
self.value.leading_zeros()
}
pub fn trailing_zeros(&self) -> usize {
self.value.trailing_zeros()
}
}
impl Not for UInt {
type Output = UInt;
fn not(self) -> Self::Output {
forward_mut_impl(self, UInt::bitnot)
}
}
impl<'a> BitAnd<&'a UInt> for UInt {
type Output = UInt;
fn bitand(self, rhs: &'a UInt) -> Self::Output {
self.into_checked_bitand(rhs).unwrap()
}
}
impl<'a, 'b> BitAnd<&'a UInt> for &'b UInt {
type Output = UInt;
fn bitand(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_bitand(rhs).unwrap()
}
}
impl<'a, 'b> BitAnd<&'a UInt> for &'b mut UInt {
type Output = UInt;
fn bitand(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_bitand(rhs).unwrap()
}
}
impl<'a> BitOr<&'a UInt> for UInt {
type Output = UInt;
fn bitor(self, rhs: &'a UInt) -> Self::Output {
self.into_checked_bitor(rhs).unwrap()
}
}
impl<'a, 'b> BitOr<&'a UInt> for &'b UInt {
type Output = UInt;
fn bitor(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_bitor(rhs).unwrap()
}
}
impl<'a, 'b> BitOr<&'a UInt> for &'b mut UInt {
type Output = UInt;
fn bitor(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_bitor(rhs).unwrap()
}
}
impl<'a> BitXor<&'a UInt> for UInt {
type Output = UInt;
fn bitxor(self, rhs: &'a UInt) -> Self::Output {
self.into_checked_bitxor(rhs).unwrap()
}
}
impl<'a, 'b> BitXor<&'a UInt> for &'b UInt {
type Output = UInt;
fn bitxor(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_bitxor(rhs).unwrap()
}
}
impl<'a, 'b> BitXor<&'a UInt> for &'b mut UInt {
type Output = UInt;
fn bitxor(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_bitxor(rhs).unwrap()
}
}
impl<'a> BitAndAssign<&'a UInt> for UInt {
fn bitand_assign(&mut self, rhs: &'a UInt) {
self.checked_bitand_assign(rhs).unwrap();
}
}
impl<'a> BitOrAssign<&'a UInt> for UInt {
fn bitor_assign(&mut self, rhs: &'a UInt) {
self.checked_bitor_assign(rhs).unwrap();
}
}
impl<'a> BitXorAssign<&'a UInt> for UInt {
fn bitxor_assign(&mut self, rhs: &'a UInt) {
self.checked_bitxor_assign(rhs).unwrap();
}
}
impl UInt {
pub fn into_checked_add(self, rhs: &UInt) -> Result<UInt> {
try_forward_bin_mut_impl(self, rhs, UInt::checked_add_assign)
}
pub fn checked_add_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.checked_add_assign(&rhs.value)
}
pub fn into_checked_sub(self, rhs: &UInt) -> Result<UInt> {
try_forward_bin_mut_impl(self, rhs, UInt::checked_sub_assign)
}
pub fn checked_sub_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.checked_sub_assign(&rhs.value)
}
pub fn into_checked_mul(self, rhs: &UInt) -> Result<UInt> {
try_forward_bin_mut_impl(self, rhs, UInt::checked_mul_assign)
}
pub fn checked_mul_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.checked_mul_assign(&rhs.value)
}
pub fn into_checked_div(self, rhs: &UInt) -> Result<UInt> {
try_forward_bin_mut_impl(self, rhs, UInt::checked_div_assign)
}
pub fn checked_div_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.checked_udiv_assign(&rhs.value)
}
pub fn into_checked_rem(self, rhs: &UInt) -> Result<UInt> {
try_forward_bin_mut_impl(self, rhs, UInt::checked_rem_assign)
}
pub fn checked_rem_assign(&mut self, rhs: &UInt) -> Result<()> {
self.value.checked_urem_assign(&rhs.value)
}
}
impl<'a> Add<&'a UInt> for UInt {
type Output = UInt;
fn add(self, rhs: &'a UInt) -> Self::Output {
self.into_checked_add(rhs).unwrap()
}
}
impl<'a, 'b> Add<&'a UInt> for &'b UInt {
type Output = UInt;
fn add(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_add(rhs).unwrap()
}
}
impl<'a> AddAssign<&'a UInt> for UInt {
fn add_assign(&mut self, rhs: &'a UInt) {
self.checked_add_assign(rhs).unwrap()
}
}
impl<'a> Sub<&'a UInt> for UInt {
type Output = UInt;
fn sub(self, rhs: &'a UInt) -> Self::Output {
self.into_checked_sub(rhs).unwrap()
}
}
impl<'a, 'b> Sub<&'a UInt> for &'b UInt {
type Output = UInt;
fn sub(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_sub(rhs).unwrap()
}
}
impl<'a> SubAssign<&'a UInt> for UInt {
fn sub_assign(&mut self, rhs: &'a UInt) {
self.checked_sub_assign(rhs).unwrap()
}
}
impl<'a> Mul<&'a UInt> for UInt {
type Output = UInt;
fn mul(self, rhs: &'a UInt) -> Self::Output {
self.into_checked_mul(rhs).unwrap()
}
}
impl<'a, 'b> Mul<&'a UInt> for &'b UInt {
type Output = UInt;
fn mul(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_mul(rhs).unwrap()
}
}
impl<'a> MulAssign<&'a UInt> for UInt {
fn mul_assign(&mut self, rhs: &'a UInt) {
self.checked_mul_assign(rhs).unwrap();
}
}
impl<'a> Div<&'a UInt> for UInt {
type Output = UInt;
fn div(self, rhs: &'a UInt) -> Self::Output {
self.into_checked_div(rhs).unwrap()
}
}
impl<'a, 'b> Div<&'a UInt> for &'b UInt {
type Output = UInt;
fn div(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_div(rhs).unwrap()
}
}
impl<'a> DivAssign<&'a UInt> for UInt {
fn div_assign(&mut self, rhs: &'a UInt) {
self.checked_div_assign(rhs).unwrap();
}
}
impl<'a> Rem<&'a UInt> for UInt {
type Output = UInt;
fn rem(self, rhs: &'a UInt) -> Self::Output {
self.into_checked_rem(rhs).unwrap()
}
}
impl<'a, 'b> Rem<&'a UInt> for &'b UInt {
type Output = UInt;
fn rem(self, rhs: &'a UInt) -> Self::Output {
self.clone().into_checked_rem(rhs).unwrap()
}
}
impl<'a> RemAssign<&'a UInt> for UInt {
fn rem_assign(&mut self, rhs: &'a UInt) {
self.checked_rem_assign(rhs).unwrap();
}
}
use std::fmt;
impl fmt::Binary for UInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl fmt::Octal for UInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl fmt::LowerHex for UInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl fmt::UpperHex for UInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}