// 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::conversion::traits::{ExactFrom, WrappingFrom};
use malachite_base::num::logic::traits::{BitIterable, SignificantBits};
use malachite_base::test_util::common::test_double_ended_iterator_size_hint;
use malachite_base::test_util::generators::{
signed_bool_vec_pair_gen_var_1, signed_gen, signed_unsigned_pair_gen_var_1,
unsigned_bool_vec_pair_gen_var_1, unsigned_gen, unsigned_gen_var_5, unsigned_pair_gen_var_2,
};
use std::cmp::Ordering::*;
use std::ops::Index;
#[test]
pub fn test_bits() {
let mut bits = 105u8.bits();
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next_back(), Some(true));
assert_eq!(bits.next_back(), Some(true));
assert_eq!(bits.next_back(), Some(false));
assert_eq!(bits.next(), Some(false));
assert_eq!(bits.next(), Some(false));
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next(), None);
assert_eq!(bits.next_back(), None);
assert_eq!(bits[0], true);
assert_eq!(bits[1], false);
assert_eq!(bits[2], false);
assert_eq!(bits[3], true);
assert_eq!(bits[4], false);
assert_eq!(bits[5], true);
assert_eq!(bits[6], true);
assert_eq!(bits[7], false);
assert_eq!(bits[8], false);
let mut bits = 105u32.bits();
assert_eq!(bits.next_back(), Some(true));
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next(), Some(false));
assert_eq!(bits.next(), Some(false));
assert_eq!(bits.next_back(), Some(true));
assert_eq!(bits.next_back(), Some(false));
assert_eq!(bits.next_back(), Some(true));
assert_eq!(bits.next(), None);
assert_eq!(bits.next_back(), None);
let mut bits = (-105i8).bits();
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next_back(), Some(true));
assert_eq!(bits.next_back(), Some(false));
assert_eq!(bits.next_back(), Some(false));
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next(), Some(false));
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next(), None);
assert_eq!(bits.next_back(), None);
assert_eq!(bits[0], true);
assert_eq!(bits[1], true);
assert_eq!(bits[2], true);
assert_eq!(bits[3], false);
assert_eq!(bits[4], true);
assert_eq!(bits[5], false);
assert_eq!(bits[6], false);
assert_eq!(bits[7], true);
assert_eq!(bits[8], true);
let mut bits = (-105i32).bits();
assert_eq!(bits.next_back(), Some(true));
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next(), Some(true));
assert_eq!(bits.next_back(), Some(false));
assert_eq!(bits.next_back(), Some(false));
assert_eq!(bits.next_back(), Some(true));
assert_eq!(bits.next_back(), Some(false));
assert_eq!(bits.next(), None);
assert_eq!(bits.next_back(), None);
}
fn bits_properties_helper_unsigned()
where
T::BitIterator: Clone + Index,
{
unsigned_gen::().test_properties(|n| {
test_double_ended_iterator_size_hint(n.bits(), usize::exact_from(n.significant_bits()));
});
unsigned_bool_vec_pair_gen_var_1::().test_properties(|(n, bs)| {
let mut bits = n.bits();
let mut bit_vec = Vec::new();
let mut i = 0;
for b in bs {
if b {
bit_vec.insert(i, bits.next().unwrap());
i += 1;
} else {
bit_vec.insert(i, bits.next_back().unwrap());
}
}
assert!(bits.next().is_none());
assert!(bits.next_back().is_none());
assert_eq!(n.to_bits_asc(), bit_vec);
});
unsigned_pair_gen_var_2::().test_properties(|(n, u)| {
if u < n.significant_bits() {
assert_eq!(n.bits()[u], n.to_bits_asc()[usize::exact_from(u)]);
} else {
assert_eq!(n.bits()[u], false);
}
});
unsigned_gen_var_5().test_properties(|u| {
assert_eq!(T::ZERO.bits()[u], false);
});
}
fn bits_properties_helper_signed()
where
T::BitIterator: Clone + Index,
::Output: PrimitiveUnsigned + WrappingFrom,
{
signed_gen::().test_properties(|i| {
let unsigned = ::Output::wrapping_from(i);
let significant_bits = match i.sign() {
Equal => 0,
Greater => unsigned.significant_bits() + 1,
Less => (!unsigned).significant_bits() + 1,
};
test_double_ended_iterator_size_hint(i.bits(), usize::exact_from(significant_bits));
});
signed_bool_vec_pair_gen_var_1::().test_properties(|(n, bs)| {
let mut bits = n.bits();
let mut bit_vec = Vec::new();
let mut i = 0;
for b in bs {
if b {
bit_vec.insert(i, bits.next().unwrap());
i += 1;
} else {
bit_vec.insert(i, bits.next_back().unwrap());
}
}
assert!(bits.next().is_none());
assert!(bits.next_back().is_none());
assert_eq!(n.to_bits_asc(), bit_vec);
});
signed_unsigned_pair_gen_var_1::().test_properties(|(n, u)| {
if u < n.significant_bits() {
assert_eq!(n.bits()[u], n.to_bits_asc()[usize::exact_from(u)]);
} else {
assert_eq!(n.bits()[u], n < T::ZERO);
}
});
unsigned_gen_var_5().test_properties(|u| {
assert_eq!(T::ZERO.bits()[u], false);
});
}
#[test]
fn bits_properties() {
apply_fn_to_unsigneds!(bits_properties_helper_unsigned);
apply_fn_to_signeds!(bits_properties_helper_signed);
}