use std::ops::Add;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Neg;
use std::ops::Rem;
use std::ops::Sub;
use derive_more::Deref;
use derive_more::DerefMut;
use derive_more::From;
use num_bigint::BigInt;
use num_integer::Integer;
use num_traits::Num;
use crate::type_::bit::Bit;
#[derive(Clone, Default, PartialEq, Eq, Hash, From, Deref, DerefMut)]
#[from(forward)]
pub struct Int(BigInt);
impl Int {
pub(crate) fn new(int: BigInt) -> Self {
Self(int)
}
pub(crate) fn unwrap(self) -> BigInt {
self.0
}
pub fn from_str_radix(s: &str, radix: u32) -> Option<Self> {
let i = BigInt::from_str_radix(s, radix).ok()?;
Some(Self(i))
}
#[expect(clippy::should_implement_trait)]
pub fn add(self, other: Int) -> Int {
Int(self.0.add(other.0))
}
pub fn subtract(self, other: Int) -> Int {
Int(self.0.sub(other.0))
}
pub fn multiply(self, other: Int) -> Int {
Int(self.0.mul(other.0))
}
pub fn divide(self, other: Int) -> Int {
Int(self.0.div(other.0))
}
pub fn remainder(self, other: Int) -> Int {
Int(self.0.rem(other.0))
}
pub fn divide_remainder(self, other: Int) -> (Int, Int) {
let (quotient, rem) = self.0.div_rem(&other.0);
(Int(quotient), Int(rem))
}
pub fn less(&self, other: &Int) -> Bit {
Bit::from(self.0.lt(&other.0))
}
pub fn less_equal(&self, other: &Int) -> Bit {
Bit::from(self.0.le(&other.0))
}
pub fn greater(&self, other: &Int) -> Bit {
Bit::from(self.0.gt(&other.0))
}
pub fn greater_equal(&self, other: &Int) -> Bit {
Bit::from(self.0.ge(&other.0))
}
pub fn less_greater(&self, other: &Int) -> Bit {
Bit::from(self.0.ne(&other.0))
}
}
impl Neg for Int {
type Output = Int;
fn neg(self) -> Int {
Int(-self.0)
}
}