use num_traits::{ConstZero, Num, One, Signed, Unsigned, Zero};
use oxinum_core::Sign;
use super::int::BigInt;
use super::uint::BigUint;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseBigUintError(String);
impl std::fmt::Display for ParseBigUintError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ParseBigUintError: {}", self.0)
}
}
impl std::error::Error for ParseBigUintError {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseBigIntError(String);
impl std::fmt::Display for ParseBigIntError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ParseBigIntError: {}", self.0)
}
}
impl std::error::Error for ParseBigIntError {}
impl Zero for BigUint {
#[inline]
fn zero() -> Self {
BigUint::zero()
}
#[inline]
fn is_zero(&self) -> bool {
BigUint::is_zero(self)
}
}
impl One for BigUint {
#[inline]
fn one() -> Self {
BigUint::one()
}
#[inline]
fn is_one(&self) -> bool {
BigUint::is_one(self)
}
}
impl ConstZero for BigUint {
const ZERO: Self = BigUint::ZERO;
}
impl Num for BigUint {
type FromStrRadixErr = ParseBigUintError;
fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
BigUint::from_str_radix(s, radix).map_err(|e| ParseBigUintError(e.to_string()))
}
}
impl Unsigned for BigUint {}
impl Zero for BigInt {
#[inline]
fn zero() -> Self {
BigInt::zero()
}
#[inline]
fn is_zero(&self) -> bool {
BigInt::is_zero(self)
}
}
impl One for BigInt {
#[inline]
fn one() -> Self {
BigInt::one()
}
#[inline]
fn is_one(&self) -> bool {
BigInt::is_one(self)
}
}
impl ConstZero for BigInt {
const ZERO: Self = BigInt::ZERO;
}
impl Num for BigInt {
type FromStrRadixErr = ParseBigIntError;
fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
let (neg, rest) = if let Some(r) = s.strip_prefix('-') {
(true, r)
} else if let Some(r) = s.strip_prefix('+') {
(false, r)
} else {
(false, s)
};
BigUint::from_str_radix(rest, radix)
.map(|mag| {
if neg && !mag.is_zero() {
BigInt::from_parts(Sign::Negative, mag)
} else {
BigInt::from_parts(Sign::Positive, mag)
}
})
.map_err(|e| ParseBigIntError(e.to_string()))
}
}
impl Signed for BigInt {
#[inline]
fn abs(&self) -> Self {
BigInt::abs(self)
}
fn abs_sub(&self, other: &Self) -> Self {
if self > other {
self.clone() - other.clone()
} else {
BigInt::zero()
}
}
fn signum(&self) -> Self {
if self.is_zero() {
BigInt::zero()
} else if BigInt::is_negative(self) {
-BigInt::one()
} else {
BigInt::one()
}
}
#[inline]
fn is_positive(&self) -> bool {
BigInt::is_positive(self)
}
#[inline]
fn is_negative(&self) -> bool {
BigInt::is_negative(self)
}
}