add int_log2 and checked_int_log2

This commit is contained in:
Trevor Spiteri 2020-04-11 17:44:09 +02:00
parent 060b58af13
commit 91bd73bca4
5 changed files with 95 additions and 0 deletions

View File

@ -74,6 +74,13 @@ The conversions supported cover the following cases.
## Whats 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

View File

@ -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)
==========================

View File

@ -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, "<U4>;
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, "<U4>;
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<i32> {
if self <= 0 {
None
} else {
Some(Self::INT_NBITS as i32 - 1 - self.leading_zeros() as i32)
}
}
}
if_signed! {
$Signedness;
comment! {

View File

@ -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<i32>;
/// 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<i32> }
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 }

View File

@ -503,6 +503,16 @@ impl<F: Fixed> Wrapping<F> {
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