use crate::int::types::Int;
#[inline]
#[must_use]
pub(crate) fn rem_native<const N: usize>(a: Int<N>, b: Int<N>) -> Int<N> {
assert!(
!b.is_zero(),
"attempt to calculate the remainder with a divisor of zero"
);
if N == 1 {
let ai = a.to_i128() as i64;
let bi = b.to_i128() as i64;
if ai == i64::MIN && bi == -1 {
panic!("attempt to calculate the remainder with overflow");
}
return Int::<N>::from_i128(ai.wrapping_rem(bi) as i128);
}
let ai = a.to_i128();
let bi = b.to_i128();
if ai == i128::MIN && bi == -1 {
panic!("attempt to calculate the remainder with overflow");
}
Int::<N>::from_i128(ai.wrapping_rem(bi))
}
#[cfg(test)]
mod tests {
use super::rem_native;
use crate::int::types::Int;
#[test]
fn rem_native_n1_matches_primitive() {
let cases: &[(i64, i64)] = &[
(10, 3),
(-10, 3),
(10, -3),
(-10, -3),
(0, 7),
(7, 7),
(100, 13),
(i64::MAX, 2),
(i64::MIN + 1, 2),
(i64::MIN, 7),
];
for &(a, b) in cases {
let got = rem_native::<1>(Int::<1>::from_i64(a), Int::<1>::from_i64(b));
assert_eq!(got.to_i128() as i64, a % b, "rem_native n1 ({a}, {b})");
}
}
#[test]
fn rem_native_n2_matches_primitive() {
let cases: &[(i128, i128)] = &[
(100, 7),
(-100, 7),
(100, -7),
(-100, -7),
(i128::MAX, 3),
(i128::MIN + 1, 3),
(1_000_000_000_000_i128, 999_999_937),
];
for &(a, b) in cases {
let got = rem_native::<2>(Int::<2>::from_i128(a), Int::<2>::from_i128(b));
assert_eq!(got.to_i128(), a % b, "rem_native n2 ({a}, {b})");
}
}
}