twibint 0.3.2

Crate for arithmetic on arbitrarily large integers. Provides Python bindings as well.
Documentation
use core::ops::{Div, DivAssign, Rem, RemAssign};

use crate::errors::DivisionError;
use crate::traits::{Digit, DivisionResult, DoubleDigit, RemDiv};
use crate::BigUint;

use crate::biguint::ops::div;

impl<T: Digit> RemDiv<T> for BigUint<T> {
    type DivOutput = BigUint<T>;
    type RemOutput = T;
    fn rem_div(&self, other: &T) -> DivisionResult<(BigUint<T>, T)> {
        if *other == T::ZERO {
            return Err(DivisionError::DivisionByZero);
        }

        let other_64 = other.to_double();
        let mut msb = T::Double::ZERO;
        let mut div: T::Double;

        let mut ret = BigUint::<T>::new(T::ZERO);
        for idx in (0..self.val.len()).rev() {
            let lsb = self.val[idx].to_double();

            let current = (msb << T::NB_BITS) | lsb;
            (div, msb) = (current / other_64, current % other_64);

            ret += BigUint::<T>::from(div.split()) << (T::NB_BITS * idx);
        }

        ret.remove_leading_zeros();
        Ok((ret, msb.truncate_upper()))
    }

    fn rem(&self, other: &T) -> DivisionResult<T> {
        if *other == T::ZERO {
            return Err(DivisionError::DivisionByZero);
        }
        let other_64 = other.to_double();
        let mut msb = T::Double::ZERO;

        for val in self.val.iter().rev() {
            let current = (msb << T::NB_BITS) | val.to_double();
            msb = current % other_64;
        }

        Ok(msb.truncate_upper())
    }
}

impl<T: Digit> RemAssign<T> for BigUint<T> {
    fn rem_assign(&mut self, other: T) {
        let value = &*self % other;
        *self = value;
    }
}
impl<T: Digit> RemAssign<&T> for BigUint<T> {
    fn rem_assign(&mut self, other: &T) {
        let value = &*self % *other;
        *self = value;
    }
}
impl<T: Digit> Rem<T> for BigUint<T> {
    type Output = BigUint<T>;
    fn rem(self, other: T) -> Self::Output {
        BigUint::new(RemDiv::rem(&self, &other).unwrap())
    }
}
impl<T: Digit> Rem<T> for &BigUint<T> {
    type Output = BigUint<T>;
    fn rem(self, other: T) -> Self::Output {
        BigUint::new(RemDiv::rem(self, &other).unwrap())
    }
}
impl<T: Digit> Rem<&T> for BigUint<T> {
    type Output = BigUint<T>;
    fn rem(self, other: &T) -> Self::Output {
        BigUint::new(RemDiv::rem(&self, other).unwrap())
    }
}
impl<T: Digit> Rem<&T> for &BigUint<T> {
    type Output = BigUint<T>;
    fn rem(self, other: &T) -> Self::Output {
        BigUint::new(RemDiv::rem(self, other).unwrap())
    }
}

impl<T: Digit> DivAssign<T> for BigUint<T> {
    fn div_assign(&mut self, other: T) {
        *self = &*self / other;
    }
}
impl<T: Digit> DivAssign<&T> for BigUint<T> {
    fn div_assign(&mut self, other: &T) {
        *self = &*self / *other;
    }
}
impl<T: Digit> Div<T> for &BigUint<T> {
    type Output = BigUint<T>;
    fn div(self, other: T) -> BigUint<T> {
        RemDiv::div(self, &other).unwrap()
    }
}
impl<T: Digit> Div<&T> for &BigUint<T> {
    type Output = BigUint<T>;
    fn div(self, other: &T) -> BigUint<T> {
        RemDiv::div(self, other).unwrap()
    }
}
impl<T: Digit> Div<T> for BigUint<T> {
    type Output = BigUint<T>;
    fn div(self, other: T) -> BigUint<T> {
        RemDiv::div(&self, &other).unwrap()
    }
}
impl<T: Digit> Div<&T> for BigUint<T> {
    type Output = BigUint<T>;
    fn div(self, other: &T) -> BigUint<T> {
        RemDiv::div(&self, other).unwrap()
    }
}

impl<T: Digit> RemDiv<BigUint<T>> for BigUint<T> {
    type DivOutput = BigUint<T>;
    type RemOutput = BigUint<T>;
    fn rem_div(&self, other: &BigUint<T>) -> DivisionResult<(BigUint<T>, BigUint<T>)> {
        div(self, other)
    }
}
impl<T: Digit> RemAssign<&BigUint<T>> for BigUint<T> {
    fn rem_assign(&mut self, other: &BigUint<T>) {
        *self = &*self % other;
    }
}
impl<T: Digit> RemAssign<BigUint<T>> for BigUint<T> {
    fn rem_assign(&mut self, other: BigUint<T>) {
        *self = &*self % &other;
    }
}
impl<T: Digit> Rem<&BigUint<T>> for &BigUint<T> {
    type Output = BigUint<T>;
    fn rem(self, other: &BigUint<T>) -> BigUint<T> {
        RemDiv::rem(self, other).unwrap()
    }
}
impl<T: Digit> Rem<&BigUint<T>> for BigUint<T> {
    type Output = BigUint<T>;
    fn rem(self, other: &BigUint<T>) -> BigUint<T> {
        RemDiv::rem(&self, other).unwrap()
    }
}
impl<T: Digit> Rem<BigUint<T>> for BigUint<T> {
    type Output = BigUint<T>;
    fn rem(self, other: BigUint<T>) -> BigUint<T> {
        RemDiv::rem(&self, &other).unwrap()
    }
}
impl<T: Digit> Rem<BigUint<T>> for &BigUint<T> {
    type Output = BigUint<T>;
    fn rem(self, other: BigUint<T>) -> BigUint<T> {
        RemDiv::rem(self, &other).unwrap()
    }
}
impl<T: Digit> DivAssign<BigUint<T>> for BigUint<T> {
    fn div_assign(&mut self, other: BigUint<T>) {
        *self = &*self / &other;
    }
}
impl<T: Digit> DivAssign<&BigUint<T>> for BigUint<T> {
    fn div_assign(&mut self, other: &BigUint<T>) {
        *self = &*self / other;
    }
}
impl<T: Digit> Div<&BigUint<T>> for &BigUint<T> {
    type Output = BigUint<T>;
    fn div(self, other: &BigUint<T>) -> BigUint<T> {
        RemDiv::div(self, other).unwrap()
    }
}
impl<T: Digit> Div<BigUint<T>> for BigUint<T> {
    type Output = BigUint<T>;
    fn div(self, other: BigUint<T>) -> BigUint<T> {
        RemDiv::div(&self, &other).unwrap()
    }
}
impl<T: Digit> Div<BigUint<T>> for &BigUint<T> {
    type Output = BigUint<T>;
    fn div(self, other: BigUint<T>) -> BigUint<T> {
        RemDiv::div(self, &other).unwrap()
    }
}
impl<T: Digit> Div<&BigUint<T>> for BigUint<T> {
    type Output = BigUint<T>;
    fn div(self, other: &BigUint<T>) -> BigUint<T> {
        RemDiv::div(&self, other).unwrap()
    }
}