diff --git a/src/lib.rs b/src/lib.rs index 6386e26..3ffb0c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1303,6 +1303,9 @@ pub struct Ones<'a> { } impl<'a> Ones<'a> { + /// Clears the least significant set bit and returns its index. + /// + /// If `n` is zero, returns the number of bits in a block and leaves it unchanged. #[inline] pub fn last_positive_bit_and_unset(n: &mut usize) -> usize { // Find the last set bit using x & -x @@ -1312,7 +1315,7 @@ impl<'a> Ones<'a> { let position = last_bit.trailing_zeros(); // Unset the last set bit - *n &= *n - 1; + *n &= n.wrapping_sub(1); position as usize } @@ -1525,6 +1528,9 @@ pub struct IntoOnes { } impl IntoOnes { + /// Clears the least significant set bit and returns its index. + /// + /// If `n` is zero, returns the number of bits in a block and leaves it unchanged. #[inline] pub fn last_positive_bit_and_unset(n: &mut Block) -> usize { // Find the last set bit using x & -x @@ -1534,7 +1540,7 @@ impl IntoOnes { let position = last_bit.trailing_zeros(); // Unset the last set bit - *n &= *n - 1; + *n &= n.wrapping_sub(1); position as usize } diff --git a/tests/tests.rs b/tests/tests.rs index 82ba13f..ff77f4b 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1359,3 +1359,35 @@ fn clone() { assert_eq!(&fb, &fb_clone_from_same); assert_eq!(&fb, &fb_clone_from_bigger); } + +fn check_last_positive_bit_and_unset(unset: fn(&mut usize) -> usize) { + let mut value = 0; + assert_eq!(unset(&mut value), BITS); + assert_eq!(value, 0); + + for bit in 0..BITS { + value = 1 << bit; + assert_eq!(unset(&mut value), bit); + assert_eq!(value, 0); + } + + value = usize::MAX; + for bit in 0..BITS { + assert_eq!(unset(&mut value), bit); + assert_eq!(value.count_ones() as usize, BITS - bit - 1); + } + assert_eq!(unset(&mut value), BITS); + assert_eq!(value, 0); +} + +#[test] +#[cfg_attr(target_family = "wasm", wasm_bindgen_test)] +fn ones_last_positive_bit_and_unset() { + check_last_positive_bit_and_unset(Ones::last_positive_bit_and_unset); +} + +#[test] +#[cfg_attr(target_family = "wasm", wasm_bindgen_test)] +fn into_ones_last_positive_bit_and_unset() { + check_last_positive_bit_and_unset(IntoOnes::last_positive_bit_and_unset); +}