use crate::natural::InnerNatural::{Large, Small};
use crate::natural::{Natural, bit_to_limb_count_floor, limb_to_bit_count};
use crate::platform::Limb;
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::logic::traits::{BitScan, TrailingZeros};
use malachite_base::slices::slice_leading_zeros;
pub_crate_test! {limbs_index_of_next_false_bit(xs: &[Limb], start: u64) -> u64 {
let starting_index = bit_to_limb_count_floor(start);
if starting_index >= xs.len() {
return start;
}
if let Some(result) = xs[starting_index].index_of_next_false_bit(start & Limb::WIDTH_MASK)
&& result != Limb::WIDTH
{
return limb_to_bit_count(starting_index) + result;
}
if starting_index == xs.len() - 1 {
return limb_to_bit_count(xs.len());
}
let false_index = starting_index
+ 1
+ xs[starting_index + 1..]
.iter()
.take_while(|&&y| y == Limb::MAX)
.count();
let mut result_offset = limb_to_bit_count(false_index);
if false_index != xs.len() {
result_offset += TrailingZeros::trailing_zeros(!xs[false_index]);
}
result_offset
}}
pub_crate_test! {limbs_index_of_next_true_bit(xs: &[Limb], start: u64) -> Option<u64> {
let starting_index = bit_to_limb_count_floor(start);
if starting_index >= xs.len() {
None
} else if let Some(result) = xs[starting_index].index_of_next_true_bit(start & Limb::WIDTH_MASK)
{
Some(limb_to_bit_count(starting_index) + result)
} else if starting_index == xs.len() - 1 {
None
} else {
let true_index = starting_index + 1 + slice_leading_zeros(&xs[starting_index + 1..]);
if true_index == xs.len() {
None
} else {
let result_offset = limb_to_bit_count(true_index);
Some(
result_offset
.checked_add(TrailingZeros::trailing_zeros(xs[true_index]))
.unwrap(),
)
}
}
}}
impl BitScan for &Natural {
fn index_of_next_false_bit(self, start: u64) -> Option<u64> {
match self {
Natural(Small(small)) => small.index_of_next_false_bit(start),
Natural(Large(limbs)) => Some(limbs_index_of_next_false_bit(limbs, start)),
}
}
fn index_of_next_true_bit(self, start: u64) -> Option<u64> {
match self {
Natural(Small(small)) => small.index_of_next_true_bit(start),
Natural(Large(limbs)) => limbs_index_of_next_true_bit(limbs, start),
}
}
}