use std::ops::{Add, Mul, Sub};
use traiter::numbers::{
CheckedDivRemEuclid, CheckedRemEuclidInv, One, Signed, Unitary, Zero,
Zeroable,
};
use super::types::BigInt;
impl<Digit, const DIGIT_BITNESS: usize> CheckedRemEuclidInv
for BigInt<Digit, DIGIT_BITNESS>
where
for<'a> Self: CheckedRemEuclidInv<&'a Self, Output = Option<Self>>,
{
type Output = Option<Self>;
fn checked_rem_euclid_inv(self, divisor: Self) -> Self::Output {
self.checked_rem_euclid_inv(&divisor)
}
}
impl<Digit, const DIGIT_BITNESS: usize> CheckedRemEuclidInv<&Self>
for BigInt<Digit, DIGIT_BITNESS>
where
for<'a> &'a Self: Add<Self, Output = Self>
+ CheckedDivRemEuclid<Output = Option<(Self, Self)>>
+ Signed
+ Unitary,
for<'a> Self: Clone + Mul<&'a Self, Output = Self> + Sub<Output = Self>,
Self: One + Zero,
{
type Output = Option<Self>;
fn checked_rem_euclid_inv(self, divisor: &Self) -> Self::Output {
let mut candidate = Self::zero();
let mut result = Self::one();
let mut step_dividend = self;
let mut step_divisor = divisor.clone();
while !(&step_divisor).is_zero() {
let (quotient, remainder) = unsafe {
step_dividend
.checked_div_rem_euclid(&step_divisor)
.unwrap_unchecked()
};
step_dividend = step_divisor;
step_divisor = remainder;
(candidate, result) = (result - quotient * &candidate, candidate);
}
if step_dividend.is_one() {
Some(if (&result).is_negative() {
divisor + result
} else {
result
})
} else {
None
}
}
}
impl<Digit, const DIGIT_BITNESS: usize>
CheckedRemEuclidInv<BigInt<Digit, DIGIT_BITNESS>>
for &BigInt<Digit, DIGIT_BITNESS>
where
for<'a> BigInt<Digit, DIGIT_BITNESS>: CheckedRemEuclidInv<
&'a BigInt<Digit, DIGIT_BITNESS>,
Output = Option<BigInt<Digit, DIGIT_BITNESS>>,
> + Clone,
{
type Output = Option<BigInt<Digit, DIGIT_BITNESS>>;
fn checked_rem_euclid_inv(
self,
divisor: BigInt<Digit, DIGIT_BITNESS>,
) -> Self::Output {
self.clone().checked_rem_euclid_inv(&divisor)
}
}
impl<Digit, const DIGIT_BITNESS: usize> CheckedRemEuclidInv
for &BigInt<Digit, DIGIT_BITNESS>
where
for<'a> BigInt<Digit, DIGIT_BITNESS>: CheckedRemEuclidInv<
&'a BigInt<Digit, DIGIT_BITNESS>,
Output = Option<BigInt<Digit, DIGIT_BITNESS>>,
> + Clone,
{
type Output = Option<BigInt<Digit, DIGIT_BITNESS>>;
fn checked_rem_euclid_inv(self, divisor: Self) -> Self::Output {
self.clone().checked_rem_euclid_inv(divisor)
}
}