// 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::signeds::PrimitiveSigned;
use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
use malachite_base::num::logic::traits::{CountOnes, CountZeros};
use malachite_base::test_util::generators::{
signed_gen, signed_gen_var_2, signed_gen_var_4, signed_pair_gen, signed_pair_gen_var_1,
signed_triple_gen_var_3, unsigned_gen, unsigned_pair_gen_var_27, unsigned_triple_gen_var_19,
};
#[test]
pub fn test_hamming_distance() {
fn test(x: T, y: T, out: u64) {
assert_eq!(x.hamming_distance(y), out);
}
test(123u16, 456u16, 6);
test(0xffffu32, 0xffff0000u32, 32);
test(0xffffu32, u32::MAX, 16);
test(0xffff0000u32, u32::MAX, 16);
}
#[test]
pub fn test_checked_hamming_distance() {
fn test(x: T, y: T, out: Option) {
assert_eq!(x.checked_hamming_distance(y), out);
}
test(123i32, 456i32, Some(6));
test(-123i32, -456i32, Some(7));
test(0i8, 127i8, Some(7));
test(0i8, -1i8, None);
test(-1i8, -128i8, Some(7));
test(0i128, i128::MAX, Some(127));
test(0i128, -1i128, None);
test(-1i128, i128::MIN, Some(127));
test(0xffffi32, 0x7fff0000i32, Some(31));
test(0xffffi32, i32::MAX, Some(15));
test(0x7fff0000i32, i32::MAX, Some(16));
}
fn hamming_distance_properties_helper() {
unsigned_pair_gen_var_27::().test_properties(|(x, y)| {
let distance = x.hamming_distance(y);
assert_eq!(y.hamming_distance(x), distance);
assert_eq!(distance == 0, x == y);
assert_eq!(CountOnes::count_ones(x ^ y), distance);
assert_eq!((!x).hamming_distance(!y), distance);
});
unsigned_triple_gen_var_19::().test_properties(|(x, y, z)| {
assert!(x.hamming_distance(z) <= x.hamming_distance(y) + y.hamming_distance(z));
});
unsigned_gen::().test_properties(|x| {
assert_eq!(x.hamming_distance(x), 0);
assert_eq!(x.hamming_distance(!x), T::WIDTH);
assert_eq!(x.hamming_distance(T::ZERO), CountOnes::count_ones(x));
assert_eq!(T::ZERO.hamming_distance(x), CountOnes::count_ones(x));
});
}
#[test]
fn hamming_distance_properties() {
apply_fn_to_unsigneds!(hamming_distance_properties_helper);
}
fn checked_hamming_distance_properties_helper() {
signed_pair_gen::().test_properties(|(x, y)| {
let distance = x.checked_hamming_distance(y);
assert_eq!(y.checked_hamming_distance(x), distance);
assert_eq!(distance == Some(0), x == y);
assert_eq!((!x).checked_hamming_distance(!y), distance);
});
signed_pair_gen_var_1::().test_properties(|(x, y)| {
let distance = x.checked_hamming_distance(y).unwrap();
assert_eq!(y.checked_hamming_distance(x).unwrap(), distance);
assert_eq!(distance == 0, x == y);
assert_eq!(CountOnes::count_ones(x ^ y), distance);
assert_eq!((!x).checked_hamming_distance(!y).unwrap(), distance);
});
signed_triple_gen_var_3::().test_properties(|(x, y, z)| {
assert!(
x.checked_hamming_distance(z).unwrap()
<= x.checked_hamming_distance(y).unwrap() + y.checked_hamming_distance(z).unwrap()
);
});
signed_gen::().test_properties(|x| {
assert_eq!(x.checked_hamming_distance(x), Some(0));
assert_eq!(x.checked_hamming_distance(!x), None);
});
signed_gen_var_2::().test_properties(|x| {
assert_eq!(
x.checked_hamming_distance(T::ZERO),
Some(CountOnes::count_ones(x))
);
assert_eq!(
T::ZERO.checked_hamming_distance(x),
Some(CountOnes::count_ones(x))
);
});
signed_gen_var_4::().test_properties(|x| {
assert_eq!(
x.checked_hamming_distance(T::NEGATIVE_ONE),
Some(CountZeros::count_zeros(x))
);
assert_eq!(
T::NEGATIVE_ONE.checked_hamming_distance(x),
Some(CountZeros::count_zeros(x))
);
});
}
#[test]
fn checked_hamming_distance_properties() {
apply_fn_to_signeds!(checked_hamming_distance_properties_helper);
}