use super::select_tables::SELECT_TABLE;
#[cfg(target_pointer_width = "64")]
#[inline]
pub fn select_bit_u64(i: usize, bit_id: usize, unit: u64) -> usize {
let mut remaining = i;
let mut offset = 0usize;
for byte_idx in 0..8 {
let byte = ((unit >> (byte_idx * 8)) & 0xFF) as u8;
let byte_popcount = byte.count_ones() as usize;
if remaining < byte_popcount {
return bit_id + offset + SELECT_TABLE[remaining][byte as usize] as usize;
}
remaining -= byte_popcount;
offset += 8;
}
bit_id + 63
}
#[cfg(target_pointer_width = "32")]
#[inline]
pub fn select_bit_u32(i: usize, bit_id: usize, unit: u32) -> usize {
let mut remaining = i;
let mut offset = 0usize;
for byte_idx in 0..4 {
let byte = ((unit >> (byte_idx * 8)) & 0xFF) as u8;
let byte_popcount = byte.count_ones() as usize;
if remaining < byte_popcount {
return bit_id + offset + SELECT_TABLE[remaining][byte as usize] as usize;
}
remaining -= byte_popcount;
offset += 8;
}
bit_id + 31
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(target_pointer_width = "64")]
#[test]
fn test_select_bit_u64_basic() {
assert_eq!(select_bit_u64(0, 0, 0b00000001), 0);
assert_eq!(select_bit_u64(0, 0, 0b00000010), 1);
assert_eq!(select_bit_u64(0, 0, 0b00000011), 0);
assert_eq!(select_bit_u64(1, 0, 0b00000011), 1);
assert_eq!(select_bit_u64(0, 0, 0b00000101), 0);
assert_eq!(select_bit_u64(1, 0, 0b00000101), 2);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn test_select_bit_u64_offset() {
assert_eq!(select_bit_u64(0, 100, 0b00000001), 100);
assert_eq!(select_bit_u64(0, 100, 0b00000010), 101);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn test_select_bit_u64_multiple_bytes() {
assert_eq!(select_bit_u64(0, 0, 0x0101), 0);
assert_eq!(select_bit_u64(1, 0, 0x0101), 8);
assert_eq!(select_bit_u64(0, 0, 0xFF00), 8);
assert_eq!(select_bit_u64(7, 0, 0xFF00), 15);
}
#[cfg(target_pointer_width = "32")]
#[test]
fn test_select_bit_u32_basic() {
assert_eq!(select_bit_u32(0, 0, 0b00000001), 0);
assert_eq!(select_bit_u32(0, 0, 0b00000010), 1);
assert_eq!(select_bit_u32(0, 0, 0b00000011), 0);
assert_eq!(select_bit_u32(1, 0, 0b00000011), 1);
}
}