use crate::number::{
instances::ratio::Rational,
traits::{integral::Integral, number::Number, one::One, real::Real, zero::Zero},
utils::i8_div_mod,
};
#[derive(Clone, PartialEq, Eq)]
pub struct Integer {
pub sign: bool,
inner: Vec<u8>,
}
impl Integer {
pub fn of(sign: bool, digits: &[u8]) -> Option<Self> {
let mut inner = digits
.iter()
.skip_while(|&&digit| digit == 0u8)
.map(|&digit| digit)
.collect::<Vec<u8>>();
if inner.is_empty() {
Some(Self::zero())
} else {
inner.reverse();
if inner.iter().all(|&digit| digit < 10u8) {
Some(Self { sign, inner })
} else {
eprintln!(
concat!(
"Error[Integer::of]: ",
"Each digit of the integer ",
"should be within the range [0, 9] ({:?})."
),
digits,
);
None
}
}
}
pub fn of_str(integer_number: &str) -> Option<Self> {
std::str::FromStr::from_str(integer_number).ok()
}
pub fn digits(&self) -> Vec<u8> { self.inner.iter().rev().cloned().collect::<Vec<u8>>() }
fn integer_add(self, rhs: Self) -> Self {
if self.is_zero() {
rhs
} else if rhs.is_zero() {
self
} else {
let expect_capacity = self.inner.len().max(rhs.inner.len()) + 1usize;
let mut sum: Vec<u8> = vec![0u8; expect_capacity];
let mut carry = 0u8;
for idx in 0..expect_capacity {
let factor = self.inner.get(idx).map_or(0u8, |&digit| digit)
+ rhs.inner.get(idx).map_or(0u8, |&digit| digit)
+ carry;
sum[idx] = factor % 10;
carry = factor / 10;
}
sum.reverse();
Self::of(true, &sum).expect(
"Error[Integer::integer_add]: Each digit should be within the range [1, 9].",
)
}
}
fn integer_sub(self, rhs: Self) -> Self {
if self.is_zero() {
-rhs
} else if rhs.is_zero() {
self
} else {
let expect_capacity = self.inner.len().max(rhs.inner.len());
let mut diff: Vec<i8> = vec![0i8; expect_capacity];
let (mut sign, subtracted, subtracting) = if self > rhs {
(true, self, rhs)
} else {
(false, rhs, self)
};
let mut carry = 0i8;
for idx in 0..expect_capacity {
let factor = subtracted.inner.get(idx).map_or(0i8, |&digit| digit as i8)
- subtracting.inner.get(idx).map_or(0i8, |&digit| digit as i8)
+ carry;
(carry, diff[idx]) = i8_div_mod(factor, 10i8);
}
sign = (carry == 0i8) == sign;
let digits = diff
.iter()
.rev() .map(|&digit| digit as u8)
.collect::<Vec<u8>>();
Self::of(sign, &digits).expect(
"Error[Integer::integer_sub]: Each digit should be within the range [1, 9].",
)
}
}
fn integer_cmp(&self, rhs: &Integer) -> std::cmp::Ordering {
if self.inner.len() > rhs.inner.len() {
std::cmp::Ordering::Greater
} else if self.inner.len() < rhs.inner.len() {
std::cmp::Ordering::Less
} else {
for (lhs_digit, rhs_digit) in self.digits().iter().zip(rhs.digits().iter()) {
if lhs_digit > rhs_digit {
return std::cmp::Ordering::Greater;
} else if lhs_digit < rhs_digit {
return std::cmp::Ordering::Less;
}
}
std::cmp::Ordering::Equal
}
}
}
impl Zero for Integer {
fn zero() -> Self {
Self {
sign: true,
inner: vec![0u8],
}
}
fn is_zero(&self) -> bool { self.inner.is_empty() || self.inner.iter().all(|&e| e == 0u8) }
}
impl One for Integer {
fn one() -> Self {
Self {
sign: true,
inner: vec![1u8],
}
}
fn is_one(&self) -> bool {
(!self.inner.is_empty()) && (self
.inner
.iter()
.rev() .skip_while(|&&e| e == 0)
.collect::<Vec<&u8>>()
== vec![&1u8]) }
}
impl std::default::Default for Integer {
fn default() -> Self { Self::zero() }
}
impl std::cmp::PartialOrd for Integer {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
if self.is_zero() && other.is_zero() {
Some(std::cmp::Ordering::Equal)
} else {
match (self.sign, other.sign) {
(true, false) => Some(std::cmp::Ordering::Greater),
(false, true) => Some(std::cmp::Ordering::Less),
(true, true) => Some(self.integer_cmp(other)),
(false, false) => Some(other.integer_cmp(self)),
}
}
}
}
impl std::cmp::Ord for Integer {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other)
.expect("Error[Integer::cmp]: Integer should be ordered.")
}
}
impl std::ops::Neg for Integer {
type Output = Self;
fn neg(self) -> Self::Output {
Self {
sign: if self.is_zero() { true } else { !self.sign },
inner: self.inner,
}
}
}
impl std::ops::Add for Integer {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
match (self.sign, rhs.sign) {
(true, false) => self.integer_sub(rhs.absolute_value()),
(false, true) => rhs.integer_sub(self.absolute_value()),
(true, true) => self.integer_add(rhs),
(false, false) => -self.absolute_value().integer_add(rhs.absolute_value()),
}
}
}
impl std::ops::Sub for Integer {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output { self + (-rhs) }
}
impl std::ops::Mul for Integer {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
if self.is_zero() || rhs.is_zero() {
Self::zero()
} else {
let expect_capacity = self.inner.len() + rhs.inner.len();
let mut product_layers = vec![vec![0u8; expect_capacity]; rhs.inner.len()];
for (idx, &digit) in rhs.inner.iter().enumerate() {
for (loc, &p) in self.inner.iter().enumerate() {
product_layers[idx][loc + idx] = digit * p;
}
}
let mut product = vec![0u8; expect_capacity];
let mut carry = 0u8;
for idx in 0usize..expect_capacity {
let factor = product_layers.iter().map(|layer| layer[idx]).sum::<u8>() + carry;
product[idx] = factor % 10u8;
carry = factor / 10u8;
}
product.reverse();
Self::of(self.sign == rhs.sign, &product)
.expect("Error[Integer::mul]: Each digit should be within the range [1, 9].")
}
}
}
impl Number for Integer {
fn absolute_value(&self) -> Self {
Self {
sign: true,
inner: self.inner.clone(),
}
}
fn sign_number(&self) -> Self {
if self.is_zero() {
Self::zero()
} else if self.sign {
Self::one()
} else {
-Self::one()
}
}
fn from_integer(integer_number: Integer) -> Self { integer_number }
}
impl Real for Integer {
fn to_rational(self) -> Rational { Rational::of(self, Self::one()) }
}
impl Integral for Integer {
fn quot_rem(self, rhs: Self) -> (Self, Self) {
if self == rhs {
(Self::one(), Self::zero())
} else if rhs.is_zero() {
panic!("Error[Integer::quot_rem]: divide by zero");
} else if self.is_zero() {
(Self::zero(), Self::zero())
} else if rhs.absolute_value().is_one() {
(if rhs.is_one() { self } else { -self }, Self::zero())
} else {
let self_digits = self.digits();
let rhs_abs = rhs.absolute_value();
let mut head = 0usize;
let mut expand = 1usize;
let mut quot_digits = Vec::<u8>::new();
let mut rem_digits = Vec::<u8>::new();
while head + expand <= self_digits.len() {
let mut rem_buffer = rem_digits.clone();
rem_buffer.extend(self_digits[head..(head + expand)].iter());
let buffer = Self::of(true, &rem_buffer).expect(&format!(
"Error[Integer::quot_rem]: ({}, {}) is out of bounds.",
head,
head + expand,
));
if buffer < rhs_abs {
quot_digits.push(0u8);
if head + expand == self_digits.len() {
rem_digits = buffer.digits();
break;
} else {
expand = expand + 1;
}
} else {
let mut factor = Self::one();
while (factor.clone() + Self::one()) * rhs_abs.clone() <= buffer {
factor = factor + Self::one();
}
rem_digits = (buffer - factor.clone() * rhs_abs.clone()).digits();
quot_digits.push(factor.inner[0]);
head = head + expand;
expand = 1usize;
}
}
Self::of(self.sign == rhs.sign, "_digits)
.zip(Self::of(self.sign, &rem_digits))
.expect(concat!(
"Error[Integer::quot_rem]: ",
"Each digit should be within the range [1, 9]."
))
}
}
fn div_mod(self, rhs: Self) -> (Self, Self) {
let (quot, rem) = self.clone().quot_rem(rhs.clone());
if rem.is_zero() || (quot >= Self::zero() && rem > Self::zero()) {
(quot, rem)
} else {
let div = quot - Self::one();
(div.clone(), self - div * rhs)
}
}
fn to_integer(self) -> Integer { self }
}
impl std::fmt::Display for Integer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}{}",
if self.sign { "" } else { "-" },
self.inner
.iter()
.rev()
.map(|d| (d + ('0' as u8)) as char)
.collect::<String>()
)
}
}
impl std::fmt::Debug for Integer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}{}",
if self.sign { "+" } else { "-" },
self.inner
.iter()
.rev()
.map(|d| (d + ('0' as u8)) as char)
.collect::<String>()
)
}
}
impl std::str::FromStr for Integer {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let trimmed_s = s.trim();
regex::Regex::new(r"(?<sign>[+-]?)(?<digits>[0-9_]+)")
.ok()
.and_then(|matcher| {
let matched_captures = matcher.captures(trimmed_s);
if let Some(captures) = matched_captures {
let sign_str = &captures["sign"];
let sign = sign_str.is_empty() || sign_str == "+";
let digits_str = &captures["digits"];
let digits = digits_str
.chars()
.filter(|digit| digit.is_ascii_digit())
.map(|digit| (digit as u8) - ('0' as u8))
.collect::<Vec<u8>>();
Self::of(sign, &digits)
} else {
None
}
})
.ok_or_else(|| {
eprintln!(
"Error[Ineteger::from_str]: Failed to parse {} from the string.",
trimmed_s
)
})
}
}