use core::str::FromStr;
use malachite_base::num::arithmetic::traits::{
Mod, ModAssign, ModIsReduced, ModPowerOf2, PowerOf2,
};
use malachite_base::test_util::generators::{
unsigned_vector_gen, unsigned_vector_unsigned_pair_gen_var_3,
};
use malachite_base::unsigned_vector::UnsignedVector;
use malachite_base::vector::Vector;
#[test]
fn test_rem() {
let test = |s, m: u64, out| {
let v = UnsignedVector::<u64>::from_str(s).unwrap();
let w = &v % m;
assert_eq!(w.to_string(), out);
assert_eq!(v.clone() % m, w);
let mut x = v;
x %= m;
assert_eq!(x, w);
};
test("()", 1, "()");
test("()", 7, "()");
test("(0)", 7, "(0)");
test("(5, 4, 1)", 3, "(2, 1, 1)");
test("(5, 4, 1)", 7, "(5, 4, 1)");
test("(5, 4, 1)", 1, "(0, 0, 0)");
test("(4, 3)", 4, "(0, 3)");
test("(3, 4)", 4, "(3, 0)");
test("(6, 3, 9)", 3, "(0, 0, 0)");
test(
"(18446744073709551615, 18446744073709551614)",
u64::MAX,
"(0, 18446744073709551614)",
);
}
#[test]
fn test_rem_u8() {
let test = |s, m: u8, out| {
assert_eq!(
(UnsignedVector::<u8>::from_str(s).unwrap() % m).to_string(),
out
);
};
test("(255, 128)", 7, "(3, 2)");
test("(255, 128)", 255, "(0, 128)");
test("(255, 128)", 128, "(127, 0)");
}
#[test]
fn test_mod_op() {
let test = |s, m: u64, out| {
let v = UnsignedVector::<u64>::from_str(s).unwrap();
let w = (&v).mod_op(m);
assert_eq!(w.to_string(), out);
assert_eq!(v.clone().mod_op(m), w);
let mut x = v;
x.mod_assign(m);
assert_eq!(x, w);
};
test("()", 1, "()");
test("(5, 4, 1)", 3, "(2, 1, 1)");
test("(5, 4, 1)", 1, "(0, 0, 0)");
test("(4, 3)", 4, "(0, 3)");
}
#[test]
#[should_panic]
fn rem_fail() {
let _ = UnsignedVector::<u64>::from_str("(1)").unwrap() % 0;
}
#[test]
#[should_panic]
fn rem_ref_fail() {
let _ = &UnsignedVector::<u64>::from_str("(1)").unwrap() % 0;
}
#[test]
#[should_panic]
fn rem_assign_fail() {
let mut v = UnsignedVector::<u64>::from_str("(1)").unwrap();
v %= 0;
}
#[test]
#[should_panic]
fn mod_op_fail() {
let _ = UnsignedVector::<u64>::from_str("(1)").unwrap().mod_op(0);
}
#[test]
#[should_panic]
fn mod_op_ref_fail() {
let _ = (&UnsignedVector::<u64>::from_str("(1)").unwrap()).mod_op(0);
}
#[test]
#[should_panic]
fn mod_assign_fail() {
let mut v = UnsignedVector::<u64>::from_str("(1)").unwrap();
v.mod_assign(0);
}
#[test]
#[should_panic]
fn rem_empty_vector_fail() {
let _ = UnsignedVector::<u64>::from_str("()").unwrap() % 0;
}
#[test]
#[should_panic]
fn rem_ref_empty_vector_fail() {
let _ = &UnsignedVector::<u64>::from_str("()").unwrap() % 0;
}
#[test]
#[should_panic]
fn rem_assign_empty_vector_fail() {
let mut v = UnsignedVector::<u64>::from_str("()").unwrap();
v %= 0;
}
#[test]
#[allow(clippy::modulo_one)]
fn rem_properties() {
unsigned_vector_unsigned_pair_gen_var_3().test_properties(|(v, m)| {
let w = &v % m;
assert_eq!(v.clone() % m, w);
let mut x = v.clone();
x %= m;
assert_eq!(x, w);
assert!(w.mod_is_reduced(&m));
assert_eq!(&w % m, w);
assert_eq!(w.dimension(), v.dimension());
assert_eq!(v.mod_is_reduced(&m), v == w);
assert_eq!((&v).mod_op(m), w);
assert_eq!(v.clone().mod_op(m), w);
let mut x = v.clone();
x.mod_assign(m);
assert_eq!(x, w);
for (&x, &y) in v.elements.iter().zip(&w.elements) {
assert_eq!(x, m * (x / m) + y);
assert_eq!(y, x % m);
}
});
unsigned_vector_gen().test_properties(|v| {
assert!((&v % 1).elements.iter().all(|&x| x == 0));
if let Some(above) = v.elements.iter().max().copied().unwrap_or(0).checked_add(1) {
assert_eq!(&v % above, v);
}
for pow in 1..64 {
assert_eq!(&v % u64::power_of_2(pow), (&v).mod_power_of_2(pow));
}
});
}