use crate::num::basic::signeds::PrimitiveSigned;
use crate::num::basic::unsigneds::PrimitiveUnsigned;
use crate::num::conversion::traits::WrappingFrom;
pub fn mod_div_euclidean<
U: PrimitiveUnsigned + WrappingFrom<S>,
S: PrimitiveSigned + WrappingFrom<U>,
>(
b: U,
c: U,
m: U,
) -> Option<U> {
assert!(b < m, "b must be reduced mod m, but {b} >= {m}");
assert!(c < m, "c must be reduced mod m, but {c} >= {m}");
if c == U::ZERO {
return if b == U::ZERO { Some(U::ZERO) } else { None };
}
if b == U::ZERO {
return Some(U::ZERO);
}
let mut x = m;
let mut r = c;
let mut v1 = S::ZERO;
let mut v2 = S::ONE;
while r != U::ZERO {
let (quot, rem) = x.div_rem(r);
x = r;
r = rem;
let t = v2;
v2 = v1.wrapping_sub(S::wrapping_from(quot).wrapping_mul(v2));
v1 = t;
}
let g = x;
let (q, rem) = b.div_rem(g);
if rem != U::ZERO {
return None;
}
let mut s = U::wrapping_from(v1);
if v1 < S::ZERO {
s.wrapping_add_assign(m);
}
Some(q.mod_mul(s, m))
}