semx_bitops 0.1.60

位操作原语与动态大小位图
Documentation
//! bitops 原语测试

use semx_bitops::{
    BITS_PER_LONG, bit, bit_mask, bit_ull, bit_word, bits_to_longs, change_bit, clear_bit,
    deposit32, deposit64, extract8, extract16, extract32, extract64, find_first_bit,
    find_first_zero_bit, find_last_bit, find_next_bit, find_next_zero_bit, half_shuffle32,
    half_shuffle64, half_unshuffle32, half_unshuffle64, make_64bit_mask, set_bit,
    test_and_change_bit, test_and_clear_bit, test_and_set_bit, test_bit,
};

// ── 常量 ──

#[test]
fn bits_per_long() {
    #[cfg(target_pointer_width = "64")]
    assert_eq!(BITS_PER_LONG, 64);
    #[cfg(target_pointer_width = "32")]
    assert_eq!(BITS_PER_LONG, 32);
}

// ── 掩码与索引 ──

#[test]
fn bit_and_bit_ull() {
    assert_eq!(bit(0), 1);
    assert_eq!(bit(1), 2);
    assert_eq!(bit(2), 4);
    assert_eq!(bit(28), 0x1000_0000);
    assert_eq!(bit(31), 0x8000_0000);
    assert_eq!(bit_ull(63), 1u64 << 63);
    assert_eq!(bit_ull(0), 1);
}

#[test]
fn bit_mask_and_word() {
    assert_eq!(bit_mask(0), 1);
    assert_eq!(bit_mask(3), 8);
    assert_eq!(bit_mask(BITS_PER_LONG), 1);
    assert_eq!(bit_mask(BITS_PER_LONG + 3), 8);

    assert_eq!(bit_word(0), 0);
    assert_eq!(bit_word(BITS_PER_LONG - 1), 0);
    assert_eq!(bit_word(BITS_PER_LONG), 1);
    assert_eq!(bit_word(BITS_PER_LONG + 1), 1);
}

#[test]
fn bits_to_longs_cases() {
    assert_eq!(bits_to_longs(0), 0);
    assert_eq!(bits_to_longs(1), 1);
    assert_eq!(bits_to_longs(BITS_PER_LONG), 1);
    assert_eq!(bits_to_longs(BITS_PER_LONG + 1), 2);
    assert_eq!(bits_to_longs(BITS_PER_LONG * 3), 3);
}

#[test]
fn make_64bit_mask_cases() {
    assert_eq!(make_64bit_mask(0, 1), 1);
    assert_eq!(make_64bit_mask(0, 2), 0b11);
    assert_eq!(make_64bit_mask(1, 3), 0b1110);
    assert_eq!(make_64bit_mask(0, 64), u64::MAX);
    assert_eq!(make_64bit_mask(32, 32), 0xFFFF_FFFF_0000_0000);
    assert_eq!(make_64bit_mask(60, 4), 0xF000_0000_0000_0000);
    assert_eq!(make_64bit_mask(63, 1), 1u64 << 63);
}

// ── 单位操作 ──

#[test]
fn set_clear_change() {
    let mut bits = [0usize; 1];
    set_bit(0, &mut bits);
    assert_eq!(bits[0], 1);

    set_bit(5, &mut bits);
    assert_eq!(bits[0], 0b10_0001);

    clear_bit(0, &mut bits);
    assert_eq!(bits[0], 0b10_0000);

    change_bit(5, &mut bits);
    assert_eq!(bits[0], 0);

    change_bit(5, &mut bits);
    assert_eq!(bits[0], 0b10_0000);
}

#[test]
fn set_clear_change_cross_word() {
    let mut bits = [0usize; 2];
    set_bit(BITS_PER_LONG, &mut bits);
    assert_eq!(bits[0], 0);
    assert_eq!(bits[1], 1);

    clear_bit(BITS_PER_LONG, &mut bits);
    assert_eq!(bits[1], 0);

    change_bit(BITS_PER_LONG + 3, &mut bits);
    assert_eq!(bits[1], 8);
}

#[test]
fn test_and_set() {
    let mut bits = [0usize; 1];
    assert!(!test_and_set_bit(3, &mut bits));
    assert!(test_and_set_bit(3, &mut bits));
    assert_eq!(bits[0], 8);
}

#[test]
fn test_and_clear() {
    let mut bits = [0b1111usize; 1];
    assert!(test_and_clear_bit(1, &mut bits));
    assert!(!test_and_clear_bit(1, &mut bits));
    assert_eq!(bits[0], 0b1101);
}

#[test]
fn test_and_change() {
    let mut bits = [0usize; 1];
    assert!(!test_and_change_bit(2, &mut bits));
    assert!(test_bit(2, &bits));
    assert!(test_and_change_bit(2, &mut bits));
    assert!(!test_bit(2, &bits));
}

#[test]
fn test_bit_cases() {
    let bits = [0b1010usize; 1];
    assert!(!test_bit(0, &bits));
    assert!(test_bit(1, &bits));
    assert!(!test_bit(2, &bits));
    assert!(test_bit(3, &bits));
}

#[test]
fn test_bit_cross_word() {
    let mut bits = [0usize; 2];
    set_bit(BITS_PER_LONG + 5, &mut bits);
    assert!(!test_bit(5, &bits));
    assert!(test_bit(BITS_PER_LONG + 5, &bits));
    assert!(!test_bit(BITS_PER_LONG + 4, &bits));
}

// ── 查找 ──

#[test]
fn find_first_bit_cases() {
    let bits = [0usize; 2];
    assert_eq!(find_first_bit(&bits, 128), 128);

    let bits = [0, 1usize];
    assert_eq!(find_first_bit(&bits, 128), BITS_PER_LONG);

    let bits = [8usize; 1];
    assert_eq!(find_first_bit(&bits, BITS_PER_LONG), 3);
}

