Skip to content

Commit

Permalink
feat: Implement checked_ilog* methods
Browse files Browse the repository at this point in the history
  • Loading branch information
sorairolake committed Nov 15, 2024
1 parent 476af2c commit 55fa163
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 5 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- aarch64-apple-darwin
- x86_64-pc-windows-msvc
toolchain:
- 1.61.0 # MSRV
- 1.67.0 # MSRV
- stable
include:
- target: x86_64-unknown-linux-gnu
Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:
- aarch64-apple-darwin
- x86_64-pc-windows-msvc
toolchain:
- 1.61.0
- 1.67.0
- stable
include:
- target: x86_64-unknown-linux-gnu
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ All notable changes to this project will be documented in this file.
The format is based on https://keepachangelog.com/[Keep a Changelog], and this
project adheres to https://semver.org/[Semantic Versioning].

== {compare-url}/v0.1.1\...HEAD[Unreleased]

=== Added

* Add `BitInt::checked_ilog` and `BitUint::checked_ilog`
({pull-request-url}/12[#12])
* Add `BitInt::checked_ilog2` and `BitUint::checked_ilog2`
({pull-request-url}/12[#12])
* Add `BitInt::checked_ilog10` and `BitUint::checked_ilog10`
({pull-request-url}/12[#12])

=== Changed

* Bump MSRV to 1.67.0 ({pull-request-url}/12[#12])

== {compare-url}/v0.1.0\...v0.1.1[0.1.1] - 2024-11-14

=== Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "bit-int"
version = "0.1.1"
authors = ["Shun Sakai <sorairolake@protonmail.ch>"]
edition = "2021"
rust-version = "1.61.0"
rust-version = "1.67.0"
description = "An arbitrary fixed bit-width integer library"
documentation = "https://docs.rs/bit-int"
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ See the [documentation][docs-url] for more details.

## Minimum supported Rust version

The minimum supported Rust version (MSRV) of this library is v1.61.0.
The minimum supported Rust version (MSRV) of this library is v1.67.0.

## Source code

Expand Down
42 changes: 42 additions & 0 deletions benches/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,48 @@ fn checked_rem_bit_uint(b: &mut Bencher) {
b.iter(|| n.checked_rem(2));
}

#[bench]
fn checked_ilog_bit_int(b: &mut Bencher) {
let n = BitI32::<31>::new(5).unwrap();

b.iter(|| n.checked_ilog(5));
}

#[bench]
fn checked_ilog_bit_uint(b: &mut Bencher) {
let n = BitU32::<31>::new(5).unwrap();

b.iter(|| n.checked_ilog(5));
}

#[bench]
fn checked_ilog2_bit_int(b: &mut Bencher) {
let n = BitI32::<31>::new(2).unwrap();

b.iter(|| n.checked_ilog2());
}

#[bench]
fn checked_ilog2_bit_uint(b: &mut Bencher) {
let n = BitU32::<31>::new(2).unwrap();

b.iter(|| n.checked_ilog2());
}

#[bench]
fn checked_ilog10_bit_int(b: &mut Bencher) {
let n = BitI32::<31>::new(10).unwrap();

b.iter(|| n.checked_ilog10());
}

#[bench]
fn checked_ilog10_bit_uint(b: &mut Bencher) {
let n = BitU32::<31>::new(10).unwrap();

b.iter(|| n.checked_ilog10());
}

#[bench]
fn checked_neg_bit_int(b: &mut Bencher) {
let n = BitI32::<31>::new(5).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion clippy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
#
# SPDX-License-Identifier: Apache-2.0 OR MIT

msrv = "1.61.0"
msrv = "1.67.0"
99 changes: 99 additions & 0 deletions src/bit_int/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,65 @@ macro_rules! impl_ops {
}
}

/// Returns the logarithm of the number with respect to an arbitrary base,
/// rounded down.
///
/// Returns [`None`] if the number is negative or zero, or if the base is
/// not at least 2.
///
/// # Examples
///
/// ```
/// # use bit_int::BitInt;
/// #
#[doc = concat!("let n = BitInt::<", stringify!($T), ", 4>::new(5).unwrap();")]
///
/// assert_eq!(n.checked_ilog(5), Some(1));
/// ```
#[must_use]
#[inline]
pub const fn checked_ilog(self, base: $T) -> Option<u32> {
self.get().checked_ilog(base)
}

/// Returns the base 2 logarithm of the number, rounded down.
///
/// Returns [`None`] if the number is negative or zero.
///
/// # Examples
///
/// ```
/// # use bit_int::BitInt;
/// #
#[doc = concat!("let n = BitInt::<", stringify!($T), ", 3>::new(2).unwrap();")]
///
/// assert_eq!(n.checked_ilog2(), Some(1));
/// ```
#[must_use]
#[inline]
pub const fn checked_ilog2(self) -> Option<u32> {
self.get().checked_ilog2()
}

/// Returns the base 10 logarithm of the number, rounded down.
///
/// Returns [`None`] if the number is negative or zero.
///
/// # Examples
///
/// ```
/// # use bit_int::BitInt;
/// #
#[doc = concat!("let n = BitInt::<", stringify!($T), ", 5>::new(10).unwrap();")]
///
/// assert_eq!(n.checked_ilog10(), Some(1));
/// ```
#[must_use]
#[inline]
pub const fn checked_ilog10(self) -> Option<u32> {
self.get().checked_ilog10()
}

/// Negates `self`.
///
/// Returns [`None`] if `self` is [`Self::MIN`].
Expand Down Expand Up @@ -282,6 +341,46 @@ mod tests {
const _: Option<BitI8<4>> = BitI8::<4>::MAX.checked_rem(0);
}

#[test]
fn checked_ilog() {
let n = BitI8::<4>::new(5).unwrap();

assert_eq!(n.checked_ilog(5), Some(1));
assert!(n.checked_ilog(1).is_none());
assert!(BitI8::<4>::MIN.checked_ilog(5).is_none());
}

#[test]
const fn checked_ilog_is_const_fn() {
const _: Option<u32> = BitI8::<4>::MIN.checked_ilog(5);
}

#[test]
fn checked_ilog2() {
let n = BitI8::<3>::new(2).unwrap();

assert_eq!(n.checked_ilog2(), Some(1));
assert!(BitI8::<3>::MIN.checked_ilog2().is_none());
}

#[test]
const fn checked_ilog2_is_const_fn() {
const _: Option<u32> = BitI8::<3>::MIN.checked_ilog2();
}

#[test]
fn checked_ilog10() {
let n = BitI8::<5>::new(10).unwrap();

assert_eq!(n.checked_ilog10(), Some(1));
assert!(BitI8::<5>::MIN.checked_ilog10().is_none());
}

#[test]
const fn checked_ilog10_is_const_fn() {
const _: Option<u32> = BitI8::<5>::MIN.checked_ilog10();
}

#[test]
fn checked_neg() {
let n = BitI8::<4>::new(5).unwrap();
Expand Down
99 changes: 99 additions & 0 deletions src/bit_uint/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,65 @@ macro_rules! impl_ops {
}
}

/// Returns the logarithm of the number with respect to an arbitrary base,
/// rounded down.
///
/// Returns [`None`] if the number is zero, or if the base is not at least
/// 2.
///
/// # Examples
///
/// ```
/// # use bit_int::BitUint;
/// #
#[doc = concat!("let n = BitUint::<", stringify!($T), ", 3>::new(5).unwrap();")]
///
/// assert_eq!(n.checked_ilog(5), Some(1));
/// ```
#[must_use]
#[inline]
pub const fn checked_ilog(self, base: $T) -> Option<u32> {
self.get().checked_ilog(base)
}

/// Returns the base 2 logarithm of the number, rounded down.
///
/// Returns [`None`] if the number is zero.
///
/// # Examples
///
/// ```
/// # use bit_int::BitUint;
/// #
#[doc = concat!("let n = BitUint::<", stringify!($T), ", 2>::new(2).unwrap();")]
///
/// assert_eq!(n.checked_ilog2(), Some(1));
/// ```
#[must_use]
#[inline]
pub const fn checked_ilog2(self) -> Option<u32> {
self.get().checked_ilog2()
}

/// Returns the base 10 logarithm of the number, rounded down.
///
/// Returns [`None`] if the number is zero.
///
/// # Examples
///
/// ```
/// # use bit_int::BitUint;
/// #
#[doc = concat!("let n = BitUint::<", stringify!($T), ", 4>::new(10).unwrap();")]
///
/// assert_eq!(n.checked_ilog10(), Some(1));
/// ```
#[must_use]
#[inline]
pub const fn checked_ilog10(self) -> Option<u32> {
self.get().checked_ilog10()
}

/// Negates `self`.
///
/// Returns [`None`] unless `self` is `0`.
Expand Down Expand Up @@ -258,6 +317,46 @@ mod tests {
const _: Option<BitU8<3>> = BitU8::<3>::MAX.checked_rem(0);
}

#[test]
fn checked_ilog() {
let n = BitU8::<3>::new(5).unwrap();

assert_eq!(n.checked_ilog(5), Some(1));
assert!(n.checked_ilog(1).is_none());
assert!(BitU8::<3>::MIN.checked_ilog(5).is_none());
}

#[test]
const fn checked_ilog_is_const_fn() {
const _: Option<u32> = BitU8::<3>::MIN.checked_ilog(5);
}

#[test]
fn checked_ilog2() {
let n = BitU8::<2>::new(2).unwrap();

assert_eq!(n.checked_ilog2(), Some(1));
assert!(BitU8::<2>::MIN.checked_ilog2().is_none());
}

#[test]
const fn checked_ilog2_is_const_fn() {
const _: Option<u32> = BitU8::<2>::MIN.checked_ilog2();
}

#[test]
fn checked_ilog10() {
let n = BitU8::<4>::new(10).unwrap();

assert_eq!(n.checked_ilog10(), Some(1));
assert!(BitU8::<4>::MIN.checked_ilog10().is_none());
}

#[test]
const fn checked_ilog10_is_const_fn() {
const _: Option<u32> = BitU8::<4>::MIN.checked_ilog10();
}

#[test]
fn checked_neg() {
assert_eq!(BitU8::<1>::MIN.checked_neg().map(BitU8::get), Some(0));
Expand Down

0 comments on commit 55fa163

Please sign in to comment.