// 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::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_pair_gen, signed_signed_signed_unsigned_quadruple_gen_var_1, signed_signed_unsigned_triple_gen_var_1, signed_signed_unsigned_triple_gen_var_2, signed_signed_unsigned_triple_gen_var_3, signed_unsigned_pair_gen_var_1, unsigned_pair_gen_var_2, unsigned_pair_gen_var_27, unsigned_quadruple_gen_var_2, unsigned_triple_gen_var_10, unsigned_triple_gen_var_4, unsigned_triple_gen_var_9, }; fn eq_mod_power_of_2_primitive_helper() { let test = |n: T, other, pow, out| { assert_eq!(n.eq_mod_power_of_2(other, pow), out); }; test(T::ZERO, T::power_of_2(T::WIDTH >> 1), T::WIDTH >> 1, true); test( T::ZERO, T::power_of_2(T::WIDTH >> 1), (T::WIDTH >> 1) + 1, false, ); test(T::exact_from(13), T::exact_from(21), 0, true); test(T::exact_from(13), T::exact_from(21), 1, true); test(T::exact_from(13), T::exact_from(21), 2, true); test(T::exact_from(13), T::exact_from(21), 3, true); test(T::exact_from(13), T::exact_from(21), 4, false); test(T::exact_from(13), T::exact_from(21), 100, false); test(T::MAX, T::MAX, T::WIDTH, true); test(T::MAX, T::MAX, 100, true); if T::WIDTH >= u64::WIDTH { test(T::exact_from(1000000000001u64), T::ONE, 12, true); test(T::exact_from(1000000000001u64), T::ONE, 13, false); test( T::exact_from(281474976710672u64), T::exact_from(844424930131984u64), 49, true, ); test( T::exact_from(281474976710672u64), T::exact_from(844424930131984u64), 50, false, ); } } fn eq_mod_power_of_2_signed_helper() { let test = |n: T, other, pow, out| { assert_eq!(n.eq_mod_power_of_2(other, pow), out); }; test(T::ZERO, -T::power_of_2(T::WIDTH >> 1), T::WIDTH >> 1, true); test( T::ZERO, -T::power_of_2(T::WIDTH >> 1), (T::WIDTH >> 1) + 1, false, ); test(T::exact_from(-13), T::exact_from(27), 0, true); test(T::exact_from(-13), T::exact_from(27), 1, true); test(T::exact_from(-13), T::exact_from(27), 2, true); test(T::exact_from(-13), T::exact_from(27), 3, true); test(T::exact_from(-13), T::exact_from(27), 4, false); test(T::exact_from(-13), T::exact_from(27), 100, false); test(T::exact_from(13), T::exact_from(-27), 0, true); test(T::exact_from(13), T::exact_from(-27), 1, true); test(T::exact_from(13), T::exact_from(-27), 2, true); test(T::exact_from(13), T::exact_from(-27), 3, true); test(T::exact_from(13), T::exact_from(-27), 4, false); test(T::exact_from(13), T::exact_from(-27), 100, false); test( T::NEGATIVE_ONE, T::power_of_2(T::WIDTH >> 1) - T::ONE, T::WIDTH >> 1, true, ); test( T::power_of_2(T::WIDTH >> 1) - T::ONE, T::NEGATIVE_ONE, T::WIDTH >> 1, true, ); if T::WIDTH >= u64::WIDTH { test( T::exact_from(-1000000000001i64), T::exact_from(4095), 13, true, ); test( T::exact_from(-1000000000001i64), T::exact_from(4095), 14, false, ); test( T::exact_from(1000000000001i64), T::exact_from(-4095), 13, true, ); test( T::exact_from(1000000000001i64), T::exact_from(-4095), 14, false, ); } test(T::exact_from(-13), T::exact_from(-21), 0, true); test(T::exact_from(-13), T::exact_from(-21), 1, true); test(T::exact_from(-13), T::exact_from(-21), 2, true); test(T::exact_from(-13), T::exact_from(-21), 3, true); test(T::exact_from(-13), T::exact_from(-21), 4, false); test(T::exact_from(-13), T::exact_from(-21), 100, false); test( T::power_of_2(T::WIDTH >> 1) - T::ONE, T::power_of_2(T::WIDTH >> 1) - T::ONE, T::WIDTH >> 1, true, ); if T::WIDTH >= u64::WIDTH { test(T::exact_from(-1000000000001i64), T::NEGATIVE_ONE, 12, true); test(T::exact_from(-1000000000001i64), T::NEGATIVE_ONE, 13, false); test( T::exact_from(-281474976710672i64), T::exact_from(-844424930131984i64), 49, true, ); test( T::exact_from(-281474976710672i64), T::exact_from(-844424930131984i64), 50, false, ); } if T::WIDTH >= u128::WIDTH { test( T::exact_from(1311693408901639117i128), T::exact_from(-17135050664807912499i128), 64, true, ); test( T::exact_from(1311693408901639117i128), T::exact_from(-17135050663395328000i128), 64, false, ); test( T::exact_from(1311693408901639117i128), T::exact_from(-17135050664807912499i128), 65, false, ); test( T::exact_from(1311693408901639117i128), T::exact_from(-17135050664807912499i128), 128, false, ); test( T::exact_from(5633680281231555440641310720i128), T::exact_from(-5634717283396403096794955776i128), 80, true, ); test( T::exact_from(-1311693408901639117i128), T::exact_from(17135050664807912499i128), 64, true, ); test( T::exact_from(-1311693408901639117i128), T::exact_from(17135050663395328000i128), 64, false, ); test( T::exact_from(-1311693408901639117i128), T::exact_from(17135050664807912499i128), 65, false, ); test( T::exact_from(-1311693408901639117i128), T::exact_from(17135050664807912499i128), 128, false, ); test( T::exact_from(-5633680281231555440641310720i128), T::exact_from(5634717283396403096794955776i128), 80, true, ); } } #[test] fn test_eq_mod_power_of_2() { apply_fn_to_primitive_ints!(eq_mod_power_of_2_primitive_helper); apply_fn_to_signeds!(eq_mod_power_of_2_signed_helper); } fn eq_mod_power_of_2_properties_helper_unsigned() { unsigned_triple_gen_var_4::().test_properties(|(x, y, pow)| { let eq_mod_power_of_2 = x.eq_mod_power_of_2(y, pow); assert_eq!(y.eq_mod_power_of_2(x, pow), eq_mod_power_of_2); assert_eq!( x.mod_power_of_2(pow) == y.mod_power_of_2(pow), eq_mod_power_of_2 ); }); unsigned_triple_gen_var_9::().test_properties(|(x, y, pow)| { assert!(x.eq_mod_power_of_2(y, pow)); assert!(y.eq_mod_power_of_2(x, pow)); assert_eq!(x.mod_power_of_2(pow), y.mod_power_of_2(pow)); }); unsigned_triple_gen_var_10::().test_properties(|(x, y, pow)| { assert!(!x.eq_mod_power_of_2(y, pow)); assert!(!y.eq_mod_power_of_2(x, pow)); assert_ne!(x.mod_power_of_2(pow), y.mod_power_of_2(pow)); }); unsigned_pair_gen_var_2::().test_properties(|(n, pow)| { assert!(n.eq_mod_power_of_2(n, pow)); assert_eq!( n.eq_mod_power_of_2(T::ZERO, pow), n.divisible_by_power_of_2(pow) ); assert_eq!( T::ZERO.eq_mod_power_of_2(n, pow), n.divisible_by_power_of_2(pow) ); }); unsigned_quadruple_gen_var_2::().test_properties(|(x, y, z, pow)| { if x.eq_mod_power_of_2(y, pow) && y.eq_mod_power_of_2(z, pow) { assert!(x.eq_mod_power_of_2(z, pow)); } }); unsigned_pair_gen_var_27::().test_properties(|(x, y)| { assert!(x.eq_mod_power_of_2(y, 0)); }); } fn eq_mod_power_of_2_properties_helper_signed< U: PrimitiveUnsigned + WrappingFrom, S: PrimitiveSigned + WrappingFrom, >() { signed_signed_unsigned_triple_gen_var_2::().test_properties(|(x, y, pow)| { let eq_mod_power_of_2 = x.eq_mod_power_of_2(y, pow); assert_eq!(y.eq_mod_power_of_2(x, pow), eq_mod_power_of_2); assert_eq!( U::wrapping_from(x).mod_power_of_2(pow) == U::wrapping_from(y).mod_power_of_2(pow), eq_mod_power_of_2, ); }); signed_signed_unsigned_triple_gen_var_1::().test_properties(|(x, y, pow)| { assert!(x.eq_mod_power_of_2(y, pow)); assert!(y.eq_mod_power_of_2(x, pow)); assert_eq!( U::wrapping_from(x).mod_power_of_2(pow), U::wrapping_from(y).mod_power_of_2(pow), ); }); signed_signed_unsigned_triple_gen_var_3::().test_properties(|(x, y, pow)| { assert!(!x.eq_mod_power_of_2(y, pow)); assert!(!y.eq_mod_power_of_2(x, pow)); assert_ne!( U::wrapping_from(x).mod_power_of_2(pow), U::wrapping_from(y).mod_power_of_2(pow), ); }); signed_unsigned_pair_gen_var_1::().test_properties(|(n, pow)| { assert!(n.eq_mod_power_of_2(n, pow)); assert_eq!( n.eq_mod_power_of_2(S::ZERO, pow), n.divisible_by_power_of_2(pow) ); assert_eq!( S::ZERO.eq_mod_power_of_2(n, pow), n.divisible_by_power_of_2(pow) ); }); signed_signed_signed_unsigned_quadruple_gen_var_1::().test_properties( |(x, y, z, pow)| { if x.eq_mod_power_of_2(y, pow) && y.eq_mod_power_of_2(z, pow) { assert!(x.eq_mod_power_of_2(z, pow)); } }, ); signed_pair_gen::().test_properties(|(x, y)| { assert!(x.eq_mod_power_of_2(y, 0)); }); } #[test] fn eq_mod_power_of_2_properties() { apply_fn_to_unsigneds!(eq_mod_power_of_2_properties_helper_unsigned); apply_fn_to_unsigned_signed_pairs!(eq_mod_power_of_2_properties_helper_signed); }