diff --git a/README.md b/README.md index 075a5e9..d4b87f6 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,13 @@ The conversions supported cover the following cases. ## What’s new +### Version 0.5.5 news (unreleased) + + * The methods [`int_log2`] and [`checked_int_log2`] were added to + all fixed-point types and to the [`Fixed`] trait. + * The method [`int_log2`][wril] was added to the [`Wrapping`] + wrapper. + ### Version 0.5.4 news (2020-02-21) * Bug fix: [`rem_euclid_int`] and its checked versions were handling @@ -112,9 +119,11 @@ The conversions supported cover the following cases. [`Rem`]: https://doc.rust-lang.org/nightly/core/ops/trait.Rem.html [`Wrapping`]: https://docs.rs/fixed/0.5.4/fixed/struct.Wrapping.html [`checked_div_euclid`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.checked_div_euclid +[`checked_int_log2`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.checked_int_log2 [`checked_rem_euclid`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.checked_rem_euclid [`checked_rem`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.checked_rem [`div_euclid`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.div_euclid +[`int_log2`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.int_log2 [`overflowing_div_euclid`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.overflowing_div_euclid [`overflowing_rem_int`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.overflowing_rem_int [`rem_euclid_int`]: https://docs.rs/fixed/0.5.4/fixed/struct.FixedI32.html#method.rem_euclid_int @@ -128,6 +137,7 @@ The conversions supported cover the following cases. [wdei]: https://docs.rs/fixed/0.5.4/fixed/struct.Wrapping.html#method.div_euclid_int [wre]: https://docs.rs/fixed/0.5.4/fixed/struct.Wrapping.html#method.rem_euclid [wrei]: https://docs.rs/fixed/0.5.4/fixed/struct.Wrapping.html#method.rem_euclid_int +[wril]: https://docs.rs/fixed/0.5.4/fixed/struct.Wrapping.html#method.int_log2 ### Other releases diff --git a/RELEASES.md b/RELEASES.md index a26e3ae..9c33277 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5,6 +5,13 @@ modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. --> +Version 0.5.5 (unreleased) +========================== + + * The methods `int_log2` and `checked_int_log2` were added to all + fixed-point types and to the `Fixed` trait. + * The method `int_log2` was added to the `Wrapping` wrapper. + Version 0.5.4 (2020-02-21) ========================== diff --git a/src/macros_frac.rs b/src/macros_frac.rs index 266782b..a423ba8 100644 --- a/src/macros_frac.rs +++ b/src/macros_frac.rs @@ -100,6 +100,59 @@ assert_eq!(Fix::frac_nbits(), 6); fixed_from_to! { $Fixed[$s_fixed]($Inner[$s_inner], $s_nbits), $Signedness } fixed_round! { $Fixed[$s_fixed]($s_nbits), $Signedness } + comment! { + "Integer base-2 logarithm, rounded down. + +# Panics + +Panics if the fixed-point number is ", if_signed_unsigned!($Signedness, "≤ 0", "zero"), ". + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +assert_eq!(Fix::from_num(4).int_log2(), 2); +assert_eq!(Fix::from_num(3.9375).int_log2(), 1); +assert_eq!(Fix::from_num(0.25).int_log2(), -2); +assert_eq!(Fix::from_num(0.1875).int_log2(), -3); +``` +"; + #[inline] + pub fn int_log2(self) -> i32 { + self.checked_int_log2().expect("log of non-positive number") + } + } + + comment! { + "Checked integer base-2 logarithm, rounded down. +Returns the logarithm or [`None`] if the fixed-point number is +", if_signed_unsigned!($Signedness, "≤ 0", "zero"), ". + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +assert_eq!(Fix::from_num(0).checked_int_log2(), None); +assert_eq!(Fix::from_num(4).checked_int_log2(), Some(2)); +assert_eq!(Fix::from_num(3.9375).checked_int_log2(), Some(1)); +assert_eq!(Fix::from_num(0.25).checked_int_log2(), Some(-2)); +assert_eq!(Fix::from_num(0.1875).checked_int_log2(), Some(-3)); +``` + +[`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None +"; + #[inline] + pub fn checked_int_log2(self) -> Option { + if self <= 0 { + None + } else { + Some(Self::INT_NBITS as i32 - 1 - self.leading_zeros() as i32) + } + } + } + if_signed! { $Signedness; comment! { diff --git a/src/traits.rs b/src/traits.rs index f929065..a29bf7e 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -614,6 +614,19 @@ where /// Returns the number of trailing zeros in the binary representation. fn trailing_zeros(self) -> u32; + /// Integer base-2 logarithm, rounded down. + /// + /// # Panics + /// + /// Panics if the fixed-point number is ≤ 0. + fn int_log2(self) -> i32; + + /// Checked integer base-2 logarithm, rounded down. Returns the + /// logarithm or [`None`] if the fixed-point number is ≤ 0. + /// + /// [`None`]: https://doc.rust-lang.org/nightly/core/option/enum.Option.html#variant.None + fn checked_int_log2(self) -> Option; + /// Shifts to the left by `n` bits, wrapping the truncated bits to the right end. fn rotate_left(self, n: u32) -> Self; @@ -1822,6 +1835,8 @@ macro_rules! impl_fixed { trait_delegate! { fn count_zeros(self) -> u32 } trait_delegate! { fn leading_zeros(self) -> u32 } trait_delegate! { fn trailing_zeros(self) -> u32 } + trait_delegate! { fn int_log2(self) -> i32 } + trait_delegate! { fn checked_int_log2(self) -> Option } trait_delegate! { fn rotate_left(self, n: u32) -> Self } trait_delegate! { fn rotate_right(self, n: u32) -> Self } trait_delegate! { fn div_euclid(self, rhs: Self) -> Self } diff --git a/src/wrapping.rs b/src/wrapping.rs index 41c40d1..bc68ca3 100644 --- a/src/wrapping.rs +++ b/src/wrapping.rs @@ -503,6 +503,16 @@ impl Wrapping { self.0.trailing_zeros() } + /// Integer base-2 logarithm, rounded down. + /// + /// # Panics + /// + /// Panics if the fixed-point number is ≤ 0. + #[inline] + pub fn int_log2(self) -> i32 { + self.0.int_log2() + } + /// Shifts to the left by `n` bits, wrapping the truncated bits to the right end. /// /// # Examples