use crypto_bigint::{Choice, Limb};
pub(super) trait Limbs: Sized + Clone + AsRef<[Limb]> + AsMut<[Limb]> {
fn widening_square(&self) -> (Self, Self);
fn wrapping_div(num: (Self, Self), denom: &Self) -> Self;
fn rem(num: Self, denom: &Self) -> Self;
}
pub(crate) fn c<L: Limbs>(a: &L, b: &(Choice, L), negative_discriminant_abs: &L) -> L {
let (mut b_lo, mut b_hi) = b.1.widening_square();
let mut carry = Limb::ZERO;
for i in 0 .. (b_lo.as_ref().len() + b_hi.as_ref().len()) {
let b_limb = if let Some(i) = i.checked_sub(b_lo.as_ref().len()) {
&mut b_hi.as_mut()[i]
} else {
&mut b_lo.as_mut()[i]
};
let new_limb;
(new_limb, carry) =
b_limb.carrying_add(*negative_discriminant_abs.as_ref().get(i).unwrap_or(&Limb::ZERO), carry);
let shift_down = new_limb << (Limb::BITS - 2);
*b_limb = new_limb >> 2;
if let Some(i) = i.checked_sub(1) {
let b_limb = if let Some(i) = i.checked_sub(b_lo.as_ref().len()) {
&mut b_hi.as_mut()[i]
} else {
&mut b_lo.as_mut()[i]
};
*b_limb |= shift_down;
}
}
*b_hi.as_mut().last_mut().unwrap() |= carry << (Limb::BITS - 2);
let ac = (b_lo, b_hi);
L::wrapping_div(ac, a)
}