#[test]
fn find_first_zero_bit_cases() {
    let bits = [usize::MAX; 2];
    assert_eq!(find_first_zero_bit(&bits, 128), 128);

    let bits = [usize::MAX, usize::MAX - 1];
    assert_eq!(find_first_zero_bit(&bits, 128), BITS_PER_LONG);
}

#[test]
fn find_last_bit_cases() {
    let bits = [0usize; 2];
    assert_eq!(find_last_bit(&bits, 128), 128);

    let bits = [0, 1usize];
    assert_eq!(find_last_bit(&bits, 128), BITS_PER_LONG);

    let bits = [0b1010usize; 1];
    assert_eq!(find_last_bit(&bits, BITS_PER_LONG), 3);
}

#[test]
fn find_next_bit_cases() {
    let bits = [0b1010_1100usize; 1];
    assert_eq!(find_next_bit(&bits, BITS_PER_LONG, 0), 2);
    assert_eq!(find_next_bit(&bits, BITS_PER_LONG, 3), 3);
    assert_eq!(find_next_bit(&bits, BITS_PER_LONG, 4), 5);
    assert_eq!(find_next_bit(&bits, BITS_PER_LONG, 8), BITS_PER_LONG);
}

#[test]
fn find_next_zero_bit_cases() {
    let bits = [0b1111_0011usize; 1];
    assert_eq!(find_next_zero_bit(&bits, BITS_PER_LONG, 0), 2);
    assert_eq!(find_next_zero_bit(&bits, BITS_PER_LONG, 2), 2);
    assert_eq!(find_next_zero_bit(&bits, BITS_PER_LONG, 4), 8);
}

#[test]
fn find_next_bit_offset_past_end() {
    let bits = [usize::MAX; 1];
    assert_eq!(find_next_bit(&bits, BITS_PER_LONG, BITS_PER_LONG), BITS_PER_LONG);
    assert_eq!(find_next_bit(&bits, BITS_PER_LONG, BITS_PER_LONG + 10), BITS_PER_LONG);
    assert_eq!(find_next_zero_bit(&bits, BITS_PER_LONG, BITS_PER_LONG), BITS_PER_LONG);
}

#[test]
fn find_multi_word() {
    let mut bits = [0usize; 3];
    set_bit(BITS_PER_LONG + 5, &mut bits);
    set_bit(BITS_PER_LONG * 2 + 10, &mut bits);

    assert_eq!(find_first_bit(&bits, BITS_PER_LONG * 3), BITS_PER_LONG + 5);
    assert_eq!(find_last_bit(&bits, BITS_PER_LONG * 3), BITS_PER_LONG * 2 + 10);
    assert_eq!(find_next_bit(&bits, BITS_PER_LONG * 3, BITS_PER_LONG + 6), BITS_PER_LONG * 2 + 10);
}

// ── 位域提取与插入 ──

#[test]
fn extract_cases() {
    assert_eq!(extract8(0xC4, 1, 2), 2);
    assert_eq!(extract8(0xFF, 0, 8), 0xFF);

    assert_eq!(extract16(0x18C4, 4, 4), 0xC);
    assert_eq!(extract16(0xFFFF, 0, 16), 0xFFFF);

    assert_eq!(extract32(0x8000_008E, 1, 3), 7);
    assert_eq!(extract32(0xFFFF_FFFF, 0, 32), 0xFFFF_FFFF);

    assert_eq!(extract64(0x01A0_00F7_000C, 32, 8), 0xA0);
    assert_eq!(extract64(u64::MAX, 0, 64), u64::MAX);
}

#[test]
fn deposit_cases() {
    assert_eq!(deposit32(0x8000_008E, 4, 2, 1), 0x8000_009E);
    assert_eq!(deposit32(0, 0, 32, 0xFFFF_FFFF), 0xFFFF_FFFF);

    assert_eq!(deposit64(0x01A0_00F7_000C, 32, 2, 3), 0x01A3_00F7_000C);
    assert_eq!(deposit64(0, 0, 64, u64::MAX), u64::MAX);
}

#[test]
fn deposit_extract_roundtrip() {
    let val = deposit32(0, 8, 4, 0xA);
    assert_eq!(extract32(val, 8, 4), 0xA);

    let val = deposit64(0, 16, 8, 0xBE);
    assert_eq!(extract64(val, 16, 8), 0xBE);
}

// ── shuffle / unshuffle ──

#[test]
fn shuffle32_roundtrip() {
    let original = 0b1111u32;
    let shuffled = half_shuffle32(original);
    assert_eq!(shuffled, 0b101_0101);
    assert_eq!(half_unshuffle32(shuffled), original);
}

#[test]
fn shuffle64_roundtrip() {
    let original: u64 = 0b1111_0000_0000_0000_0000;
    let shuffled = half_shuffle64(original);
    assert_eq!(shuffled, 0x55_0000_0000);
    assert_eq!(half_unshuffle64(shuffled), original);
}

#[test]
fn find_size_zero() {
    let bits = [0usize; 0];
    assert_eq!(find_first_bit(&bits, 0), 0);
    assert_eq!(find_first_zero_bit(&bits, 0), 0);
    assert_eq!(find_last_bit(&bits, 0), 0);
    assert_eq!(find_next_bit(&bits, 0, 0), 0);
    assert_eq!(find_next_zero_bit(&bits, 0, 0), 0);
}

#[test]
fn shuffle_zero() {
    assert_eq!(half_shuffle32(0), 0);
    assert_eq!(half_unshuffle32(0), 0);
    assert_eq!(half_shuffle64(0), 0);
    assert_eq!(half_unshuffle64(0), 0);
}