use malachite_base::num::arithmetic::traits::{
BalancedMod, BalancedModAssign, Parity, UnsignedAbs,
};
use malachite_base::num::basic::signeds::PrimitiveSigned;
use malachite_base::num::basic::traits::Zero;
use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
use malachite_base::test_util::generators::{signed_pair_gen_var_52, unsigned_pair_gen_var_52};
use std::panic::catch_unwind;
#[test]
fn test_balanced_mod_unsigned() {
assert_eq!(0u32.balanced_mod(10), 0);
assert_eq!(3u32.balanced_mod(10), 3);
assert_eq!(5u32.balanced_mod(10), 5);
assert_eq!(6u32.balanced_mod(10), -4);
assert_eq!(23u32.balanced_mod(10), 3);
assert_eq!(27u32.balanced_mod(10), -3);
assert_eq!(4u32.balanced_mod(9), 4);
assert_eq!(5u32.balanced_mod(9), -4);
assert_eq!(7u8.balanced_mod(1), 0);
assert_eq!(u8::MAX.balanced_mod(u8::MAX), 0);
assert_eq!((u8::MAX - 1).balanced_mod(u8::MAX), -1);
assert_eq!(127u8.balanced_mod(u8::MAX), 127);
assert_eq!(128u8.balanced_mod(u8::MAX), -127);
assert_eq!(u64::MAX.balanced_mod(u64::MAX), 0);
assert_eq!((u64::MAX >> 1).balanced_mod(u64::MAX), i64::MAX);
}
#[test]
fn test_balanced_mod_signed() {
assert_eq!(23i32.balanced_mod(10), 3);
assert_eq!(27i32.balanced_mod(10), -3);
assert_eq!(25i32.balanced_mod(10), 5);
assert_eq!((-23i32).balanced_mod(10), -3);
assert_eq!((-27i32).balanced_mod(10), 3);
assert_eq!((-25i32).balanced_mod(10), 5);
assert_eq!(23i32.balanced_mod(-10), 3);
assert_eq!((-27i32).balanced_mod(-10), 3);
assert_eq!(0i32.balanced_mod(10), 0);
assert_eq!(0i8.balanced_mod(i8::MIN), 0);
assert_eq!(64i8.balanced_mod(i8::MIN), 64);
assert_eq!(65i8.balanced_mod(i8::MIN), -63);
assert_eq!((-64i8).balanced_mod(i8::MIN), 64);
assert_eq!(i8::MIN.balanced_mod(i8::MIN), 0);
assert_eq!(i8::MAX.balanced_mod(i8::MIN), -1);
let mut x = 27i32;
x.balanced_mod_assign(10);
assert_eq!(x, -3);
}
fn balanced_mod_fail_helper_unsigned<T: PrimitiveUnsigned>() {
assert_panic!(T::exact_from(10).balanced_mod(T::ZERO));
}
fn balanced_mod_fail_helper_signed<T: PrimitiveSigned>() {
assert_panic!(T::exact_from(10).balanced_mod(T::ZERO));
assert_panic!(T::exact_from(10).balanced_mod_assign(T::ZERO));
}
#[test]
fn balanced_mod_fail() {
apply_fn_to_unsigneds!(balanced_mod_fail_helper_unsigned);
apply_fn_to_signeds!(balanced_mod_fail_helper_signed);
}
fn balanced_mod_properties_helper_unsigned<T: PrimitiveUnsigned>() {
unsigned_pair_gen_var_52::<T>().test_properties(|(x, y)| {
let r = x.balanced_mod(y);
type S<T> = <T as BalancedMod<T>>::Output;
let m = x % y;
let abs_r = r.unsigned_abs();
if r >= S::<T>::ZERO {
assert_eq!(abs_r, m);
} else {
assert_eq!(y - abs_r, m);
}
let half = y >> 1;
assert!(abs_r <= half);
if abs_r == half && y.even() && r != S::<T>::ZERO {
assert!(r > S::<T>::ZERO);
}
});
}
fn balanced_mod_properties_helper_signed<T: PrimitiveSigned>()
where
<T as UnsignedAbs>::Output: PrimitiveUnsigned,
{
signed_pair_gen_var_52::<T>().test_properties(|(x, y)| {
let r = x.balanced_mod(y);
let mut mut_x = x;
mut_x.balanced_mod_assign(y);
assert_eq!(mut_x, r);
let abs_y = y.unsigned_abs();
let m = x.mod_euclidean(y).unsigned_abs();
let abs_r = r.unsigned_abs();
if r >= T::ZERO {
assert_eq!(abs_r, m);
} else {
assert_eq!(abs_y - abs_r, m);
}
let half = abs_y >> 1;
assert!(abs_r <= half);
if abs_r == half && abs_y.even() && r != T::ZERO {
assert!(r > T::ZERO);
}
if y != T::MIN {
assert_eq!(x.balanced_mod(-y), r);
}
});
}
#[test]
fn balanced_mod_properties() {
apply_fn_to_unsigneds!(balanced_mod_properties_helper_unsigned);
apply_fn_to_signeds!(balanced_mod_properties_helper_signed);
}