#[macro_export]
macro_rules! max {
($arg:expr) => { $arg };
($arg1:expr, $($arg:expr),+) => {
core::cmp::max($arg1, $crate::max!( $($arg),+ ))
};
}
#[macro_export]
macro_rules! min {
($arg:expr) => { $arg };
($arg1:expr, $($arg:expr),+) => {
core::cmp::min($arg1, $crate::min!( $($arg),+ ))
};
}
#[doc(inline)]
pub use max;
#[doc(inline)]
pub use min;
pub trait Logarithm: Sized {
fn log2_ceil(self) -> Self;
fn log2(self) -> Self;
fn checked_log(self, base: Self) -> Option<Self>;
fn log(self, base: Self) -> Self;
}
impl Logarithm for usize {
#[inline(always)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
fn log2_ceil(self) -> usize {
usize_const_log2_ceil(self)
}
#[inline(always)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
fn log2(self) -> usize {
usize_const_log2(self)
}
#[inline(always)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
fn checked_log(self, base: usize) -> Option<Self> {
usize_const_checked_log(self, base)
}
#[inline(always)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
fn log(self, base: usize) -> Self {
match self.checked_log(base) {
Some(log) => log,
None => panic!("cannot take log base {base} of {self}"),
}
}
}
#[inline(always)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn usize_const_log2_ceil(n: usize) -> usize {
n.next_power_of_two().trailing_zeros() as usize
}
#[inline(always)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn usize_const_log2(n: usize) -> usize {
(usize::BITS - 1) as usize - n.leading_zeros() as usize
}
#[inline(always)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn usize_const_checked_log(mut n: usize, base: usize) -> Option<usize> {
if n == 0 || base <= 1 {
return None;
}
if base == 2 {
return Some(usize_const_log2(n));
}
let mut log = 0;
while n >= base {
n /= base;
log += 1;
}
Some(log)
}
#[cfg(all(test, not(loom)))]
#[test]
fn test_log2_ceil() {
assert_eq!(0, 0.log2_ceil());
assert_eq!(0, 1.log2_ceil());
assert_eq!(1, 2.log2_ceil());
assert_eq!(5, 32.log2_ceil());
assert_eq!(10, 1024.log2_ceil());
}