diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f9bd00b8..c03416ba 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,13 +9,7 @@ jobs: strategy: matrix: rust: [ - 1.31.0, # MSRV - 1.35.0, # has_copysign - 1.37.0, # has_reverse_bits - 1.38.0, # has_div_euclid - 1.44.0, # has_to_int_unchecked - 1.46.0, # has_leading_trailing_ones - 1.53.0, # has_is_subnormal + 1.60.0, # MSRV 1.62.0, # has_total_cmp stable, beta, diff --git a/.github/workflows/master.yaml b/.github/workflows/master.yaml index 68c4900d..034e3793 100644 --- a/.github/workflows/master.yaml +++ b/.github/workflows/master.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - rust: [1.31.0, stable] + rust: [1.60.0, stable] steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 5004cbbf..ac27bc45 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - rust: [1.31.0, stable] + rust: [1.60.0, stable] steps: - uses: actions/checkout@v4 - uses: actions/cache@v4 diff --git a/Cargo.toml b/Cargo.toml index 4f494e01..b75a7e1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,8 @@ version = "0.2.18" readme = "README.md" build = "build.rs" exclude = ["/ci/*", "/.github/*"] -edition = "2018" -rust-version = "1.31" +edition = "2021" +rust-version = "1.60" [package.metadata.docs.rs] features = ["std"] @@ -24,6 +24,7 @@ libm = { version = "0.2.0", optional = true } [features] default = ["std"] +libm = ["dep:libm"] std = [] # vestigial features, now always in effect diff --git a/README.md b/README.md index fa2f297c..71464a86 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![crate](https://img.shields.io/crates/v/num-traits.svg)](https://crates.io/crates/num-traits) [![documentation](https://docs.rs/num-traits/badge.svg)](https://docs.rs/num-traits) -[![minimum rustc 1.31](https://img.shields.io/badge/rustc-1.31+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![minimum rustc 1.60](https://img.shields.io/badge/rustc-1.60+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![build status](https://github.com/rust-num/num-traits/workflows/master/badge.svg)](https://github.com/rust-num/num-traits/actions) Numeric traits for generic mathematics in Rust. @@ -40,7 +40,7 @@ Release notes are available in [RELEASES.md](RELEASES.md). ## Compatibility -The `num-traits` crate is tested for rustc 1.31 and greater. +The `num-traits` crate is tested for rustc 1.60 and greater. ## License diff --git a/build.rs b/build.rs index 11bf090a..98b06bef 100644 --- a/build.rs +++ b/build.rs @@ -1,25 +1,7 @@ -use std::env; - fn main() { let ac = autocfg::new(); - ac.emit_expression_cfg( - "unsafe { 1f64.to_int_unchecked::() }", - "has_to_int_unchecked", - ); - - ac.emit_expression_cfg("1u32.reverse_bits()", "has_reverse_bits"); - ac.emit_expression_cfg("1u32.trailing_ones()", "has_leading_trailing_ones"); - ac.emit_expression_cfg("1u32.div_euclid(1u32)", "has_div_euclid"); - - if env::var_os("CARGO_FEATURE_STD").is_some() { - ac.emit_expression_cfg("1f64.copysign(-1f64)", "has_copysign"); - } - ac.emit_expression_cfg("1f64.is_subnormal()", "has_is_subnormal"); - ac.emit_expression_cfg("1f64.total_cmp(&2f64)", "has_total_cmp"); - - ac.emit_expression_cfg("1u32.to_ne_bytes()", "has_int_to_from_bytes"); - ac.emit_expression_cfg("3.14f64.to_ne_bytes()", "has_float_to_from_bytes"); + ac.emit_expression_cfg("1f64.total_cmp(&2f64)", "has_total_cmp"); // 1.62 autocfg::rerun_path("build.rs"); } diff --git a/ci/rustup.sh b/ci/rustup.sh index 26c8c3db..a07aa610 100755 --- a/ci/rustup.sh +++ b/ci/rustup.sh @@ -5,6 +5,6 @@ set -ex ci=$(dirname $0) -for version in 1.31.0 1.35.0 1.37.0 1.38.0 1.44.0 1.46.0 1.53.0 1.62.0 stable beta nightly; do +for version in 1.60.0 1.62.0 stable beta nightly; do rustup run "$version" "$ci/test_full.sh" done diff --git a/ci/test_full.sh b/ci/test_full.sh index e8c09c14..157756a6 100755 --- a/ci/test_full.sh +++ b/ci/test_full.sh @@ -3,7 +3,7 @@ set -e CRATE=num-traits -MSRV=1.31 +MSRV=1.60 get_rust_version() { local array=($(rustc --version)); @@ -32,9 +32,6 @@ echo "Testing supported features: ${FEATURES[*]}" cargo generate-lockfile -# libm 0.2.6 started using {float}::EPSILON -check_version 1.43 || cargo update -p libm --precise 0.2.5 - set -x # test the default diff --git a/src/cast.rs b/src/cast.rs index 125e2e38..a3e4dd8b 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -277,7 +277,6 @@ macro_rules! impl_to_primitive_float_to_float { )*} } -#[cfg(has_to_int_unchecked)] macro_rules! float_to_int_unchecked { // SAFETY: Must not be NaN or infinite; must be representable as the integer after truncating. // We already checked that the float is in the exclusive range `(MIN-1, MAX+1)`. @@ -286,13 +285,6 @@ macro_rules! float_to_int_unchecked { }; } -#[cfg(not(has_to_int_unchecked))] -macro_rules! float_to_int_unchecked { - ($float:expr => $int:ty) => { - $float as $int - }; -} - macro_rules! impl_to_primitive_float_to_signed_int { ($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$( #[inline] diff --git a/src/float.rs b/src/float.rs index 844b89ae..7a42dd87 100644 --- a/src/float.rs +++ b/src/float.rs @@ -790,6 +790,7 @@ impl FloatCore for f32 { Self::is_infinite(self) -> bool; Self::is_finite(self) -> bool; Self::is_normal(self) -> bool; + Self::is_subnormal(self) -> bool; Self::classify(self) -> FpCategory; Self::is_sign_positive(self) -> bool; Self::is_sign_negative(self) -> bool; @@ -800,11 +801,6 @@ impl FloatCore for f32 { Self::to_radians(self) -> Self; } - #[cfg(has_is_subnormal)] - forward! { - Self::is_subnormal(self) -> bool; - } - #[cfg(feature = "std")] forward! { Self::floor(self) -> Self; @@ -855,6 +851,7 @@ impl FloatCore for f64 { Self::is_infinite(self) -> bool; Self::is_finite(self) -> bool; Self::is_normal(self) -> bool; + Self::is_subnormal(self) -> bool; Self::classify(self) -> FpCategory; Self::is_sign_positive(self) -> bool; Self::is_sign_negative(self) -> bool; @@ -865,11 +862,6 @@ impl FloatCore for f64 { Self::to_radians(self) -> Self; } - #[cfg(has_is_subnormal)] - forward! { - Self::is_subnormal(self) -> bool; - } - #[cfg(feature = "std")] forward! { Self::floor(self) -> Self; @@ -1901,6 +1893,7 @@ macro_rules! float_impl_std { Self::is_infinite(self) -> bool; Self::is_finite(self) -> bool; Self::is_normal(self) -> bool; + Self::is_subnormal(self) -> bool; Self::classify(self) -> FpCategory; Self::floor(self) -> Self; Self::ceil(self) -> Self; @@ -1944,17 +1937,8 @@ macro_rules! float_impl_std { Self::asinh(self) -> Self; Self::acosh(self) -> Self; Self::atanh(self) -> Self; - } - - #[cfg(has_copysign)] - forward! { Self::copysign(self, sign: Self) -> Self; } - - #[cfg(has_is_subnormal)] - forward! { - Self::is_subnormal(self) -> bool; - } } }; } @@ -1993,6 +1977,7 @@ macro_rules! float_impl_libm { Self::is_infinite(self) -> bool; Self::is_finite(self) -> bool; Self::is_normal(self) -> bool; + Self::is_subnormal(self) -> bool; Self::classify(self) -> FpCategory; Self::is_sign_positive(self) -> bool; Self::is_sign_negative(self) -> bool; @@ -2003,11 +1988,6 @@ macro_rules! float_impl_libm { Self::to_radians(self) -> Self; } - #[cfg(has_is_subnormal)] - forward! { - Self::is_subnormal(self) -> bool; - } - forward! { FloatCore::signum(self) -> Self; FloatCore::powi(self, n: i32) -> Self; diff --git a/src/int.rs b/src/int.rs index e3ca72c0..c6284bf4 100644 --- a/src/int.rs +++ b/src/int.rs @@ -404,7 +404,6 @@ macro_rules! prim_int_impl { <$T>::count_zeros(self) } - #[cfg(has_leading_trailing_ones)] #[inline] fn leading_ones(self) -> u32 { <$T>::leading_ones(self) @@ -415,7 +414,6 @@ macro_rules! prim_int_impl { <$T>::leading_zeros(self) } - #[cfg(has_leading_trailing_ones)] #[inline] fn trailing_ones(self) -> u32 { <$T>::trailing_ones(self) @@ -461,7 +459,6 @@ macro_rules! prim_int_impl { <$T>::swap_bytes(self) } - #[cfg(has_reverse_bits)] #[inline] fn reverse_bits(self) -> Self { <$T>::reverse_bits(self) diff --git a/src/lib.rs b/src/lib.rs index 9ee16fc8..d392e920 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ //! //! ## Compatibility //! -//! The `num-traits` crate is tested for rustc 1.31 and greater. +//! The `num-traits` crate is tested for rustc 1.60 and greater. #![doc(html_root_url = "https://docs.rs/num-traits/0.2")] #![deny(unconditional_recursion)] diff --git a/src/ops/bytes.rs b/src/ops/bytes.rs index 4df9ecd0..f6a8030a 100644 --- a/src/ops/bytes.rs +++ b/src/ops/bytes.rs @@ -2,8 +2,6 @@ use core::borrow::{Borrow, BorrowMut}; use core::cmp::{Eq, Ord, PartialEq, PartialOrd}; use core::fmt::Debug; use core::hash::Hash; -#[cfg(not(has_int_to_from_bytes))] -use core::mem::transmute; pub trait NumBytes: Debug @@ -152,7 +150,6 @@ pub trait FromBytes: Sized { macro_rules! float_to_from_bytes_impl { ($T:ty, $L:expr) => { - #[cfg(has_float_to_from_bytes)] impl ToBytes for $T { type Bytes = [u8; $L]; @@ -172,7 +169,6 @@ macro_rules! float_to_from_bytes_impl { } } - #[cfg(has_float_to_from_bytes)] impl FromBytes for $T { type Bytes = [u8; $L]; @@ -191,52 +187,11 @@ macro_rules! float_to_from_bytes_impl { <$T>::from_ne_bytes(*bytes) } } - - #[cfg(not(has_float_to_from_bytes))] - impl ToBytes for $T { - type Bytes = [u8; $L]; - - #[inline] - fn to_be_bytes(&self) -> Self::Bytes { - ToBytes::to_be_bytes(&self.to_bits()) - } - - #[inline] - fn to_le_bytes(&self) -> Self::Bytes { - ToBytes::to_le_bytes(&self.to_bits()) - } - - #[inline] - fn to_ne_bytes(&self) -> Self::Bytes { - ToBytes::to_ne_bytes(&self.to_bits()) - } - } - - #[cfg(not(has_float_to_from_bytes))] - impl FromBytes for $T { - type Bytes = [u8; $L]; - - #[inline] - fn from_be_bytes(bytes: &Self::Bytes) -> Self { - Self::from_bits(FromBytes::from_be_bytes(bytes)) - } - - #[inline] - fn from_le_bytes(bytes: &Self::Bytes) -> Self { - Self::from_bits(FromBytes::from_le_bytes(bytes)) - } - - #[inline] - fn from_ne_bytes(bytes: &Self::Bytes) -> Self { - Self::from_bits(FromBytes::from_ne_bytes(bytes)) - } - } }; } macro_rules! int_to_from_bytes_impl { ($T:ty, $L:expr) => { - #[cfg(has_int_to_from_bytes)] impl ToBytes for $T { type Bytes = [u8; $L]; @@ -256,7 +211,6 @@ macro_rules! int_to_from_bytes_impl { } } - #[cfg(has_int_to_from_bytes)] impl FromBytes for $T { type Bytes = [u8; $L]; @@ -275,46 +229,6 @@ macro_rules! int_to_from_bytes_impl { <$T>::from_ne_bytes(*bytes) } } - - #[cfg(not(has_int_to_from_bytes))] - impl ToBytes for $T { - type Bytes = [u8; $L]; - - #[inline] - fn to_be_bytes(&self) -> Self::Bytes { - <$T as ToBytes>::to_ne_bytes(&<$T>::to_be(*self)) - } - - #[inline] - fn to_le_bytes(&self) -> Self::Bytes { - <$T as ToBytes>::to_ne_bytes(&<$T>::to_le(*self)) - } - - #[inline] - fn to_ne_bytes(&self) -> Self::Bytes { - unsafe { transmute(*self) } - } - } - - #[cfg(not(has_int_to_from_bytes))] - impl FromBytes for $T { - type Bytes = [u8; $L]; - - #[inline] - fn from_be_bytes(bytes: &Self::Bytes) -> Self { - Self::from_be(::from_ne_bytes(bytes)) - } - - #[inline] - fn from_le_bytes(bytes: &Self::Bytes) -> Self { - Self::from_le(::from_ne_bytes(bytes)) - } - - #[inline] - fn from_ne_bytes(bytes: &Self::Bytes) -> Self { - unsafe { transmute(*bytes) } - } - } }; } diff --git a/src/ops/euclid.rs b/src/ops/euclid.rs index c12137db..fa7b317a 100644 --- a/src/ops/euclid.rs +++ b/src/ops/euclid.rs @@ -71,7 +71,6 @@ pub trait Euclid: Sized + Div + Rem { macro_rules! euclid_forward_impl { ($($t:ty)*) => {$( - #[cfg(has_div_euclid)] impl Euclid for $t { #[inline] fn div_euclid(&self, v: &$t) -> Self { @@ -86,64 +85,13 @@ macro_rules! euclid_forward_impl { )*} } -macro_rules! euclid_int_impl { - ($($t:ty)*) => {$( - euclid_forward_impl!($t); - - #[cfg(not(has_div_euclid))] - impl Euclid for $t { - #[inline] - fn div_euclid(&self, v: &$t) -> Self { - let q = self / v; - if self % v < 0 { - return if *v > 0 { q - 1 } else { q + 1 } - } - q - } - - #[inline] - fn rem_euclid(&self, v: &$t) -> Self { - let r = self % v; - if r < 0 { - if *v < 0 { - r - v - } else { - r + v - } - } else { - r - } - } - } - )*} -} +euclid_forward_impl!(isize i8 i16 i32 i64 i128); +euclid_forward_impl!(usize u8 u16 u32 u64 u128); -macro_rules! euclid_uint_impl { - ($($t:ty)*) => {$( - euclid_forward_impl!($t); - - #[cfg(not(has_div_euclid))] - impl Euclid for $t { - #[inline] - fn div_euclid(&self, v: &$t) -> Self { - self / v - } - - #[inline] - fn rem_euclid(&self, v: &$t) -> Self { - self % v - } - } - )*} -} - -euclid_int_impl!(isize i8 i16 i32 i64 i128); -euclid_uint_impl!(usize u8 u16 u32 u64 u128); - -#[cfg(all(has_div_euclid, feature = "std"))] +#[cfg(feature = "std")] euclid_forward_impl!(f32 f64); -#[cfg(not(all(has_div_euclid, feature = "std")))] +#[cfg(not(feature = "std"))] impl Euclid for f32 { #[inline] fn div_euclid(&self, v: &f32) -> f32 { @@ -165,7 +113,7 @@ impl Euclid for f32 { } } -#[cfg(not(all(has_div_euclid, feature = "std")))] +#[cfg(not(feature = "std"))] impl Euclid for f64 { #[inline] fn div_euclid(&self, v: &f64) -> f64 { @@ -219,7 +167,6 @@ pub trait CheckedEuclid: Euclid { macro_rules! checked_euclid_forward_impl { ($($t:ty)*) => {$( - #[cfg(has_div_euclid)] impl CheckedEuclid for $t { #[inline] fn checked_div_euclid(&self, v: &$t) -> Option { @@ -234,62 +181,8 @@ macro_rules! checked_euclid_forward_impl { )*} } -macro_rules! checked_euclid_int_impl { - ($($t:ty)*) => {$( - checked_euclid_forward_impl!($t); - - #[cfg(not(has_div_euclid))] - impl CheckedEuclid for $t { - #[inline] - fn checked_div_euclid(&self, v: &$t) -> Option<$t> { - if *v == 0 || (*self == Self::min_value() && *v == -1) { - None - } else { - Some(Euclid::div_euclid(self, v)) - } - } - - #[inline] - fn checked_rem_euclid(&self, v: &$t) -> Option<$t> { - if *v == 0 || (*self == Self::min_value() && *v == -1) { - None - } else { - Some(Euclid::rem_euclid(self, v)) - } - } - } - )*} -} - -macro_rules! checked_euclid_uint_impl { - ($($t:ty)*) => {$( - checked_euclid_forward_impl!($t); - - #[cfg(not(has_div_euclid))] - impl CheckedEuclid for $t { - #[inline] - fn checked_div_euclid(&self, v: &$t) -> Option<$t> { - if *v == 0 { - None - } else { - Some(Euclid::div_euclid(self, v)) - } - } - - #[inline] - fn checked_rem_euclid(&self, v: &$t) -> Option<$t> { - if *v == 0 { - None - } else { - Some(Euclid::rem_euclid(self, v)) - } - } - } - )*} -} - -checked_euclid_int_impl!(isize i8 i16 i32 i64 i128); -checked_euclid_uint_impl!(usize u8 u16 u32 u64 u128); +checked_euclid_forward_impl!(isize i8 i16 i32 i64 i128); +checked_euclid_forward_impl!(usize u8 u16 u32 u64 u128); #[cfg(test)] mod tests {