use std::fmt;
use rustc_macros::{Decodable, Encodable};
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Encodable, Decodable, PartialOrd, Ord)]
pub struct BigInt {
sign: Sign,
val: u128,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, PartialOrd, Ord)]
enum Sign {
Negative,
NonNegative,
}
impl BigInt {
pub const ZERO: BigInt = BigInt { sign: Sign::NonNegative, val: 0 };
pub const ONE: BigInt = BigInt { sign: Sign::NonNegative, val: 1 };
pub fn int_min(bit_width: u32) -> BigInt {
BigInt { sign: Sign::Negative, val: 1u128 << (bit_width - 1) }
}
pub fn int_max(bit_width: u32) -> BigInt {
(i128::MAX >> (128 - bit_width)).into()
}
pub fn uint_max(bit_width: u32) -> BigInt {
(u128::MAX >> (128 - bit_width)).into()
}
}
impl From<usize> for BigInt {
fn from(val: usize) -> Self {
BigInt { sign: Sign::NonNegative, val: val as u128 }
}
}
impl From<u128> for BigInt {
fn from(val: u128) -> Self {
BigInt { sign: Sign::NonNegative, val }
}
}
impl From<i128> for BigInt {
fn from(val: i128) -> Self {
let sign = if val < 0 { Sign::Negative } else { Sign::NonNegative };
BigInt { sign, val: val.unsigned_abs() }
}
}
impl From<i32> for BigInt {
fn from(val: i32) -> Self {
if val < 0 {
BigInt { sign: Sign::Negative, val: -(val as i64) as u128 }
} else {
BigInt { sign: Sign::NonNegative, val: val as u128 }
}
}
}
impl From<u32> for BigInt {
fn from(val: u32) -> Self {
BigInt { sign: Sign::NonNegative, val: val as u128 }
}
}
impl liquid_fixpoint::FixpointFmt for BigInt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.sign {
Sign::NonNegative => write!(f, "{}", self.val),
Sign::Negative => write!(f, "(- {})", self.val),
}
}
}
impl fmt::Display for BigInt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.sign {
Sign::NonNegative => write!(f, "{}", self.val),
Sign::Negative => write!(f, "-{}", self.val),
}
}
}