// 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::UnsignedAbs; use malachite_base::num::basic::signeds::PrimitiveSigned; use malachite_base::num::basic::unsigneds::PrimitiveUnsigned; use malachite_base::num::logic::traits::BitBlockAccess; use malachite_base::test_util::generators::{ signed_unsigned_pair_gen_var_1, signed_unsigned_unsigned_triple_gen_var_1, signed_unsigned_unsigned_unsigned_quadruple_gen_var_1, unsigned_pair_gen_var_2, unsigned_pair_gen_var_7, unsigned_quadruple_gen_var_1, unsigned_triple_gen_var_4, }; use malachite_base::test_util::num::logic::bit_block_access::assign_bits_naive; use std::cmp::min; use std::panic::catch_unwind; #[test] pub fn test_assign_bits_unsigned() { fn test + PrimitiveUnsigned>( x_in: T, start: u64, end: u64, bits: T, x_out: T, ) { let mut x = x_in; x.assign_bits(start, end, &bits); assert_eq!(x, x_out); let mut x = x_in; assign_bits_naive(&mut x, start, end, &bits); assert_eq!(x, x_out); } // - assign partially test(0xab5du16, 4, 8, 0xc, 0xabcd); test(0x5bcdu16, 12, 100, 0xa, 0xabcd); test(0xabcdu16, 5, 9, 10, 43853); test(0xabcdu16, 5, 5, 123, 0xabcd); // - assign zeros above width test(0xabcdu16, 100, 200, 0, 0xabcd); test(0xabcdu16, 8, 24, 0, 0xcd); // - assign everything test(0xabcdu16, 0, 100, 0x1234, 0x1234); test(0xab5du64, 4, 8, 0xc, 0xabcd); test(0x5bcdu64, 12, 100, 0xa, 0xabcd); test(0xabcdu64, 5, 9, 10, 43853); test(0xabcdu64, 5, 5, 123, 0xabcd); test(0xabcdu64, 100, 200, 0, 0xabcd); test(0xabcdu64, 0, 100, 0x1234, 0x1234); } #[test] pub fn test_assign_bits_signed() { fn test + PrimitiveSigned, U: PrimitiveUnsigned>( x_in: T, start: u64, end: u64, bits: U, x_out: T, ) { let mut x = x_in; x.assign_bits(start, end, &bits); assert_eq!(x, x_out); let mut x = x_in; assign_bits_naive(&mut x, start, end, &bits); assert_eq!(x, x_out); } // - *self >= 0 test(0x2b5di16, 4, 8, 0xc, 0x2bcd); // - *self < 0 // - assign within width test(-0x5413i16, 4, 8, 0xc, -0x5433); test(-0x54a3i16, 5, 9, 14, -21539); test(-0x5433i16, 5, 5, 0, -0x5433); // - assign ones above width test(-0x5433i16, 100, 104, 0xf, -0x5433); // - assign everything test(-57i8, 0, 8, 0xff, -1); test(0x2b5di64, 4, 8, 0xc, 0x2bcd); test(-0x5413i64, 4, 8, 0xc, -0x5433); test(-0x54a3i64, 5, 9, 14, -21539); test(-0x5433i64, 5, 5, 0, -0x5433); test(-0x5433i64, 100, 104, 0xf, -0x5433); test(-57i64, 0, 64, u64::MAX, -1); } fn assign_bits_fail_helper_unsigned + PrimitiveUnsigned>() { assert_panic!(T::exact_from(100).assign_bits(10, 5, &T::exact_from(3))); assert_panic!(T::exact_from(100).assign_bits(3, T::WIDTH + 3, &T::MAX)); } fn assign_bits_fail_helper_signed< U: PrimitiveUnsigned, S: BitBlockAccess + PrimitiveSigned, >() { assert_panic!(S::exact_from(100).assign_bits(7, 5, &U::exact_from(3))); assert_panic!(S::exact_from(100).assign_bits(0, S::WIDTH, &U::MAX)); assert_panic!(S::exact_from(-100).assign_bits(0, S::WIDTH + 1, &U::ZERO)); assert_panic!(S::exact_from(-100).assign_bits(S::WIDTH + 1, S::WIDTH + 2, &U::ZERO)); assert_panic!({ let half_width = S::WIDTH >> 1; S::exact_from(-100).assign_bits(half_width, 3 * half_width - 4, &U::ZERO); }); } #[test] fn assign_bits_fail() { apply_fn_to_unsigneds!(assign_bits_fail_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(assign_bits_fail_helper_signed); } fn properties_helper_unsigned + PrimitiveUnsigned>() { unsigned_quadruple_gen_var_1::().test_properties(|(n, start, end, bits)| { let mut mut_n = n; mut_n.assign_bits(start, end, &bits); let mut mut_n_alt = mut_n; mut_n_alt.assign_bits(start, end, &bits); assert_eq!(mut_n_alt, mut_n); let mut mut_n_alt = n; assign_bits_naive::(&mut mut_n_alt, start, end, &bits); assert_eq!(mut_n_alt, mut_n); assert_eq!(mut_n.get_bits(start, end), bits.mod_power_of_2(end - start)); }); unsigned_triple_gen_var_4::().test_properties(|(n, bits, start)| { let mut mut_n = n; mut_n.assign_bits(start, start, &bits); assert_eq!(mut_n, n); }); unsigned_pair_gen_var_2::().test_properties(|(n, start)| { let mut mut_n = n; mut_n.assign_bits(start + T::WIDTH, start + (T::WIDTH << 1), &T::ZERO); assert_eq!(mut_n, n); }); unsigned_pair_gen_var_7::().test_properties(|(start, end)| { let mut n = T::ZERO; n.assign_bits(start, end, &T::ZERO); assert_eq!(n, T::ZERO); }); } fn properties_helper_signed< U: BitBlockAccess + PrimitiveUnsigned, T: BitBlockAccess + PrimitiveSigned + UnsignedAbs, >() { signed_unsigned_unsigned_unsigned_quadruple_gen_var_1::().test_properties( |(n, start, end, bits)| { let mut mut_n = n; mut_n.assign_bits(start, end, &bits); let mut mut_n_alt = mut_n; mut_n_alt.assign_bits(start, end, &bits); assert_eq!(mut_n_alt, mut_n); let mut mut_n_alt = n; assign_bits_naive::(&mut mut_n_alt, start, end, &bits); assert_eq!(mut_n_alt, mut_n); assert_eq!(mut_n.get_bits(start, end), bits.mod_power_of_2(end - start)); assert_eq!(mut_n >= T::ZERO, n >= T::ZERO); }, ); signed_unsigned_unsigned_triple_gen_var_1::().test_properties(|(n, bits, start)| { let mut mut_n = n; mut_n.assign_bits(start, start, &bits); assert_eq!(mut_n, n); }); signed_unsigned_pair_gen_var_1::().test_properties(|(n, start)| { let mut mut_n = n; mut_n.assign_bits( start + T::WIDTH - 1, start + (T::WIDTH << 1) - 1, &(if n >= T::ZERO { U::ZERO } else { U::MAX }), ); assert_eq!(mut_n, n); }); unsigned_pair_gen_var_7().test_properties(|(start, end)| { let mut n = T::ZERO; n.assign_bits(start, end, &U::ZERO); assert_eq!(n, T::ZERO); let mut n = T::NEGATIVE_ONE; n.assign_bits(start, min(end, start.saturating_add(T::WIDTH)), &U::MAX); assert_eq!(n, T::NEGATIVE_ONE); }); } #[test] fn assign_bits_properties() { apply_fn_to_unsigneds!(properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(properties_helper_signed); }