// Copyright © 2024 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See .
use malachite_base::num::arithmetic::traits::{ArithmeticCheckedShr, ModShl, ModShr, ModShrAssign};
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::signeds::PrimitiveSigned;
use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
use malachite_base::num::conversion::traits::WrappingFrom;
use malachite_base::test_util::generators::{
signed_gen_var_5, signed_unsigned_pair_gen_var_13, unsigned_pair_gen_var_16,
unsigned_signed_pair_gen_var_1, unsigned_signed_unsigned_triple_gen_var_2,
};
use std::panic::catch_unwind;
#[test]
fn test_mod_shr() {
fn test<
T: ModShr + ModShrAssign + PrimitiveUnsigned,
U: PrimitiveInt,
>(
t: T,
i: U,
m: T,
out: T,
) {
assert_eq!(t.mod_shr(i, m), out);
let mut t = t;
t.mod_shr_assign(i, m);
assert_eq!(t, out);
}
test::(0, 0, 1, 0);
test::(0, 0, 5, 0);
test::(8, -2, 10, 2);
test::(10, -100, 17, 7);
test::(10, 2, 15, 2);
test::(10, 100, 19, 0);
test::(10, 100, 19, 0);
}
fn mod_shr_fail_helper, U: PrimitiveSigned>() {
assert_panic!(T::ZERO.mod_shr(U::TWO, T::ZERO));
assert_panic!(T::from(123u8).mod_shr(U::TWO, T::from(123u8)));
}
#[test]
fn mod_shr_fail() {
apply_fn_to_unsigneds_and_signeds!(mod_shr_fail_helper);
}
fn mod_shr_assign_fail_helper, U: PrimitiveSigned>() {
assert_panic!({
let mut x = T::ZERO;
x.mod_shr_assign(U::TWO, T::ZERO);
});
assert_panic!({
let mut x = T::from(123u8);
x.mod_shr_assign(U::TWO, T::from(123u8));
});
}
#[test]
fn mod_shr_assign_fail() {
apply_fn_to_unsigneds_and_signeds!(mod_shr_assign_fail_helper);
}
fn mod_shr_properties_helper<
T: ArithmeticCheckedShr
+ ModShl
+ ModShr
+ ModShrAssign
+ PrimitiveUnsigned,
U: PrimitiveUnsigned + WrappingFrom,
S: PrimitiveSigned + WrappingFrom,
>() {
unsigned_signed_unsigned_triple_gen_var_2::().test_properties(|(n, i, m)| {
assert!(n.mod_is_reduced(&m));
let shifted = n.mod_shr(i, m);
assert!(shifted.mod_is_reduced(&m));
let mut shifted_alt = n;
shifted_alt.mod_shr_assign(i, m);
assert_eq!(shifted_alt, shifted);
if let Some(shifted_alt) = n.arithmetic_checked_shr(i) {
assert_eq!(shifted_alt % m, shifted);
}
if i != S::MIN {
assert_eq!(n.mod_shl(-i, m), shifted);
}
});
unsigned_pair_gen_var_16::().test_properties(|(n, m)| {
assert_eq!(n.mod_shr(S::ZERO, m), n);
});
signed_unsigned_pair_gen_var_13::().test_properties(|(i, m)| {
assert_eq!(T::ZERO.mod_shr(i, m), T::ZERO);
});
unsigned_signed_pair_gen_var_1::().test_properties(|(n, i)| {
assert_panic!(n.mod_shr(i, T::ZERO));
assert_panic!({
let mut n = n;
n.mod_shr_assign(i, T::ZERO);
});
});
signed_gen_var_5::().test_properties(|i| {
assert_eq!(T::ZERO.mod_shl(i, T::ONE), T::ZERO);
});
}
#[test]
fn mod_shr_properties() {
apply_fn_to_unsigneds_and_unsigned_signed_pairs!(mod_shr_properties_helper);
}