diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba003bb..09b5633 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: rust: [ - 1.94.0, # MSRV + 1.97.0, # MSRV stable, beta, nightly, @@ -52,7 +52,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.94.0 + - uses: dtolnay/rust-toolchain@1.97.0 with: components: rustfmt - run: cargo fmt --all --check diff --git a/Cargo.toml b/Cargo.toml index 1c73692..ea88cea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "num-primitive" -version = "0.3.8" +version = "0.3.9" description = "Traits for primitive numeric types" repository = "https://github.com/rust-num/num-primitive" license = "MIT OR Apache-2.0" keywords = ["generic", "mathematics", "numerics", "primitive"] categories = ["algorithms", "science", "no-std"] edition = "2024" -rust-version = "1.94" +rust-version = "1.97" [package.metadata.release] allow-branch = ["main"] diff --git a/README.md b/README.md index 3eb59e6..b1afb2c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # num-primitive [![crate](https://img.shields.io/crates/v/num-primitive.svg)](https://crates.io/crates/num-primitive) -[![minimum rust 1.94](https://img.shields.io/badge/rust-1.94+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![minimum rust 1.97](https://img.shields.io/badge/rust-1.97+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![documentation](https://docs.rs/num-primitive/badge.svg)](https://docs.rs/num-primitive) -[![build status](https://github.com/rust-num/num-primitive/workflows/CI/badge.svg)](https://github.com/rust-num/num-primitive/actions) +[![build status](https://github.com/rust-num/num-primitive/actions/workflows/ci.yml/badge.svg)](https://github.com/rust-num/num-primitive/actions/workflows/ci.yml) Traits for primitive numeric types in Rust. diff --git a/RELEASES.md b/RELEASES.md index 3d4c215..c9b694c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,13 @@ +# Release 0.3.9 (2026-07-09) + +- Updated to MSRV 1.97. +- Added `PrimitiveInteger::{highest_one,lowest_one}`. +- Added `PrimitiveInteger::{isolate_highest_one,isolate_lowest_one}`. +- Added `PrimitiveUnsigned::bit_width`. +- Added `NonZeroPrimitiveInteger::{highest_one,lowest_one}`. +- Added `NonZeroPrimitiveInteger::{isolate_highest_one,isolate_lowest_one}`. +- Added `NonZeroPrimitiveUnsigned::bit_width`. + # Release 0.3.8 (2026-07-09) - Added traits for `NonZero`-wrapped primitive integers: `NonZeroPrimitiveInteger`, diff --git a/src/integer.rs b/src/integer.rs index f51c6c7..5cf6f66 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -280,6 +280,9 @@ pub trait PrimitiveInteger: /// Parses an integer from a string slice with digits in a given base. fn from_str_radix(src: &str, radix: u32) -> Result; + /// Returns the index of the highest bit set to one in `self`, or `None` if `self` is `0`. + fn highest_one(self) -> Option; + /// Returns the logarithm of the number with respect to an arbitrary base, rounded down. fn ilog(self, base: Self) -> u32; @@ -289,6 +292,12 @@ pub trait PrimitiveInteger: /// Returns the base 2 logarithm of the number, rounded down. fn ilog2(self) -> u32; + /// Returns `self` with only the most significant bit set, or `0` if the input is `0`. + fn isolate_highest_one(self) -> Self; + + /// Returns `self` with only the least significant bit set, or `0` if the input is `0`. + fn isolate_lowest_one(self) -> Self; + /// Returns the square root of the number, rounded down. fn isqrt(self) -> Self; @@ -298,6 +307,9 @@ pub trait PrimitiveInteger: /// Returns the number of leading zeros in the binary representation of `self`. fn leading_zeros(self) -> u32; + /// Returns the index of the lowest bit set to one in `self`, or `None` if `self` is `0`. + fn lowest_one(self) -> Option; + /// Calculates `self + rhs`. Returns a tuple of the addition along with a boolean indicating /// whether an arithmetic overflow would occur. fn overflowing_add(self, rhs: Self) -> (Self, bool); @@ -707,9 +719,21 @@ pub trait NonZeroPrimitiveInteger: /// Returns the contained value as a primitive type. fn get(self) -> Self::Integer; + /// Returns the index of the highest bit set to one in `self`. + fn highest_one(self) -> u32; + + /// Returns `self` with only the most significant bit set. + fn isolate_highest_one(self) -> Self; + + /// Returns `self` with only the least significant bit set. + fn isolate_lowest_one(self) -> Self; + /// Returns the number of leading zeros in the binary representation of `self`. fn leading_zeros(self) -> u32; + /// Returns the index of the lowest bit set to one in `self`. + fn lowest_one(self) -> u32; + /// Creates a non-zero if the given value is not zero. fn new(n: Self::Integer) -> Option; @@ -767,12 +791,16 @@ macro_rules! impl_integer { fn count_ones(self) -> u32; fn count_zeros(self) -> u32; fn div_euclid(self, rhs: Self) -> Self; + fn highest_one(self) -> Option; fn ilog(self, base: Self) -> u32; fn ilog10(self) -> u32; fn ilog2(self) -> u32; + fn isolate_highest_one(self) -> Self; + fn isolate_lowest_one(self) -> Self; fn isqrt(self) -> Self; fn leading_ones(self) -> u32; fn leading_zeros(self) -> u32; + fn lowest_one(self) -> Option; fn overflowing_add(self, rhs: Self) -> (Self, bool); fn overflowing_div(self, rhs: Self) -> (Self, bool); fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool); @@ -854,7 +882,11 @@ macro_rules! impl_integer { fn checked_pow(self, other: u32) -> Option; fn count_ones(self) -> NonZero; fn get(self) -> Self::Integer; + fn highest_one(self) -> u32; + fn isolate_highest_one(self) -> Self; + fn isolate_lowest_one(self) -> Self; fn leading_zeros(self) -> u32; + fn lowest_one(self) -> u32; fn saturating_mul(self, other: Self) -> Self; fn saturating_pow(self, other: u32) -> Self; fn trailing_zeros(self) -> u32; diff --git a/src/unsigned.rs b/src/unsigned.rs index dd2655e..0d1576a 100644 --- a/src/unsigned.rs +++ b/src/unsigned.rs @@ -54,6 +54,10 @@ pub trait PrimitiveUnsigned: /// Computes the absolute difference between `self` and `other`. fn abs_diff(self, other: Self) -> Self; + /// Returns the minimum number of bits required to represent `self`. + /// This method returns zero if `self` is zero. + fn bit_width(self) -> u32; + /// Calculates `self` − `rhs` − `borrow` and returns a tuple /// containing the difference and the output borrow. fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool); @@ -185,6 +189,9 @@ pub trait NonZeroPrimitiveUnsigned: /// For `core::num::NonZero`, this is `NonZero`. type NonZeroSigned: NonZeroPrimitiveSigned; + /// Returns the minimum number of bits required to represent `self`. + fn bit_width(self) -> NonZero; + /// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size. fn cast_signed(self) -> Self::NonZeroSigned; @@ -224,6 +231,7 @@ macro_rules! impl_unsigned { forward! { fn abs_diff(self, other: Self) -> Self; + fn bit_width(self) -> u32; fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool); fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool); fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self); @@ -256,6 +264,7 @@ macro_rules! impl_unsigned { type NonZeroSigned = NonZero<$Signed>; forward! { + fn bit_width(self) -> NonZero; fn cast_signed(self) -> Self::NonZeroSigned; fn checked_add(self, other: Self::Integer) -> Option; fn checked_next_power_of_two(self) -> Option;