use crate::natural::arithmetic::div_mod::limbs_invert_limb;
use crate::natural::arithmetic::mod_op::mod_by_preinversion;
use crate::platform::{DoubleLimb, Limb};
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::logic::traits::LeadingZeros;
use rug::ops::RemRounding;
pub fn rug_neg_mod(x: rug::Integer, y: rug::Integer) -> rug::Integer {
-x.rem_ceil(y)
}
pub fn limbs_mod_limb_alt_3(ns: &[Limb], d: Limb) -> Limb {
assert_ne!(d, 0);
let len = ns.len();
assert!(len > 1);
let bits = LeadingZeros::leading_zeros(d);
let (ns_last, ns_init) = ns.split_last().unwrap();
if bits == 0 {
let mut r = *ns_last;
if r >= d {
r -= d;
}
let d_inv = limbs_invert_limb::<DoubleLimb, Limb>(d);
for n in ns_init.iter().rev() {
r = mod_by_preinversion::<DoubleLimb, Limb>(r, *n, d, d_inv);
}
r
} else {
let (ns, mut r) = if *ns_last < d {
(ns_init, *ns_last)
} else {
(ns, 0)
};
let d = d << bits;
r <<= bits;
let d_inv = limbs_invert_limb::<DoubleLimb, Limb>(d);
let (ns_last, ns_init) = ns.split_last().unwrap();
let mut previous_n = *ns_last;
let cobits = Limb::WIDTH - bits;
r |= previous_n >> cobits;
for &n in ns_init.iter().rev() {
let shifted_n = (previous_n << bits) | (n >> cobits);
r = mod_by_preinversion::<DoubleLimb, Limb>(r, shifted_n, d, d_inv);
previous_n = n;
}
mod_by_preinversion::<DoubleLimb, Limb>(r, previous_n << bits, d, d_inv) >> bits
}
}