diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b483954..ad2ccbd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: rust: [ - 1.90.0, # MSRV + 1.91.0, # MSRV stable, beta, nightly, @@ -52,7 +52,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.90.0 + - uses: dtolnay/rust-toolchain@1.91.0 with: components: rustfmt - run: cargo fmt --all --check diff --git a/Cargo.toml b/Cargo.toml index d2f9cd9..ff5baa1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "num-primitive" -version = "0.3.1" +version = "0.3.2" 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.90" +rust-version = "1.91" [features] default = ["std"] diff --git a/README.md b/README.md index e6b3392..6bdd715 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![crate](https://img.shields.io/crates/v/num-primitive.svg)](https://crates.io/crates/num-primitive) [![documentation](https://docs.rs/num-primitive/badge.svg)](https://docs.rs/num-primitive) -[![minimum rustc 1.90](https://img.shields.io/badge/rustc-1.90+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![minimum rustc 1.91](https://img.shields.io/badge/rustc-1.91+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![build status](https://github.com/rust-num/num-primitive/workflows/CI/badge.svg)](https://github.com/rust-num/num-primitive/actions) Traits for primitive numeric types in Rust. @@ -61,7 +61,7 @@ Release notes are available in [RELEASES.md](RELEASES.md). ## Compatibility -The `num-primitive` crate is currently tested for Rust 1.90 and greater. This +The `num-primitive` crate is currently tested for Rust 1.91 and greater. This minimum-supported Rust version (MSRV) may be increased at any time to add support for newly-stabilized functionality from the standard library. Changes will be documented prominently in the release notes. diff --git a/RELEASES.md b/RELEASES.md index 58a0094..d79dd39 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,11 @@ +# Release 0.3.2 (2025-12-16) + +- Updated to MSRV 1.91. +- Added `PrimitiveInteger::strict_{add,div,{div,rem}_euclid,mul,neg,pow,rem,shl,shr,sub}` +- Added `PrimitiveSigned::strict_{abs,{add,sub}_unsigned}` +- Added `PrimitiveUnsigned::strict_{abs,{add,sub}_signed}` +- Added `PrimitiveUnsigned::{borrowing_sub,carrying_{add,mul,mul_add},checked_signed_diff}` + # Release 0.3.1 (2025-12-16) - Updated to MSRV 1.90. diff --git a/src/integer.rs b/src/integer.rs index 1abeaec..15b59fd 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -221,7 +221,8 @@ pub trait PrimitiveInteger: /// occurred. fn checked_mul(self, rhs: Self) -> Option; - /// Checked negation. Computes -self, returning `None` if `self == MIN`. + /// Checked negation. Computes -self, returning `None` if `self == MIN` for signed integers, + /// or for any non-zero unsigned integer. fn checked_neg(self) -> Option; /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if overflow occurred. @@ -367,6 +368,44 @@ pub trait PrimitiveInteger: /// instead of overflowing. fn saturating_sub(self, rhs: Self) -> Self; + /// Strict integer addition. Computes `self + rhs`, panicking if overflow occurred. + fn strict_add(self, rhs: Self) -> Self; + + /// Strict integer division. Computes `self / rhs`, panicking if overflow occurred. + fn strict_div(self, rhs: Self) -> Self; + + /// Strict Euclidean division. Computes `self.div_euclid(rhs)`, panicking if overflow occurred. + fn strict_div_euclid(self, rhs: Self) -> Self; + + /// Strict integer multiplication. Computes `self * rhs`, panicking if overflow occurred. + fn strict_mul(self, rhs: Self) -> Self; + + /// Strict negation. Computes `-self`, panicking if `self == MIN` for signed integers, + /// or for any non-zero unsigned integer. + fn strict_neg(self) -> Self; + + /// Strict exponentiation. Computes `self.pow(exp)`, panicking if overflow occurred. + fn strict_pow(self, exp: u32) -> Self; + + /// Strict integer remainder. Computes `self % rhs`, panicking if + /// the division results in overflow. + fn strict_rem(self, rhs: Self) -> Self; + + /// Strict Euclidean remainder. Computes `self.rem_euclid(rhs)`, panicking if + /// the division results in overflow. + fn strict_rem_euclid(self, rhs: Self) -> Self; + + /// Strict shift left. Computes `self << rhs`, panicking if `rhs` is larger + /// than or equal to the number of bits in `self`. + fn strict_shl(self, rhs: u32) -> Self; + + /// Strict shift right. Computes `self >> rhs`, panicking if `rhs` is + /// larger than or equal to the number of bits in `self`. + fn strict_shr(self, rhs: u32) -> Self; + + /// Strict integer subtraction. Computes `self - rhs`, panicking if overflow occurred. + fn strict_sub(self, rhs: Self) -> Self; + /// Reverses the byte order of the integer. fn swap_bytes(self) -> Self; @@ -589,6 +628,17 @@ macro_rules! impl_integer { fn saturating_mul(self, rhs: Self) -> Self; fn saturating_pow(self, exp: u32) -> Self; fn saturating_sub(self, rhs: Self) -> Self; + fn strict_add(self, rhs: Self) -> Self; + fn strict_div(self, rhs: Self) -> Self; + fn strict_div_euclid(self, rhs: Self) -> Self; + fn strict_mul(self, rhs: Self) -> Self; + fn strict_neg(self) -> Self; + fn strict_pow(self, exp: u32) -> Self; + fn strict_rem(self, rhs: Self) -> Self; + fn strict_rem_euclid(self, rhs: Self) -> Self; + fn strict_shl(self, rhs: u32) -> Self; + fn strict_shr(self, rhs: u32) -> Self; + fn strict_sub(self, rhs: Self) -> Self; fn swap_bytes(self) -> Self; fn to_be(self) -> Self; fn to_le(self) -> Self; diff --git a/src/signed.rs b/src/signed.rs index 7d2cf11..91933b8 100644 --- a/src/signed.rs +++ b/src/signed.rs @@ -114,6 +114,17 @@ pub trait PrimitiveSigned: PrimitiveInteger + From + core::ops::Neg Self; + /// Strict absolute value. Computes `self.abs()`, panicking if `self == MIN`. + fn strict_abs(self) -> Self; + + /// Strict addition with an unsigned integer. Computes `self + rhs`, + /// panicking if overflow occurred. + fn strict_add_unsigned(self, rhs: Self::Unsigned) -> Self; + + /// Strict subtraction with an unsigned integer. Computes `self - rhs`, + /// panicking if overflow occurred. + fn strict_sub_unsigned(self, rhs: Self::Unsigned) -> Self; + /// Computes the absolute value of `self` without any wrapping or panicking. fn unsigned_abs(self) -> Self::Unsigned; @@ -159,6 +170,9 @@ macro_rules! impl_signed { fn saturating_neg(self) -> Self; fn saturating_sub_unsigned(self, rhs: Self::Unsigned) -> Self; fn signum(self) -> Self; + fn strict_abs(self) -> Self; + fn strict_add_unsigned(self, rhs: Self::Unsigned) -> Self; + fn strict_sub_unsigned(self, rhs: Self::Unsigned) -> Self; fn unsigned_abs(self) -> Self::Unsigned; fn wrapping_abs(self) -> Self; fn wrapping_add_unsigned(self, rhs: Self::Unsigned) -> Self; diff --git a/src/unsigned.rs b/src/unsigned.rs index 8f797ad..4f7592e 100644 --- a/src/unsigned.rs +++ b/src/unsigned.rs @@ -40,6 +40,21 @@ pub trait PrimitiveUnsigned: PrimitiveInteger + From { /// Computes the absolute difference between `self` and `other`. fn abs_diff(self, other: Self) -> Self; + /// 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); + + /// Calculates `self` + `rhs` + `carry` and returns a tuple containing + /// the sum and the output carry (in that order). + fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool); + + /// Calculates the "full multiplication" `self * rhs + carry` + /// without the possibility to overflow. + fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self); + + /// Calculates the "full multiplication" `self * rhs + carry + add`. + fn carrying_mul_add(self, rhs: Self, carry: Self, add: Self) -> (Self, Self); + /// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size. fn cast_signed(self) -> Self::Signed; @@ -56,6 +71,10 @@ pub trait PrimitiveUnsigned: PrimitiveInteger + From { /// wrapped in Some. fn checked_next_power_of_two(self) -> Option; + /// Checked integer subtraction. Computes `self - rhs` and checks if the result fits into a + /// signed integer of the same size, returning `None` if overflow occurred. + fn checked_signed_diff(self, rhs: Self) -> Option; + /// Checked subtraction with a signed integer. Computes `self - rhs`, /// returning `None` if overflow occurred. fn checked_sub_signed(self, rhs: Self::Signed) -> Option; @@ -91,6 +110,14 @@ pub trait PrimitiveUnsigned: PrimitiveInteger + From { /// the numeric bounds instead of overflowing. fn saturating_sub_signed(self, rhs: Self::Signed) -> Self; + /// Strict addition with a signed integer. Computes `self + rhs`, + /// panicking if overflow occurred. + fn strict_add_signed(self, rhs: Self::Signed) -> Self; + + /// Strict subtraction with a signed integer. Computes `self - rhs`, + /// panicking if overflow occurred. + fn strict_sub_signed(self, rhs: Self::Signed) -> Self; + /// Wrapping (modular) addition with a signed integer. Computes `self + rhs`, wrapping around /// at the boundary of the type. fn wrapping_add_signed(self, rhs: Self::Signed) -> Self; @@ -113,10 +140,15 @@ macro_rules! impl_unsigned { forward! { fn abs_diff(self, other: Self) -> Self; + 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); + fn carrying_mul_add(self, rhs: Self, carry: Self, add: Self) -> (Self, Self); fn cast_signed(self) -> Self::Signed; fn checked_add_signed(self, rhs: Self::Signed) -> Option; fn checked_next_multiple_of(self, rhs: Self) -> Option; fn checked_next_power_of_two(self) -> Option; + fn checked_signed_diff(self, rhs: Self) -> Option; fn checked_sub_signed(self, rhs: Self::Signed) -> Option; fn div_ceil(self, rhs: Self) -> Self; fn is_multiple_of(self, rhs: Self) -> bool; @@ -127,6 +159,8 @@ macro_rules! impl_unsigned { fn overflowing_sub_signed(self, rhs: Self::Signed) -> (Self, bool); fn saturating_add_signed(self, rhs: Self::Signed) -> Self; fn saturating_sub_signed(self, rhs: Self::Signed) -> Self; + fn strict_add_signed(self, rhs: Self::Signed) -> Self; + fn strict_sub_signed(self, rhs: Self::Signed) -> Self; fn wrapping_add_signed(self, rhs: Self::Signed) -> Self; fn wrapping_sub_signed(self, rhs: Self::Signed) -> Self; }