use apint::ApInt;
use traits::Width;
use digit::Bit;
use bitwidth::BitWidth;
use errors::Result;
use apint::{ShiftAmount};
use bitpos::{BitPos};
use uint::UInt;
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,
Neg,
Add,
Sub,
Mul,
Div,
Rem,
AddAssign,
SubAssign,
MulAssign,
DivAssign,
RemAssign,
Shl,
ShlAssign,
Shr,
ShrAssign
};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Int {
value: ApInt,
}
impl From<ApInt> for Int {
fn from(value: ApInt) -> Int {
Int { value }
}
}
impl Int {
pub fn into_apint(self) -> ApInt {
self.value
}
pub fn into_unsigned(self) -> UInt {
UInt::from(self.value)
}
}
impl Int {
pub fn from_bit<B>(bit: B) -> Int
where
B: Into<Bit>,
{
Int::from(ApInt::from_bit(bit))
}
#[inline]
pub fn from_i8(val: i8) -> Int {
Int::from(ApInt::from_i8(val))
}
#[inline]
pub fn from_i16(val: i16) -> Int {
Int::from(ApInt::from_i16(val))
}
#[inline]
pub fn from_i32(val: i32) -> Int {
Int::from(ApInt::from_i32(val))
}
#[inline]
pub fn from_i64(val: i64) -> Int {
Int::from(ApInt::from_i64(val))
}
pub fn from_i128(val: i128) -> Int {
Int::from(ApInt::from_i128(val))
}
pub fn zero(width: BitWidth) -> Int {
Int::from(ApInt::zero(width))
}
pub fn one(width: BitWidth) -> Int {
Int::from(ApInt::one(width))
}
pub fn all_unset(width: BitWidth) -> Int {
Int::zero(width)
}
pub fn all_set(width: BitWidth) -> Int {
Int::from(ApInt::all_set(width))
}
pub fn min_value(width: BitWidth) -> Int {
Int::from(ApInt::signed_min_value(width))
}
pub fn max_value(width: BitWidth) -> Int {
Int::from(ApInt::signed_max_value(width))
}
}
impl<B> From<B> for Int
where B: Into<Bit>
{
#[inline]
fn from(bit: B) -> Int {
Int::from_bit(bit)
}
}
impl From<i8> for Int {
fn from(val: i8) -> Int {
Int::from_i8(val)
}
}
impl From<i16> for Int {
fn from(val: i16) -> Int {
Int::from_i16(val)
}
}
impl From<i32> for Int {
fn from(val: i32) -> Int {
Int::from_i32(val)
}
}
impl From<i64> for Int {
fn from(val: i64) -> Int {
Int::from_i64(val)
}
}
impl From<i128> for Int {
fn from(val: i128) -> Int {
Int::from_i128(val)
}
}
macro_rules! impl_from_array_for_Int {
($n:expr) => {
impl From<[i64; $n]> for Int {
fn from(val: [i64; $n]) -> Int {
Int::from(ApInt::from(val))
}
}
}
}
impl_from_array_for_Int!(2); impl_from_array_for_Int!(3); impl_from_array_for_Int!(4); impl_from_array_for_Int!(5); impl_from_array_for_Int!(6); impl_from_array_for_Int!(7); impl_from_array_for_Int!(8); impl_from_array_for_Int!(16); impl_from_array_for_Int!(32);
impl Int {
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()
}
pub fn is_positive(&self) -> bool {
self.sign_bit() == Bit::Unset
}
pub fn is_negative(&self) -> bool {
!self.is_positive()
}
pub fn signum(&self) -> i8 {
if self.is_zero() {
return 0
}
if self.is_negative() {
return -1
}
1
}
pub fn into_abs(self) -> Int {
forward_mut_impl(self, Int::abs)
}
pub fn abs(&mut self) {
if self.is_negative() {
self.negate()
}
}
}
impl Int {
pub fn checked_lt(&self, rhs: &Int) -> Result<bool> {
self.value.checked_slt(&rhs.value)
}
#[inline]
pub fn checked_le(&self, rhs: &Int) -> Result<bool> {
self.value.checked_sle(&rhs.value)
}
#[inline]
pub fn checked_gt(&self, rhs: &Int) -> Result<bool> {
self.value.checked_sgt(&rhs.value)
}
#[inline]
pub fn checked_ge(&self, rhs: &Int) -> Result<bool> {
self.value.checked_sge(&rhs.value)
}
}
impl PartialOrd for Int {
fn partial_cmp(&self, rhs: &Int) -> 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: &Int) -> bool {
self.checked_lt(rhs).unwrap_or(false)
}
fn le(&self, rhs: &Int) -> bool {
self.checked_le(rhs).unwrap_or(false)
}
fn gt(&self, rhs: &Int) -> bool {
self.checked_gt(rhs).unwrap_or(false)
}
fn ge(&self, rhs: &Int) -> bool {
self.checked_ge(rhs).unwrap_or(false)
}
}
impl Int {
pub fn resize_to_bool(&self) -> bool {
self.value.resize_to_bool()
}
pub fn resize_to_i8(&self) -> i8 {
self.value.resize_to_i8()
}
pub fn resize_to_i16(&self) -> i16 {
self.value.resize_to_i16()
}
pub fn resize_to_i32(&self) -> i32 {
self.value.resize_to_i32()
}
pub fn resize_to_i64(&self) -> i64 {
self.value.resize_to_i64()
}
pub fn resize_to_i128(&self) -> i128 {
self.value.resize_to_i128()
}
}
impl Int {
pub fn try_to_bool(&self) -> Result<bool> {
self.value.try_to_bool()
}
pub fn try_to_i8(&self) -> Result<i8> {
self.value.try_to_i8()
}
pub fn try_to_i16(&self) -> Result<i16> {
self.value.try_to_i16()
}
pub fn try_to_i32(&self) -> Result<i32> {
self.value.try_to_i32()
}
pub fn try_to_i64(&self) -> Result<i64> {
self.value.try_to_i64()
}
pub fn try_to_i128(&self) -> Result<i128> {
self.value.try_to_i128()
}
}
impl Int {
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<Int>
where S: Into<ShiftAmount>
{
self.value.into_checked_shl(shift_amount).map(Int::from)
}
pub fn checked_shr_assign<S>(&mut self, shift_amount: S) -> Result<()>
where S: Into<ShiftAmount>
{
self.value.checked_ashr_assign(shift_amount)
}
pub fn into_checked_shr<S>(self, shift_amount: S) -> Result<Int>
where S: Into<ShiftAmount>
{
self.value.into_checked_ashr(shift_amount).map(Int::from)
}
}
impl<S> Shl<S> for Int
where S: Into<ShiftAmount>
{
type Output = Int;
fn shl(self, shift_amount: S) -> Self::Output {
self.into_checked_shl(shift_amount).unwrap()
}
}
impl<S> Shr<S> for Int
where S: Into<ShiftAmount>
{
type Output = Int;
fn shr(self, shift_amount: S) -> Self::Output {
self.into_checked_shr(shift_amount).unwrap()
}
}
impl<S> ShlAssign<S> for Int
where S: Into<ShiftAmount>
{
fn shl_assign(&mut self, shift_amount: S) {
self.checked_shl_assign(shift_amount).unwrap()
}
}
impl<S> ShrAssign<S> for Int
where S: Into<ShiftAmount>
{
fn shr_assign(&mut self, shift_amount: S) {
self.checked_shr_assign(shift_amount).unwrap()
}
}
#[cfg(feature = "rand_support")]
impl Int {
pub fn random_with_width(width: BitWidth) -> Int {
Int::from(ApInt::random_with_width(width))
}
pub fn random_with_width_using<R>(width: BitWidth, rng: &mut R) -> Int
where R: rand::Rng
{
Int::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 Int {
pub fn assign(&mut self, rhs: &Int) {
self.value.assign(&rhs.value)
}
pub fn strict_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.strict_assign(&rhs.value)
}
}
impl Int {
pub fn into_truncate<W>(self, target_width: W) -> Result<Int>
where W: Into<BitWidth>
{
try_forward_bin_mut_impl(self, target_width, Int::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<Int>
where W: Into<BitWidth>
{
try_forward_bin_mut_impl(self, target_width, Int::extend)
}
pub fn extend<W>(&mut self, target_width: W) -> Result<()>
where W: Into<BitWidth>
{
self.value.sign_extend(target_width)
}
pub fn into_resize<W>(self, target_width: W) -> Int
where W: Into<BitWidth>
{
forward_bin_mut_impl(self, target_width, Int::resize)
}
pub fn resize<W>(&mut self, target_width: W)
where W: Into<BitWidth>
{
self.value.sign_resize(target_width)
}
}
impl Int {
pub fn into_bitnot(self) -> Self {
forward_mut_impl(self, Int::bitnot)
}
pub fn bitnot(&mut self) {
self.value.bitnot()
}
pub fn into_checked_bitand(self, rhs: &Int) -> Result<Int> {
try_forward_bin_mut_impl(self, rhs, Int::checked_bitand_assign)
}
pub fn checked_bitand_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.checked_bitand_assign(&rhs.value)
}
pub fn into_checked_bitor(self, rhs: &Int) -> Result<Int> {
try_forward_bin_mut_impl(self, rhs, Int::checked_bitor_assign)
}
pub fn checked_bitor_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.checked_bitor_assign(&rhs.value)
}
pub fn into_checked_bitxor(self, rhs: &Int) -> Result<Int> {
try_forward_bin_mut_impl(self, rhs, Int::checked_bitxor_assign)
}
pub fn checked_bitxor_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.checked_bitxor_assign(&rhs.value)
}
}
impl Int {
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()
}
pub fn sign_bit(&self) -> Bit {
self.value.sign_bit()
}
pub fn set_sign_bit(&mut self) {
self.value.set_sign_bit()
}
pub fn unset_sign_bit(&mut self) {
self.value.unset_sign_bit()
}
pub fn flip_sign_bit(&mut self) {
self.value.flip_sign_bit()
}
}
impl Int {
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 Int {
type Output = Int;
fn not(self) -> Self::Output {
forward_mut_impl(self, Int::bitnot)
}
}
impl<'a> BitAnd<&'a Int> for Int {
type Output = Int;
fn bitand(self, rhs: &'a Int) -> Self::Output {
self.into_checked_bitand(rhs).unwrap()
}
}
impl<'a, 'b> BitAnd<&'a Int> for &'b Int {
type Output = Int;
fn bitand(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_bitand(rhs).unwrap()
}
}
impl<'a, 'b> BitAnd<&'a Int> for &'b mut Int {
type Output = Int;
fn bitand(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_bitand(rhs).unwrap()
}
}
impl<'a> BitOr<&'a Int> for Int {
type Output = Int;
fn bitor(self, rhs: &'a Int) -> Self::Output {
self.into_checked_bitor(rhs).unwrap()
}
}
impl<'a, 'b> BitOr<&'a Int> for &'b Int {
type Output = Int;
fn bitor(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_bitor(rhs).unwrap()
}
}
impl<'a, 'b> BitOr<&'a Int> for &'b mut Int {
type Output = Int;
fn bitor(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_bitor(rhs).unwrap()
}
}
impl<'a> BitXor<&'a Int> for Int {
type Output = Int;
fn bitxor(self, rhs: &'a Int) -> Self::Output {
self.into_checked_bitxor(rhs).unwrap()
}
}
impl<'a, 'b> BitXor<&'a Int> for &'b Int {
type Output = Int;
fn bitxor(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_bitxor(rhs).unwrap()
}
}
impl<'a, 'b> BitXor<&'a Int> for &'b mut Int {
type Output = Int;
fn bitxor(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_bitxor(rhs).unwrap()
}
}
impl<'a> BitAndAssign<&'a Int> for Int {
fn bitand_assign(&mut self, rhs: &'a Int) {
self.checked_bitand_assign(rhs).unwrap();
}
}
impl<'a> BitOrAssign<&'a Int> for Int {
fn bitor_assign(&mut self, rhs: &'a Int) {
self.checked_bitor_assign(rhs).unwrap();
}
}
impl<'a> BitXorAssign<&'a Int> for Int {
fn bitxor_assign(&mut self, rhs: &'a Int) {
self.checked_bitxor_assign(rhs).unwrap();
}
}
impl Int {
pub fn into_negate(self) -> Int {
forward_mut_impl(self, Int::negate)
}
pub fn negate(&mut self) {
self.value.negate()
}
pub fn into_checked_add(self, rhs: &Int) -> Result<Int> {
try_forward_bin_mut_impl(self, rhs, Int::checked_add_assign)
}
pub fn checked_add_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.checked_add_assign(&rhs.value)
}
pub fn into_checked_sub(self, rhs: &Int) -> Result<Int> {
try_forward_bin_mut_impl(self, rhs, Int::checked_sub_assign)
}
pub fn checked_sub_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.checked_sub_assign(&rhs.value)
}
pub fn into_checked_mul(self, rhs: &Int) -> Result<Int> {
try_forward_bin_mut_impl(self, rhs, Int::checked_mul_assign)
}
pub fn checked_mul_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.checked_mul_assign(&rhs.value)
}
pub fn into_checked_div(self, rhs: &Int) -> Result<Int> {
try_forward_bin_mut_impl(self, rhs, Int::checked_div_assign)
}
pub fn checked_div_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.checked_sdiv_assign(&rhs.value)
}
pub fn into_checked_rem(self, rhs: &Int) -> Result<Int> {
try_forward_bin_mut_impl(self, rhs, Int::checked_rem_assign)
}
pub fn checked_rem_assign(&mut self, rhs: &Int) -> Result<()> {
self.value.checked_srem_assign(&rhs.value)
}
}
impl Neg for Int {
type Output = Int;
fn neg(self) -> Self::Output {
self.into_negate()
}
}
impl<'a> Neg for &'a Int {
type Output = Int;
fn neg(self) -> Self::Output {
self.clone().into_negate()
}
}
impl<'a> Neg for &'a mut Int {
type Output = &'a mut Int;
fn neg(self) -> Self::Output {
self.negate();
self
}
}
impl<'a> Add<&'a Int> for Int {
type Output = Int;
fn add(self, rhs: &'a Int) -> Self::Output {
self.into_checked_add(rhs).unwrap()
}
}
impl<'a, 'b> Add<&'a Int> for &'b Int {
type Output = Int;
fn add(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_add(rhs).unwrap()
}
}
impl<'a> AddAssign<&'a Int> for Int {
fn add_assign(&mut self, rhs: &'a Int) {
self.checked_add_assign(rhs).unwrap()
}
}
impl<'a> Sub<&'a Int> for Int {
type Output = Int;
fn sub(self, rhs: &'a Int) -> Self::Output {
self.into_checked_sub(rhs).unwrap()
}
}
impl<'a, 'b> Sub<&'a Int> for &'b Int {
type Output = Int;
fn sub(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_sub(rhs).unwrap()
}
}
impl<'a> SubAssign<&'a Int> for Int {
fn sub_assign(&mut self, rhs: &'a Int) {
self.checked_sub_assign(rhs).unwrap()
}
}
impl<'a> Mul<&'a Int> for Int {
type Output = Int;
fn mul(self, rhs: &'a Int) -> Self::Output {
self.into_checked_mul(rhs).unwrap()
}
}
impl<'a, 'b> Mul<&'a Int> for &'b Int {
type Output = Int;
fn mul(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_mul(rhs).unwrap()
}
}
impl<'a> MulAssign<&'a Int> for Int {
fn mul_assign(&mut self, rhs: &'a Int) {
self.checked_mul_assign(rhs).unwrap();
}
}
impl<'a> Div<&'a Int> for Int {
type Output = Int;
fn div(self, rhs: &'a Int) -> Self::Output {
self.into_checked_div(rhs).unwrap()
}
}
impl<'a, 'b> Div<&'a Int> for &'b Int {
type Output = Int;
fn div(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_div(rhs).unwrap()
}
}
impl<'a> DivAssign<&'a Int> for Int {
fn div_assign(&mut self, rhs: &'a Int) {
self.checked_div_assign(rhs).unwrap();
}
}
impl<'a> Rem<&'a Int> for Int {
type Output = Int;
fn rem(self, rhs: &'a Int) -> Self::Output {
self.into_checked_rem(rhs).unwrap()
}
}
impl<'a, 'b> Rem<&'a Int> for &'b Int {
type Output = Int;
fn rem(self, rhs: &'a Int) -> Self::Output {
self.clone().into_checked_rem(rhs).unwrap()
}
}
impl<'a> RemAssign<&'a Int> for Int {
fn rem_assign(&mut self, rhs: &'a Int) {
self.checked_rem_assign(rhs).unwrap();
}
}
use std::fmt;
impl fmt::Binary for Int {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl fmt::Octal for Int {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl fmt::LowerHex for Int {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl fmt::UpperHex for Int {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}