use crate::{
add::add_same_len_in_place,
buffer::Buffer,
ibig::IBig,
mul::sub_mul_word_same_len_in_place,
primitive::{double_word, extend_word, split_double_word, Word},
sign::Abs,
ubig::{Repr::*, UBig},
};
use core::{
mem,
ops::{Div, DivAssign, Rem, RemAssign},
};
pub trait DivRem<Rhs = Self> {
type OutputDiv;
type OutputRem;
fn div_rem(self, rhs: Rhs) -> (Self::OutputDiv, Self::OutputRem);
}
pub trait DivEuclid<Rhs = Self> {
type Output;
fn div_euclid(self, rhs: Rhs) -> Self::Output;
}
pub trait RemEuclid<Rhs = Self> {
type Output;
fn rem_euclid(self, rhs: Rhs) -> Self::Output;
}
pub trait DivRemEuclid<Rhs = Self> {
type OutputDiv;
type OutputRem;
fn div_rem_euclid(self, rhs: Rhs) -> (Self::OutputDiv, Self::OutputRem);
}
impl Div<UBig> for UBig {
type Output = UBig;
#[inline]
fn div(self, rhs: UBig) -> UBig {
match (self.into_repr(), rhs.into_repr()) {
(Small(word0), Small(word1)) => UBig::div_word(word0, word1),
(Small(_), Large(_)) => UBig::from_word(0),
(Large(buffer0), Small(word1)) => UBig::div_large_word(buffer0, word1),
(Large(buffer0), Large(buffer1)) => {
if buffer0.len() >= buffer1.len() {
UBig::div_large(buffer0, buffer1)
} else {
UBig::from_word(0)
}
}
}
}
}
impl Div<&UBig> for UBig {
type Output = UBig;
#[inline]
fn div(self, rhs: &UBig) -> UBig {
match self.into_repr() {
Small(word0) => match rhs.repr() {
Small(word1) => UBig::div_word(word0, *word1),
Large(_) => UBig::from_word(0),
},
Large(buffer0) => match rhs.repr() {
Small(word1) => UBig::div_large_word(buffer0, *word1),
Large(buffer1) => {
if buffer0.len() >= buffer1.len() {
UBig::div_large(buffer0, buffer1.clone())
} else {
UBig::from_word(0)
}
}
},
}
}
}
impl Div<UBig> for &UBig {
type Output = UBig;
#[inline]
fn div(self, rhs: UBig) -> UBig {
match self.repr() {
Small(word0) => match rhs.into_repr() {
Small(word1) => UBig::div_word(*word0, word1),
Large(_) => UBig::from_word(0),
},
Large(buffer0) => match rhs.into_repr() {
Small(word1) => UBig::div_large_word(buffer0.clone(), word1),
Large(buffer1) => {
if buffer0.len() >= buffer1.len() {
UBig::div_large(buffer0.clone(), buffer1)
} else {
UBig::from_word(0)
}
}
},
}
}
}
impl Div<&UBig> for &UBig {
type Output = UBig;
#[inline]
fn div(self, rhs: &UBig) -> UBig {
match (self.repr(), rhs.repr()) {
(Small(word0), Small(word1)) => UBig::div_word(*word0, *word1),
(Small(_), Large(_)) => UBig::from_word(0),
(Large(buffer0), Small(word1)) => UBig::div_large_word(buffer0.clone(), *word1),
(Large(buffer0), Large(buffer1)) => {
if buffer0.len() >= buffer1.len() {
UBig::div_large(buffer0.clone(), buffer1.clone())
} else {
UBig::from_word(0)
}
}
}
}
}
impl DivAssign<UBig> for UBig {
#[inline]
fn div_assign(&mut self, rhs: UBig) {
*self = mem::take(self) / rhs;
}
}
impl DivAssign<&UBig> for UBig {
#[inline]
fn div_assign(&mut self, rhs: &UBig) {
*self = mem::take(self) / rhs;
}
}
impl Rem<UBig> for UBig {
type Output = UBig;
#[inline]
fn rem(self, rhs: UBig) -> UBig {
match (self.into_repr(), rhs.into_repr()) {
(Small(word0), Small(word1)) => UBig::rem_word(word0, word1),
(Small(word0), Large(_)) => UBig::from_word(word0),
(Large(buffer0), Small(word1)) => UBig::rem_large_word(&buffer0, word1),
(Large(buffer0), Large(buffer1)) => {
if buffer0.len() >= buffer1.len() {
UBig::rem_large(buffer0, buffer1)
} else {
buffer0.into()
}
}
}
}
}
impl Rem<&UBig> for UBig {
type Output = UBig;
#[inline]
fn rem(self, rhs: &UBig) -> UBig {
match self.into_repr() {
Small(word0) => match rhs.repr() {
Small(word1) => UBig::rem_word(word0, *word1),
Large(_) => UBig::from_word(word0),
},
Large(buffer0) => match rhs.repr() {
Small(word1) => UBig::rem_large_word(&buffer0, *word1),
Large(buffer1) => {
if buffer0.len() >= buffer1.len() {
UBig::rem_large(buffer0, buffer1.clone())
} else {
buffer0.into()
}
}
},
}
}
}
impl Rem<UBig> for &UBig {
type Output = UBig;
#[inline]
fn rem(self, rhs: UBig) -> UBig {
match self.repr() {
Small(word0) => match rhs.into_repr() {
Small(word1) => UBig::rem_word(*word0, word1),
Large(_) => UBig::from_word(*word0),
},
Large(buffer0) => match rhs.into_repr() {
Small(word1) => UBig::rem_large_word(buffer0, word1),
Large(mut buffer1) => {
if buffer0.len() >= buffer1.len() {
UBig::rem_large(buffer0.clone(), buffer1)
} else {
buffer1.resizing_clone_from(buffer0);
buffer1.into()
}
}
},
}
}
}
impl Rem<&UBig> for &UBig {
type Output = UBig;
#[inline]
fn rem(self, rhs: &UBig) -> UBig {
match (self.repr(), rhs.repr()) {
(Small(word0), Small(word1)) => UBig::rem_word(*word0, *word1),
(Small(word0), Large(_)) => UBig::from_word(*word0),
(Large(buffer0), Small(word1)) => UBig::rem_large_word(buffer0, *word1),
(Large(buffer0), Large(buffer1)) => {
if buffer0.len() >= buffer1.len() {
UBig::rem_large(buffer0.clone(), buffer1.clone())
} else {
self.clone()
}
}
}
}
}
impl RemAssign<UBig> for UBig {
#[inline]
fn rem_assign(&mut self, rhs: UBig) {
*self = mem::take(self) % rhs;
}
}
impl RemAssign<&UBig> for UBig {
#[inline]
fn rem_assign(&mut self, rhs: &UBig) {
*self = mem::take(self) % rhs;
}
}
impl DivRem<UBig> for UBig {
type OutputDiv = UBig;
type OutputRem = UBig;
#[inline]
fn div_rem(self, rhs: UBig) -> (UBig, UBig) {
match (self.into_repr(), rhs.into_repr()) {
(Small(word0), Small(word1)) => UBig::div_rem_word(word0, word1),
(Small(word0), Large(_)) => (UBig::from_word(0), UBig::from_word(word0)),
(Large(buffer0), Small(word1)) => UBig::div_rem_large_word(buffer0, word1),
(Large(buffer0), Large(buffer1)) => {
if buffer0.len() >= buffer1.len() {
UBig::div_rem_large(buffer0, buffer1)
} else {
(UBig::from_word(0), buffer0.into())
}
}
}
}
}
impl DivRem<&UBig> for UBig {
type OutputDiv = UBig;
type OutputRem = UBig;
#[inline]
fn div_rem(self, rhs: &UBig) -> (UBig, UBig) {
match self.into_repr() {
Small(word0) => match rhs.repr() {
Small(word1) => UBig::div_rem_word(word0, *word1),
Large(_) => (UBig::from_word(0), UBig::from_word(word0)),
},
Large(buffer0) => match rhs.repr() {
Small(word1) => UBig::div_rem_large_word(buffer0, *word1),
Large(buffer1) => {
if buffer0.len() >= buffer1.len() {
UBig::div_rem_large(buffer0, buffer1.clone())
} else {
(UBig::from_word(0), buffer0.into())
}
}
},
}
}
}
impl DivRem<UBig> for &UBig {
type OutputDiv = UBig;
type OutputRem = UBig;
#[inline]
fn div_rem(self, rhs: UBig) -> (UBig, UBig) {
match self.repr() {
Small(word0) => match rhs.into_repr() {
Small(word1) => UBig::div_rem_word(*word0, word1),
Large(_) => (UBig::from_word(0), UBig::from_word(*word0)),
},
Large(buffer0) => match rhs.into_repr() {
Small(word1) => UBig::div_rem_large_word(buffer0.clone(), word1),
Large(mut buffer1) => {
if buffer0.len() >= buffer1.len() {
UBig::div_rem_large(buffer0.clone(), buffer1)
} else {
buffer1.resizing_clone_from(buffer0);
(UBig::from_word(0), buffer1.into())
}
}
},
}
}
}
impl DivRem<&UBig> for &UBig {
type OutputDiv = UBig;
type OutputRem = UBig;
#[inline]
fn div_rem(self, rhs: &UBig) -> (UBig, UBig) {
match (self.repr(), rhs.repr()) {
(Small(word0), Small(word1)) => UBig::div_rem_word(*word0, *word1),
(Small(word0), Large(_)) => (UBig::from_word(0), UBig::from_word(*word0)),
(Large(buffer0), Small(word1)) => UBig::div_rem_large_word(buffer0.clone(), *word1),
(Large(buffer0), Large(buffer1)) => {
if buffer0.len() >= buffer1.len() {
UBig::div_rem_large(buffer0.clone(), buffer1.clone())
} else {
(UBig::from_word(0), self.clone())
}
}
}
}
}
impl DivEuclid<UBig> for UBig {
type Output = UBig;
#[inline]
fn div_euclid(self, rhs: UBig) -> UBig {
self / rhs
}
}
impl DivEuclid<&UBig> for UBig {
type Output = UBig;
#[inline]
fn div_euclid(self, rhs: &UBig) -> UBig {
self / rhs
}
}
impl DivEuclid<UBig> for &UBig {
type Output = UBig;
#[inline]
fn div_euclid(self, rhs: UBig) -> UBig {
self / rhs
}
}
impl DivEuclid<&UBig> for &UBig {
type Output = UBig;
#[inline]
fn div_euclid(self, rhs: &UBig) -> UBig {
self / rhs
}
}
impl RemEuclid<UBig> for UBig {
type Output = UBig;
#[inline]
fn rem_euclid(self, rhs: UBig) -> UBig {
self % rhs
}
}
impl RemEuclid<&UBig> for UBig {
type Output = UBig;
#[inline]
fn rem_euclid(self, rhs: &UBig) -> UBig {
self % rhs
}
}
impl RemEuclid<UBig> for &UBig {
type Output = UBig;
#[inline]
fn rem_euclid(self, rhs: UBig) -> UBig {
self % rhs
}
}
impl RemEuclid<&UBig> for &UBig {
type Output = UBig;
#[inline]
fn rem_euclid(self, rhs: &UBig) -> UBig {
self % rhs
}
}
impl DivRemEuclid<UBig> for UBig {
type OutputDiv = UBig;
type OutputRem = UBig;
#[inline]
fn div_rem_euclid(self, rhs: UBig) -> (UBig, UBig) {
self.div_rem(rhs)
}
}
impl DivRemEuclid<&UBig> for UBig {
type OutputDiv = UBig;
type OutputRem = UBig;
#[inline]
fn div_rem_euclid(self, rhs: &UBig) -> (UBig, UBig) {
self.div_rem(rhs)
}
}
impl DivRemEuclid<UBig> for &UBig {
type OutputDiv = UBig;
type OutputRem = UBig;
#[inline]
fn div_rem_euclid(self, rhs: UBig) -> (UBig, UBig) {
self.div_rem(rhs)
}
}
impl DivRemEuclid<&UBig> for &UBig {
type OutputDiv = UBig;
type OutputRem = UBig;
#[inline]
fn div_rem_euclid(self, rhs: &UBig) -> (UBig, UBig) {
self.div_rem(rhs)
}
}
fn panic_divide_by_0() -> ! {
panic!("divide by 0")
}
impl UBig {
fn div_word(lhs: Word, rhs: Word) -> UBig {
match lhs.checked_div(rhs) {
Some(res) => UBig::from_word(res),
None => panic_divide_by_0(),
}
}
fn rem_word(lhs: Word, rhs: Word) -> UBig {
match lhs.checked_rem(rhs) {
Some(res) => UBig::from_word(res),
None => panic_divide_by_0(),
}
}
fn div_rem_word(lhs: Word, rhs: Word) -> (UBig, UBig) {
match lhs.checked_div(rhs) {
Some(res) => (UBig::from_word(res), UBig::from_word(lhs % rhs)),
None => panic_divide_by_0(),
}
}
fn div_large_word(lhs: Buffer, rhs: Word) -> UBig {
let (q, _) = UBig::div_rem_large_word(lhs, rhs);
q
}
fn rem_large_word(lhs: &[Word], rhs: Word) -> UBig {
if rhs == 0 {
panic_divide_by_0();
}
let mut rem: Word = 0;
for word in lhs.iter().rev() {
let (v0, v1) = split_double_word(double_word(*word, rem) % extend_word(rhs));
debug_assert!(v1 == 0);
rem = v0;
}
UBig::from_word(rem)
}
fn div_rem_large_word(mut buffer: Buffer, rhs: Word) -> (UBig, UBig) {
if rhs == 0 {
panic_divide_by_0();
}
let rem = div_rem_by_word_in_place(&mut buffer, rhs);
(buffer.into(), UBig::from_word(rem))
}
fn div_large(lhs: Buffer, rhs: Buffer) -> UBig {
debug_assert!(lhs.len() >= rhs.len() && rhs.len() >= 2);
let (q, _) = UBig::div_rem_large(lhs, rhs);
q
}
fn rem_large(lhs: Buffer, rhs: Buffer) -> UBig {
debug_assert!(lhs.len() >= rhs.len() && rhs.len() >= 2);
let (_, r) = UBig::div_rem_large(lhs, rhs);
r
}
fn div_rem_large(lhs: Buffer, rhs: Buffer) -> (UBig, UBig) {
debug_assert!(lhs.len() >= rhs.len() && rhs.len() >= 2 && *rhs.last().unwrap() != 0);
let shift = rhs.last().unwrap().leading_zeros();
if let Large(buffer0) = (UBig::from(lhs) << shift).into_repr() {
if let Large(buffer1) = (UBig::from(rhs) << shift).into_repr() {
let (q, r) = UBig::div_rem_simple(buffer0, &buffer1);
return (q, r >> shift);
}
}
unreachable!()
}
fn div_rem_simple(mut lhs: Buffer, rhs: &[Word]) -> (UBig, UBig) {
let n = rhs.len();
debug_assert!(lhs.len() >= n && n >= 2);
let rhs0 = rhs[n - 1];
debug_assert!(rhs0.leading_zeros() == 0);
let rhs1 = rhs[n - 2];
let mut lhs0: Word = 0;
let mut quotient = Buffer::allocate(lhs.len() - n + 1);
quotient.push_zeros(lhs.len() - n + 1);
while lhs.len() >= n {
let m = lhs.len();
let lhs1 = lhs[m - 1];
let lhs2 = lhs[m - 2];
let lhs10 = double_word(lhs1, lhs0);
let rhs0_extended = extend_word(rhs0);
let mut q = lhs10 / rhs0_extended;
let mut r = lhs10 % rhs0_extended;
loop {
let (q_lo, q_hi) = split_double_word(q);
let (r_lo, r_hi) = split_double_word(r);
if q_hi != 0
|| (r_hi == 0
&& extend_word(q_lo) * extend_word(rhs1) > double_word(lhs2, r_lo))
{
q -= 1;
r += rhs0_extended;
} else {
break;
}
}
let (mut q_lo, q_hi) = split_double_word(q);
debug_assert!(q_hi == 0);
let offset = lhs.len() - n;
let borrow = sub_mul_word_same_len_in_place(&mut lhs[offset..], q_lo, &rhs);
if borrow > lhs0 {
q_lo -= 1;
let carry = add_same_len_in_place(&mut lhs[offset..], &rhs);
debug_assert!(carry && borrow - 1 == lhs0);
}
quotient[m - n] = q_lo;
lhs0 = lhs.pop().unwrap();
}
lhs.push(lhs0);
(quotient.into(), lhs.into())
}
}
pub(crate) fn div_rem_by_word_in_place(words: &mut [Word], rhs: Word) -> Word {
let mut rem: Word = 0;
for word in words.iter_mut().rev() {
let a = double_word(*word, rem);
let (q0, q1) = split_double_word(a / extend_word(rhs));
debug_assert!(q1 == 0);
let (r0, r1) = split_double_word(a % extend_word(rhs));
debug_assert!(r1 == 0);
*word = q0;
rem = r0;
}
rem
}
impl Div<IBig> for IBig {
type Output = IBig;
#[inline]
fn div(self, rhs: IBig) -> IBig {
let (sign0, mag0) = self.into_sign_magnitude();
let (sign1, mag1) = rhs.into_sign_magnitude();
IBig::from_sign_magnitude(sign0 * sign1, mag0 / mag1)
}
}
impl Div<&IBig> for IBig {
type Output = IBig;
#[inline]
fn div(self, rhs: &IBig) -> IBig {
let (sign0, mag0) = self.into_sign_magnitude();
let (sign1, mag1) = (rhs.sign(), rhs.magnitude());
IBig::from_sign_magnitude(sign0 * sign1, mag0 / mag1)
}
}
impl Div<IBig> for &IBig {
type Output = IBig;
#[inline]
fn div(self, rhs: IBig) -> IBig {
let (sign0, mag0) = (self.sign(), self.magnitude());
let (sign1, mag1) = rhs.into_sign_magnitude();
IBig::from_sign_magnitude(sign0 * sign1, mag0 / mag1)
}
}
impl Div<&IBig> for &IBig {
type Output = IBig;
#[inline]
fn div(self, rhs: &IBig) -> IBig {
let (sign0, mag0) = (self.sign(), self.magnitude());
let (sign1, mag1) = (rhs.sign(), rhs.magnitude());
IBig::from_sign_magnitude(sign0 * sign1, mag0 / mag1)
}
}
impl DivAssign<IBig> for IBig {
#[inline]
fn div_assign(&mut self, rhs: IBig) {
*self = mem::take(self) / rhs;
}
}
impl DivAssign<&IBig> for IBig {
#[inline]
fn div_assign(&mut self, rhs: &IBig) {
*self = mem::take(self) / rhs;
}
}
impl Rem<IBig> for IBig {
type Output = IBig;
#[inline]
fn rem(self, rhs: IBig) -> IBig {
let (sign0, mag0) = self.into_sign_magnitude();
let (_, mag1) = rhs.into_sign_magnitude();
IBig::from_sign_magnitude(sign0, mag0 % mag1)
}
}
impl Rem<&IBig> for IBig {
type Output = IBig;
#[inline]
fn rem(self, rhs: &IBig) -> IBig {
let (sign0, mag0) = self.into_sign_magnitude();
let mag1 = rhs.magnitude();
IBig::from_sign_magnitude(sign0, mag0 % mag1)
}
}
impl Rem<IBig> for &IBig {
type Output = IBig;
#[inline]
fn rem(self, rhs: IBig) -> IBig {
let (sign0, mag0) = (self.sign(), self.magnitude());
let (_, mag1) = rhs.into_sign_magnitude();
IBig::from_sign_magnitude(sign0, mag0 % mag1)
}
}
impl Rem<&IBig> for &IBig {
type Output = IBig;
#[inline]
fn rem(self, rhs: &IBig) -> IBig {
let (sign0, mag0) = (self.sign(), self.magnitude());
let mag1 = rhs.magnitude();
IBig::from_sign_magnitude(sign0, mag0 % mag1)
}
}
impl RemAssign<IBig> for IBig {
#[inline]
fn rem_assign(&mut self, rhs: IBig) {
*self = mem::take(self) % rhs;
}
}
impl RemAssign<&IBig> for IBig {
#[inline]
fn rem_assign(&mut self, rhs: &IBig) {
*self = mem::take(self) % rhs;
}
}
impl DivRem<IBig> for IBig {
type OutputDiv = IBig;
type OutputRem = IBig;
#[inline]
fn div_rem(self, rhs: IBig) -> (IBig, IBig) {
let (sign0, mag0) = self.into_sign_magnitude();
let (sign1, mag1) = rhs.into_sign_magnitude();
let (q, r) = mag0.div_rem(mag1);
(
IBig::from_sign_magnitude(sign0 * sign1, q),
IBig::from_sign_magnitude(sign0, r),
)
}
}
impl DivRem<&IBig> for IBig {
type OutputDiv = IBig;
type OutputRem = IBig;
#[inline]
fn div_rem(self, rhs: &IBig) -> (IBig, IBig) {
let (sign0, mag0) = self.into_sign_magnitude();
let (sign1, mag1) = (rhs.sign(), rhs.magnitude());
let (q, r) = mag0.div_rem(mag1);
(
IBig::from_sign_magnitude(sign0 * sign1, q),
IBig::from_sign_magnitude(sign0, r),
)
}
}
impl DivRem<IBig> for &IBig {
type OutputDiv = IBig;
type OutputRem = IBig;
#[inline]
fn div_rem(self, rhs: IBig) -> (IBig, IBig) {
let (sign0, mag0) = (self.sign(), self.magnitude());
let (sign1, mag1) = rhs.into_sign_magnitude();
let (q, r) = mag0.div_rem(mag1);
(
IBig::from_sign_magnitude(sign0 * sign1, q),
IBig::from_sign_magnitude(sign0, r),
)
}
}
impl DivRem<&IBig> for &IBig {
type OutputDiv = IBig;
type OutputRem = IBig;
#[inline]
fn div_rem(self, rhs: &IBig) -> (IBig, IBig) {
let (sign0, mag0) = (self.sign(), self.magnitude());
let (sign1, mag1) = (rhs.sign(), rhs.magnitude());
let (q, r) = mag0.div_rem(mag1);
(
IBig::from_sign_magnitude(sign0 * sign1, q),
IBig::from_sign_magnitude(sign0, r),
)
}
}
impl DivEuclid<IBig> for IBig {
type Output = IBig;
#[inline]
fn div_euclid(self, rhs: IBig) -> IBig {
let s = rhs.signum();
let (q, r) = self.div_rem(rhs);
if r.is_negative() {
q - s
} else {
q
}
}
}
impl DivEuclid<&IBig> for IBig {
type Output = IBig;
#[inline]
fn div_euclid(self, rhs: &IBig) -> IBig {
let (q, r) = self.div_rem(rhs);
if r.is_negative() {
q - rhs.signum()
} else {
q
}
}
}
impl DivEuclid<IBig> for &IBig {
type Output = IBig;
#[inline]
fn div_euclid(self, rhs: IBig) -> IBig {
let s = rhs.signum();
let (q, r) = self.div_rem(rhs);
if r.is_negative() {
q - s
} else {
q
}
}
}
impl DivEuclid<&IBig> for &IBig {
type Output = IBig;
#[inline]
fn div_euclid(self, rhs: &IBig) -> IBig {
let (q, r) = self.div_rem(rhs);
if r.is_negative() {
q - rhs.signum()
} else {
q
}
}
}
impl RemEuclid<IBig> for IBig {
type Output = IBig;
#[inline]
fn rem_euclid(self, rhs: IBig) -> IBig {
let r = self % &rhs;
if r.is_negative() {
r + rhs.abs()
} else {
r
}
}
}
impl RemEuclid<&IBig> for IBig {
type Output = IBig;
#[inline]
fn rem_euclid(self, rhs: &IBig) -> IBig {
let r = self % rhs;
if r.is_negative() {
r + rhs.abs()
} else {
r
}
}
}
impl RemEuclid<IBig> for &IBig {
type Output = IBig;
#[inline]
fn rem_euclid(self, rhs: IBig) -> IBig {
let r = self % &rhs;
if r.is_negative() {
r + rhs.abs()
} else {
r
}
}
}
impl RemEuclid<&IBig> for &IBig {
type Output = IBig;
#[inline]
fn rem_euclid(self, rhs: &IBig) -> IBig {
let r = self % rhs;
if r.is_negative() {
r + rhs.abs()
} else {
r
}
}
}
impl DivRemEuclid<IBig> for IBig {
type OutputDiv = IBig;
type OutputRem = IBig;
#[inline]
fn div_rem_euclid(self, rhs: IBig) -> (IBig, IBig) {
let (q, r) = self.div_rem(&rhs);
if r.is_negative() {
(q - rhs.signum(), r + rhs.abs())
} else {
(q, r)
}
}
}
impl DivRemEuclid<&IBig> for IBig {
type OutputDiv = IBig;
type OutputRem = IBig;
#[inline]
fn div_rem_euclid(self, rhs: &IBig) -> (IBig, IBig) {
let (q, r) = self.div_rem(rhs);
if r.is_negative() {
(q - rhs.signum(), r + rhs.abs())
} else {
(q, r)
}
}
}
impl DivRemEuclid<IBig> for &IBig {
type OutputDiv = IBig;
type OutputRem = IBig;
#[inline]
fn div_rem_euclid(self, rhs: IBig) -> (IBig, IBig) {
let (q, r) = self.div_rem(&rhs);
if r.is_negative() {
(q - rhs.signum(), r + rhs.abs())
} else {
(q, r)
}
}
}
impl DivRemEuclid<&IBig> for &IBig {
type OutputDiv = IBig;
type OutputRem = IBig;
#[inline]
fn div_rem_euclid(self, rhs: &IBig) -> (IBig, IBig) {
let (q, r) = self.div_rem(rhs);
if r.is_negative() {
(q - rhs.signum(), r + rhs.abs())
} else {
(q, r)
}
}
}