From: Joshua Simmons Date: Thu, 6 Oct 2022 21:52:46 +0000 (+0200) Subject: Fix log2 off-by-one error X-Git-Url: https://git.nega.tv//gitweb.cgi?a=commitdiff_plain;h=f0968ccb3daef6d30f2bcf4b4bcc540ee6733700;p=josh%2Fnarcissus Fix log2 off-by-one error --- diff --git a/narcissus-core/src/lib.rs b/narcissus-core/src/lib.rs index b593329..aea5deb 100644 --- a/narcissus-core/src/lib.rs +++ b/narcissus-core/src/lib.rs @@ -282,7 +282,7 @@ pub fn page_size() -> usize { /// Panics in debug mode when given a value of zero. pub fn log2_u32(value: u32) -> u32 { debug_assert_ne!(value, 0); - u32::BITS - value.leading_zeros() + u32::BITS - 1 - value.leading_zeros() } /// Returns the base 2 logarithm of the number, rounded down. @@ -292,7 +292,7 @@ pub fn log2_u32(value: u32) -> u32 { /// Panics in debug mode when given a value of zero. pub fn log2_u64(value: u64) -> u32 { debug_assert_ne!(value, 0); - u64::BITS - value.leading_zeros() + u64::BITS - 1 - value.leading_zeros() } /// Returns the base 2 logarithm of the number, rounded down. @@ -302,7 +302,7 @@ pub fn log2_u64(value: u64) -> u32 { /// Panics in debug mode when given a value of zero. pub fn log2_usize(value: usize) -> u32 { debug_assert_ne!(value, 0); - usize::BITS - value.leading_zeros() + usize::BITS - 1 - value.leading_zeros() } /// Returns the multiplicative inverse of the number. @@ -351,6 +351,10 @@ pub fn mod_inverse_u32(value: u32) -> u32 { mod tests { use std::ffi::CStr; + use super::log2_u32; + use super::log2_u64; + use super::log2_usize; + use super::cstr; use super::mod_inverse_u32; use super::mod_inverse_u64; @@ -363,6 +367,27 @@ mod tests { ); } + #[test] + fn test_log2() { + let mut x = 0; + for i in 0..u32::BITS { + x = (x << 1) | 1; + assert_eq!(log2_u32(x), i); + } + + let mut x = 0; + for i in 0..u64::BITS { + x = (x << 1) | 1; + assert_eq!(log2_u64(x), i); + } + + let mut x = 0; + for i in 0..usize::BITS { + x = (x << 1) | 1; + assert_eq!(log2_usize(x), i); + } + } + // Test is exhaustive and quite slow in debug mode. So ignore by default. #[test] #[ignore]