// 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::{
ArithmeticCheckedShl, ModPowerOf2Shl, ModPowerOf2ShlAssign, ModPowerOf2Shr,
};
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::signeds::PrimitiveSigned;
use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
use malachite_base::test_util::generators::{
signed_unsigned_pair_gen_var_12, unsigned_pair_gen_var_17, unsigned_pair_gen_var_23,
unsigned_signed_unsigned_triple_gen_var_1, unsigned_triple_gen_var_17,
};
use std::panic::catch_unwind;
#[test]
fn test_mod_power_of_2_shl() {
fn test<
T: ModPowerOf2Shl + ModPowerOf2ShlAssign + PrimitiveUnsigned,
U: PrimitiveInt,
>(
t: T,
u: U,
pow: u64,
out: T,
) {
assert_eq!(t.mod_power_of_2_shl(u, pow), out);
let mut t = t;
t.mod_power_of_2_shl_assign(u, pow);
assert_eq!(t, out);
}
test::(0, 0, 0, 0);
test::(0, 0, 5, 0);
test::(12, 2, 5, 16);
test::(10, 100, 4, 0);
test::(10, -2, 4, 2);
test::(10, -100, 4, 0);
test::(10, -100, 4, 0);
}
fn mod_power_of_2_shl_fail_helper<
T: PrimitiveUnsigned + ModPowerOf2Shl,
U: PrimitiveInt,
>() {
assert_panic!(T::ONE.mod_power_of_2_shl(U::TWO, 0));
assert_panic!(T::from(200u8).mod_power_of_2_shl(U::TWO, 7));
}
#[test]
fn mod_power_of_2_shl_fail() {
apply_fn_to_unsigneds_and_primitive_ints!(mod_power_of_2_shl_fail_helper);
}
fn mod_power_of_2_shl_assign_fail_helper<
T: PrimitiveUnsigned + ModPowerOf2ShlAssign,
U: PrimitiveInt,
>() {
assert_panic!({
let mut x = T::ONE;
x.mod_power_of_2_shl_assign(U::TWO, 0);
});
assert_panic!({
let mut x = T::from(200u8);
x.mod_power_of_2_shl_assign(U::TWO, 7);
});
}
#[test]
fn mod_power_of_2_shl_assign_fail() {
apply_fn_to_unsigneds_and_primitive_ints!(mod_power_of_2_shl_assign_fail_helper);
}
fn mod_power_of_2_shl_properties_unsigned_unsigned_helper<
T: ArithmeticCheckedShl
+ ModPowerOf2Shl
+ ModPowerOf2ShlAssign
+ PrimitiveUnsigned,
U: PrimitiveUnsigned,
>() {
unsigned_triple_gen_var_17::().test_properties(|(n, u, pow)| {
assert!(n.mod_power_of_2_is_reduced(pow));
let shifted = n.mod_power_of_2_shl(u, pow);
assert!(shifted.mod_power_of_2_is_reduced(pow));
let mut shifted_alt = n;
shifted_alt.mod_power_of_2_shl_assign(u, pow);
assert_eq!(shifted_alt, shifted);
if let Some(shifted_alt) = n.arithmetic_checked_shl(u) {
assert_eq!(shifted_alt.mod_power_of_2(pow), shifted);
}
});
unsigned_pair_gen_var_17::().test_properties(|(n, pow)| {
assert_eq!(n.mod_power_of_2_shl(U::ZERO, pow), n);
});
unsigned_pair_gen_var_23::().test_properties(|(u, pow)| {
assert_eq!(T::ZERO.mod_power_of_2_shl(u, pow), T::ZERO);
});
}
fn mod_power_of_2_shl_properties_unsigned_signed_helper<
T: ArithmeticCheckedShl
+ ModPowerOf2Shl
+ ModPowerOf2Shr
+ ModPowerOf2ShlAssign
+ PrimitiveUnsigned,
U: PrimitiveSigned,
>() {
unsigned_signed_unsigned_triple_gen_var_1::().test_properties(|(n, i, pow)| {
assert!(n.mod_power_of_2_is_reduced(pow));
let shifted = n.mod_power_of_2_shl(i, pow);
assert!(shifted.mod_power_of_2_is_reduced(pow));
let mut shifted_alt = n;
shifted_alt.mod_power_of_2_shl_assign(i, pow);
assert_eq!(shifted_alt, shifted);
if let Some(shifted_alt) = n.arithmetic_checked_shl(i) {
assert_eq!(shifted_alt.mod_power_of_2(pow), shifted);
}
if i != U::MIN {
assert_eq!(n.mod_power_of_2_shr(-i, pow), shifted);
}
});
unsigned_pair_gen_var_17::().test_properties(|(n, pow)| {
assert_eq!(n.mod_power_of_2_shl(U::ZERO, pow), n);
});
signed_unsigned_pair_gen_var_12::().test_properties(|(i, pow)| {
assert_eq!(T::ZERO.mod_power_of_2_shl(i, pow), T::ZERO);
});
}
#[test]
fn mod_power_of_2_shl_properties() {
apply_fn_to_unsigneds_and_unsigneds!(mod_power_of_2_shl_properties_unsigned_unsigned_helper);
apply_fn_to_unsigneds_and_signeds!(mod_power_of_2_shl_properties_unsigned_signed_helper);
}