diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /library/core/src/num | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/src/num')
-rw-r--r-- | library/core/src/num/dec2flt/fpu.rs | 11 | ||||
-rw-r--r-- | library/core/src/num/dec2flt/number.rs | 1 | ||||
-rw-r--r-- | library/core/src/num/f32.rs | 21 | ||||
-rw-r--r-- | library/core/src/num/f64.rs | 21 | ||||
-rw-r--r-- | library/core/src/num/int_macros.rs | 54 | ||||
-rw-r--r-- | library/core/src/num/mod.rs | 3 | ||||
-rw-r--r-- | library/core/src/num/nonzero.rs | 14 | ||||
-rw-r--r-- | library/core/src/num/saturating.rs | 438 | ||||
-rw-r--r-- | library/core/src/num/uint_macros.rs | 64 | ||||
-rw-r--r-- | library/core/src/num/wrapping.rs | 1 |
10 files changed, 406 insertions, 222 deletions
diff --git a/library/core/src/num/dec2flt/fpu.rs b/library/core/src/num/dec2flt/fpu.rs index 3806977f7..8d62684f8 100644 --- a/library/core/src/num/dec2flt/fpu.rs +++ b/library/core/src/num/dec2flt/fpu.rs @@ -8,6 +8,17 @@ pub use fpu_precision::set_precision; // round to 80 bits causing double rounding to happen when values are eventually represented as // 32/64 bit float values. To overcome this, the FPU control word can be set so that the // computations are performed in the desired precision. +// +// Note that normally, it is Undefined Behavior to alter the FPU control word while Rust code runs. +// The compiler assumes that the control word is always in its default state. However, in this +// particular case the semantics with the altered control word are actually *more faithful* +// to Rust semantics than the default -- arguably it is all the code that runs *outside* of the scope +// of a `set_precision` guard that is wrong. +// In other words, we are only using this to work around <https://github.com/rust-lang/rust/issues/114479>. +// Sometimes killing UB with UB actually works... +// (If this is used to set 32bit precision, there is still a risk that the compiler moves some 64bit +// operation into the scope of the `set_precision` guard. So it's not like this is totally sound. +// But it's not really any less sound than the default state of 80bit precision...) #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] mod fpu_precision { use core::arch::asm; diff --git a/library/core/src/num/dec2flt/number.rs b/library/core/src/num/dec2flt/number.rs index 8589e2bbd..253899156 100644 --- a/library/core/src/num/dec2flt/number.rs +++ b/library/core/src/num/dec2flt/number.rs @@ -51,6 +51,7 @@ impl Number { /// There is an exception: disguised fast-path cases, where we can shift /// powers-of-10 from the exponent to the significant digits. pub fn try_fast_path<F: RawFloat>(&self) -> Option<F> { + // Here we need to work around <https://github.com/rust-lang/rust/issues/114479>. // The fast path crucially depends on arithmetic being rounded to the correct number of bits // without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision // of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit. diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index d050d21c8..290f649f9 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -277,6 +277,14 @@ pub mod consts { #[stable(feature = "tau_constant", since = "1.47.0")] pub const TAU: f32 = 6.28318530717958647692528676655900577_f32; + /// The golden ratio (φ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const PHI: f32 = 1.618033988749894848204586834365638118_f32; + + /// The Euler-Mascheroni constant (γ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const EGAMMA: f32 = 0.577215664901532860606512090082402431_f32; + /// π/2 #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32; @@ -301,6 +309,10 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32; + /// 1/sqrt(π) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_PI: f32 = 0.564189583547756286948079451560772586_f32; + /// 2/π #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32; @@ -317,6 +329,14 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32; + /// sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const SQRT_3: f32 = 1.732050807568877293527446341505872367_f32; + + /// 1/sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_3: f32 = 0.577350269189625764509148780501957456_f32; + /// Euler's number (e) #[stable(feature = "rust1", since = "1.0.0")] pub const E: f32 = 2.71828182845904523536028747135266250_f32; @@ -937,6 +957,7 @@ impl f32 { } else if self == other { if self.is_sign_negative() && other.is_sign_positive() { self } else { other } } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. self + other } } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index d9a738191..7569d2cd6 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -277,6 +277,14 @@ pub mod consts { #[stable(feature = "tau_constant", since = "1.47.0")] pub const TAU: f64 = 6.28318530717958647692528676655900577_f64; + /// The golden ratio (φ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const PHI: f64 = 1.618033988749894848204586834365638118_f64; + + /// The Euler-Mascheroni constant (γ) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const EGAMMA: f64 = 0.577215664901532860606512090082402431_f64; + /// π/2 #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64; @@ -301,6 +309,10 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64; + /// 1/sqrt(π) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_PI: f64 = 0.564189583547756286948079451560772586_f64; + /// 2/π #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64; @@ -317,6 +329,14 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64; + /// sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const SQRT_3: f64 = 1.732050807568877293527446341505872367_f64; + + /// 1/sqrt(3) + #[unstable(feature = "more_float_constants", issue = "103883")] + pub const FRAC_1_SQRT_3: f64 = 0.577350269189625764509148780501957456_f64; + /// Euler's number (e) #[stable(feature = "rust1", since = "1.0.0")] pub const E: f64 = 2.71828182845904523536028747135266250_f64; @@ -948,6 +968,7 @@ impl f64 { } else if self == other { if self.is_sign_negative() && other.is_sign_positive() { self } else { other } } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. self + other } } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 1f43520e1..3cbb55af3 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -898,6 +898,30 @@ macro_rules! int_impl { acc.checked_mul(base) } + /// Returns the square root of the number, rounded down. + /// + /// Returns `None` if `self` is negative. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_isqrt(), Some(3));")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_isqrt(self) -> Option<Self> { + if self < 0 { + None + } else { + Some((self as $UnsignedT).isqrt() as Self) + } + } + /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric /// bounds instead of overflowing. /// @@ -2061,6 +2085,36 @@ macro_rules! int_impl { acc * base } + /// Returns the square root of the number, rounded down. + /// + /// # Panics + /// + /// This function will panic if `self` is negative. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn isqrt(self) -> Self { + // I would like to implement it as + // ``` + // self.checked_isqrt().expect("argument of integer square root must be non-negative") + // ``` + // but `expect` is not yet stable as a `const fn`. + match self.checked_isqrt() { + Some(sqrt) => sqrt, + None => panic!("argument of integer square root must be non-negative"), + } + } + /// Calculates the quotient of Euclidean division of `self` by `rhs`. /// /// This computes the integer `q` such that `self = q * rhs + r`, with diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 95dcaf5dd..8b127132c 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -44,11 +44,10 @@ mod uint_macros; // import uint_impl! mod error; mod int_log10; mod nonzero; -#[unstable(feature = "saturating_int_impl", issue = "87920")] mod saturating; mod wrapping; -#[unstable(feature = "saturating_int_impl", issue = "87920")] +#[stable(feature = "saturating_int_impl", since = "1.74.0")] pub use saturating::Saturating; #[stable(feature = "rust1", since = "1.0.0")] pub use wrapping::Wrapping; diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 5939dedbd..7f8d673c1 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -41,6 +41,20 @@ macro_rules! nonzero_integers { /// with the exception that `0` is not a valid instance. #[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")] /// including in FFI. + /// + /// Thanks to the [null pointer optimization], + #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")] + /// are guaranteed to have the same size and alignment: + /// + /// ``` + /// # use std::mem::{size_of, align_of}; + #[doc = concat!("use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::<Option<", stringify!($Ty), ">>());")] + #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::<Option<", stringify!($Ty), ">>());")] + /// ``` + /// + /// [null pointer optimization]: crate::option#representation #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs index 8982473b2..d9ccc73c4 100644 --- a/library/core/src/num/saturating.rs +++ b/library/core/src/num/saturating.rs @@ -4,7 +4,7 @@ use crate::fmt; use crate::ops::{Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign}; use crate::ops::{BitXor, BitXorAssign, Div, DivAssign}; use crate::ops::{Mul, MulAssign, Neg, Not, Rem, RemAssign}; -use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign}; +use crate::ops::{Sub, SubAssign}; /// Provides intentionally-saturating arithmetic on `T`. /// @@ -24,7 +24,6 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign}; /// # Examples /// /// ``` -/// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// /// let max = Saturating(u32::MAX); @@ -32,180 +31,186 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign}; /// /// assert_eq!(u32::MAX, (max + one).0); /// ``` -#[unstable(feature = "saturating_int_impl", issue = "87920")] +#[stable(feature = "saturating_int_impl", since = "1.74.0")] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] #[repr(transparent)] -pub struct Saturating<T>(#[unstable(feature = "saturating_int_impl", issue = "87920")] pub T); +#[rustc_diagnostic_item = "Saturating"] +pub struct Saturating<T>( + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub T, +); -#[unstable(feature = "saturating_int_impl", issue = "87920")] +#[stable(feature = "saturating_int_impl", since = "1.74.0")] impl<T: fmt::Debug> fmt::Debug for Saturating<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } -#[unstable(feature = "saturating_int_impl", issue = "87920")] +#[stable(feature = "saturating_int_impl", since = "1.74.0")] impl<T: fmt::Display> fmt::Display for Saturating<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } -#[unstable(feature = "saturating_int_impl", issue = "87920")] +#[stable(feature = "saturating_int_impl", since = "1.74.0")] impl<T: fmt::Binary> fmt::Binary for Saturating<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } -#[unstable(feature = "saturating_int_impl", issue = "87920")] +#[stable(feature = "saturating_int_impl", since = "1.74.0")] impl<T: fmt::Octal> fmt::Octal for Saturating<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } -#[unstable(feature = "saturating_int_impl", issue = "87920")] +#[stable(feature = "saturating_int_impl", since = "1.74.0")] impl<T: fmt::LowerHex> fmt::LowerHex for Saturating<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } -#[unstable(feature = "saturating_int_impl", issue = "87920")] +#[stable(feature = "saturating_int_impl", since = "1.74.0")] impl<T: fmt::UpperHex> fmt::UpperHex for Saturating<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } -#[allow(unused_macros)] -macro_rules! sh_impl_signed { - ($t:ident, $f:ident) => { - // FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065 - // - // #[unstable(feature = "saturating_int_impl", issue = "87920")] - // impl Shl<$f> for Saturating<$t> { - // type Output = Saturating<$t>; - // - // #[inline] - // fn shl(self, other: $f) -> Saturating<$t> { - // if other < 0 { - // Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32)) - // } else { - // Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32)) - // } - // } - // } - // forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f, - // #[unstable(feature = "saturating_int_impl", issue = "87920")] } - // - // #[unstable(feature = "saturating_int_impl", issue = "87920")] - // impl ShlAssign<$f> for Saturating<$t> { - // #[inline] - // fn shl_assign(&mut self, other: $f) { - // *self = *self << other; - // } - // } - // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f } - - #[unstable(feature = "saturating_int_impl", issue = "87920")] - impl Shr<$f> for Saturating<$t> { - type Output = Saturating<$t>; - - #[inline] - fn shr(self, other: $f) -> Saturating<$t> { - if other < 0 { - Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32)) - } else { - Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32)) - } - } - } - forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } - - #[unstable(feature = "saturating_int_impl", issue = "87920")] - impl ShrAssign<$f> for Saturating<$t> { - #[inline] - fn shr_assign(&mut self, other: $f) { - *self = *self >> other; - } - } - forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f } - }; -} - -macro_rules! sh_impl_unsigned { - ($t:ident, $f:ident) => { - #[unstable(feature = "saturating_int_impl", issue = "87920")] - impl Shl<$f> for Saturating<$t> { - type Output = Saturating<$t>; - - #[inline] - fn shl(self, other: $f) -> Saturating<$t> { - Saturating(self.0.wrapping_shl(other as u32)) - } - } - forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } - - #[unstable(feature = "saturating_int_impl", issue = "87920")] - impl ShlAssign<$f> for Saturating<$t> { - #[inline] - fn shl_assign(&mut self, other: $f) { - *self = *self << other; - } - } - forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f } - - #[unstable(feature = "saturating_int_impl", issue = "87920")] - impl Shr<$f> for Saturating<$t> { - type Output = Saturating<$t>; - - #[inline] - fn shr(self, other: $f) -> Saturating<$t> { - Saturating(self.0.wrapping_shr(other as u32)) - } - } - forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] - impl ShrAssign<$f> for Saturating<$t> { - #[inline] - fn shr_assign(&mut self, other: $f) { - *self = *self >> other; - } - } - forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f } - }; -} - -// FIXME (#23545): uncomment the remaining impls -macro_rules! sh_impl_all { - ($($t:ident)*) => ($( - //sh_impl_unsigned! { $t, u8 } - //sh_impl_unsigned! { $t, u16 } - //sh_impl_unsigned! { $t, u32 } - //sh_impl_unsigned! { $t, u64 } - //sh_impl_unsigned! { $t, u128 } - sh_impl_unsigned! { $t, usize } - - //sh_impl_signed! { $t, i8 } - //sh_impl_signed! { $t, i16 } - //sh_impl_signed! { $t, i32 } - //sh_impl_signed! { $t, i64 } - //sh_impl_signed! { $t, i128 } - //sh_impl_signed! { $t, isize } - )*) -} - -sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } +// FIXME the correct implementation is not clear. Waiting for a real world use case at https://github.com/rust-lang/libs-team/issues/230 +// +// #[allow(unused_macros)] +// macro_rules! sh_impl_signed { +// ($t:ident, $f:ident) => { +// // FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065 +// // +// // #[unstable(feature = "saturating_int_impl", issue = "87920")] +// // impl Shl<$f> for Saturating<$t> { +// // type Output = Saturating<$t>; +// // +// // #[inline] +// // fn shl(self, other: $f) -> Saturating<$t> { +// // if other < 0 { +// // Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32)) +// // } else { +// // Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32)) +// // } +// // } +// // } +// // forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f, +// // #[unstable(feature = "saturating_int_impl", issue = "87920")] } +// // +// // #[unstable(feature = "saturating_int_impl", issue = "87920")] +// // impl ShlAssign<$f> for Saturating<$t> { +// // #[inline] +// // fn shl_assign(&mut self, other: $f) { +// // *self = *self << other; +// // } +// // } +// // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl Shr<$f> for Saturating<$t> { +// type Output = Saturating<$t>; +// +// #[inline] +// fn shr(self, other: $f) -> Saturating<$t> { +// if other < 0 { +// Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32)) +// } else { +// Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32)) +// } +// } +// } +// forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl ShrAssign<$f> for Saturating<$t> { +// #[inline] +// fn shr_assign(&mut self, other: $f) { +// *self = *self >> other; +// } +// } +// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f } +// }; +// } +// +// macro_rules! sh_impl_unsigned { +// ($t:ident, $f:ident) => { +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl Shl<$f> for Saturating<$t> { +// type Output = Saturating<$t>; +// +// #[inline] +// fn shl(self, other: $f) -> Saturating<$t> { +// Saturating(self.0.wrapping_shl(other as u32)) +// } +// } +// forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl ShlAssign<$f> for Saturating<$t> { +// #[inline] +// fn shl_assign(&mut self, other: $f) { +// *self = *self << other; +// } +// } +// forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl Shr<$f> for Saturating<$t> { +// type Output = Saturating<$t>; +// +// #[inline] +// fn shr(self, other: $f) -> Saturating<$t> { +// Saturating(self.0.wrapping_shr(other as u32)) +// } +// } +// forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f, +// #[unstable(feature = "saturating_int_impl", issue = "87920")] } +// +// #[unstable(feature = "saturating_int_impl", issue = "87920")] +// impl ShrAssign<$f> for Saturating<$t> { +// #[inline] +// fn shr_assign(&mut self, other: $f) { +// *self = *self >> other; +// } +// } +// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f } +// }; +// } +// +// // FIXME (#23545): uncomment the remaining impls +// macro_rules! sh_impl_all { +// ($($t:ident)*) => ($( +// //sh_impl_unsigned! { $t, u8 } +// //sh_impl_unsigned! { $t, u16 } +// //sh_impl_unsigned! { $t, u32 } +// //sh_impl_unsigned! { $t, u64 } +// //sh_impl_unsigned! { $t, u128 } +// sh_impl_unsigned! { $t, usize } +// +// //sh_impl_signed! { $t, i8 } +// //sh_impl_signed! { $t, i16 } +// //sh_impl_signed! { $t, i32 } +// //sh_impl_signed! { $t, i64 } +// //sh_impl_signed! { $t, i128 } +// //sh_impl_signed! { $t, isize } +// )*) +// } +// +// sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } // FIXME(30524): impl Op<T> for Saturating<T>, impl OpAssign<T> for Saturating<T> macro_rules! saturating_impl { ($($t:ty)*) => ($( - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl Add for Saturating<$t> { type Output = Saturating<$t>; @@ -215,9 +220,9 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Add, add for Saturating<$t>, Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl AddAssign for Saturating<$t> { #[inline] fn add_assign(&mut self, other: Saturating<$t>) { @@ -226,7 +231,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, Saturating<$t> } - #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] impl AddAssign<$t> for Saturating<$t> { #[inline] fn add_assign(&mut self, other: $t) { @@ -235,7 +240,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, $t } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl Sub for Saturating<$t> { type Output = Saturating<$t>; @@ -245,9 +250,9 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Sub, sub for Saturating<$t>, Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl SubAssign for Saturating<$t> { #[inline] fn sub_assign(&mut self, other: Saturating<$t>) { @@ -256,7 +261,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, Saturating<$t> } - #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] impl SubAssign<$t> for Saturating<$t> { #[inline] fn sub_assign(&mut self, other: $t) { @@ -265,7 +270,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, $t } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl Mul for Saturating<$t> { type Output = Saturating<$t>; @@ -275,9 +280,9 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Mul, mul for Saturating<$t>, Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl MulAssign for Saturating<$t> { #[inline] fn mul_assign(&mut self, other: Saturating<$t>) { @@ -286,7 +291,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, Saturating<$t> } - #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] impl MulAssign<$t> for Saturating<$t> { #[inline] fn mul_assign(&mut self, other: $t) { @@ -300,7 +305,6 @@ macro_rules! saturating_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(Saturating(2", stringify!($t), "), Saturating(5", stringify!($t), ") / Saturating(2));")] @@ -309,12 +313,11 @@ macro_rules! saturating_impl { /// ``` /// /// ```should_panic - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let _ = Saturating(0", stringify!($t), ") / Saturating(0);")] /// ``` - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl Div for Saturating<$t> { type Output = Saturating<$t>; @@ -324,10 +327,10 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Div, div for Saturating<$t>, Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl DivAssign for Saturating<$t> { #[inline] fn div_assign(&mut self, other: Saturating<$t>) { @@ -336,7 +339,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, Saturating<$t> } - #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] impl DivAssign<$t> for Saturating<$t> { #[inline] fn div_assign(&mut self, other: $t) { @@ -345,7 +348,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, $t } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl Rem for Saturating<$t> { type Output = Saturating<$t>; @@ -355,9 +358,9 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl Rem, rem for Saturating<$t>, Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl RemAssign for Saturating<$t> { #[inline] fn rem_assign(&mut self, other: Saturating<$t>) { @@ -366,7 +369,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, Saturating<$t> } - #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] impl RemAssign<$t> for Saturating<$t> { #[inline] fn rem_assign(&mut self, other: $t) { @@ -375,7 +378,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, $t } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl Not for Saturating<$t> { type Output = Saturating<$t>; @@ -385,9 +388,9 @@ macro_rules! saturating_impl { } } forward_ref_unop! { impl Not, not for Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl BitXor for Saturating<$t> { type Output = Saturating<$t>; @@ -397,9 +400,9 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl BitXorAssign for Saturating<$t> { #[inline] fn bitxor_assign(&mut self, other: Saturating<$t>) { @@ -408,7 +411,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, Saturating<$t> } - #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] impl BitXorAssign<$t> for Saturating<$t> { #[inline] fn bitxor_assign(&mut self, other: $t) { @@ -417,7 +420,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, $t } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl BitOr for Saturating<$t> { type Output = Saturating<$t>; @@ -427,9 +430,9 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl BitOrAssign for Saturating<$t> { #[inline] fn bitor_assign(&mut self, other: Saturating<$t>) { @@ -438,7 +441,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, Saturating<$t> } - #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] impl BitOrAssign<$t> for Saturating<$t> { #[inline] fn bitor_assign(&mut self, other: $t) { @@ -447,7 +450,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, $t } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl BitAnd for Saturating<$t> { type Output = Saturating<$t>; @@ -457,9 +460,9 @@ macro_rules! saturating_impl { } } forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl BitAndAssign for Saturating<$t> { #[inline] fn bitand_assign(&mut self, other: Saturating<$t>) { @@ -468,7 +471,7 @@ macro_rules! saturating_impl { } forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, Saturating<$t> } - #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] + #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")] impl BitAndAssign<$t> for Saturating<$t> { #[inline] fn bitand_assign(&mut self, other: $t) { @@ -492,12 +495,11 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MIN, Saturating(", stringify!($t), "::MIN));")] /// ``` - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const MIN: Self = Self(<$t>::MIN); /// Returns the largest value that can be represented by this integer type. @@ -507,12 +509,11 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MAX, Saturating(", stringify!($t), "::MAX));")] /// ``` - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const MAX: Self = Self(<$t>::MAX); /// Returns the size of this integer type in bits. @@ -522,12 +523,11 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::BITS, ", stringify!($t), "::BITS);")] /// ``` - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const BITS: u32 = <$t>::BITS; /// Returns the number of ones in the binary representation of `self`. @@ -537,7 +537,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let n = Saturating(0b01001100", stringify!($t), ");")] @@ -549,7 +548,8 @@ macro_rules! saturating_int_impl { #[doc(alias = "popcnt")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn count_ones(self) -> u32 { self.0.count_ones() } @@ -561,7 +561,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(Saturating(!0", stringify!($t), ").count_zeros(), 0);")] @@ -569,7 +568,8 @@ macro_rules! saturating_int_impl { #[inline] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn count_zeros(self) -> u32 { self.0.count_zeros() } @@ -581,7 +581,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let n = Saturating(0b0101000", stringify!($t), ");")] @@ -591,7 +590,8 @@ macro_rules! saturating_int_impl { #[inline] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn trailing_zeros(self) -> u32 { self.0.trailing_zeros() } @@ -608,7 +608,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// /// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF); @@ -619,7 +618,8 @@ macro_rules! saturating_int_impl { #[inline] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn rotate_left(self, n: u32) -> Self { Saturating(self.0.rotate_left(n)) } @@ -636,7 +636,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// /// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF); @@ -647,7 +646,8 @@ macro_rules! saturating_int_impl { #[inline] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn rotate_right(self, n: u32) -> Self { Saturating(self.0.rotate_right(n)) } @@ -659,7 +659,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// /// let n: Saturating<i16> = Saturating(0b0000000_01010101); @@ -673,7 +672,8 @@ macro_rules! saturating_int_impl { #[inline] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn swap_bytes(self) -> Self { Saturating(self.0.swap_bytes()) } @@ -688,7 +688,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// /// let n = Saturating(0b0000000_01010101i16); @@ -700,8 +699,8 @@ macro_rules! saturating_int_impl { /// assert_eq!(m, Saturating(-22016)); /// ``` #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] - #[rustc_const_unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn reverse_bits(self) -> Self { @@ -718,7 +717,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")] @@ -731,7 +729,8 @@ macro_rules! saturating_int_impl { /// ``` #[inline] #[must_use] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn from_be(x: Self) -> Self { Saturating(<$t>::from_be(x.0)) } @@ -746,7 +745,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")] @@ -759,7 +757,8 @@ macro_rules! saturating_int_impl { /// ``` #[inline] #[must_use] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn from_le(x: Self) -> Self { Saturating(<$t>::from_le(x.0)) } @@ -774,7 +773,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")] @@ -786,7 +784,8 @@ macro_rules! saturating_int_impl { /// } /// ``` #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn to_be(self) -> Self { @@ -803,7 +802,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")] @@ -815,7 +813,8 @@ macro_rules! saturating_int_impl { /// } /// ``` #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn to_le(self) -> Self { @@ -829,7 +828,6 @@ macro_rules! saturating_int_impl { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(Saturating(3", stringify!($t), ").pow(4), Saturating(81));")] @@ -838,17 +836,17 @@ macro_rules! saturating_int_impl { /// Results that are too large are saturated: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// /// assert_eq!(Saturating(3i8).pow(5), Saturating(127)); /// assert_eq!(Saturating(3i8).pow(6), Saturating(127)); /// ``` #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn pow(self, exp: u32) -> Self { + pub const fn pow(self, exp: u32) -> Self { Saturating(self.0.saturating_pow(exp)) } } @@ -867,7 +865,6 @@ macro_rules! saturating_int_impl_signed { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")] @@ -875,7 +872,8 @@ macro_rules! saturating_int_impl_signed { /// assert_eq!(n.leading_zeros(), 3); /// ``` #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn leading_zeros(self) -> u32 { @@ -890,7 +888,6 @@ macro_rules! saturating_int_impl_signed { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(Saturating(100", stringify!($t), ").abs(), Saturating(100));")] @@ -900,10 +897,11 @@ macro_rules! saturating_int_impl_signed { #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MAX));")] /// ``` #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn abs(self) -> Saturating<$t> { + pub const fn abs(self) -> Saturating<$t> { Saturating(self.0.saturating_abs()) } @@ -918,7 +916,6 @@ macro_rules! saturating_int_impl_signed { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert_eq!(Saturating(10", stringify!($t), ").signum(), Saturating(1));")] @@ -926,10 +923,11 @@ macro_rules! saturating_int_impl_signed { #[doc = concat!("assert_eq!(Saturating(-10", stringify!($t), ").signum(), Saturating(-1));")] /// ``` #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - pub fn signum(self) -> Saturating<$t> { + pub const fn signum(self) -> Saturating<$t> { Saturating(self.0.signum()) } @@ -941,7 +939,6 @@ macro_rules! saturating_int_impl_signed { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert!(Saturating(10", stringify!($t), ").is_positive());")] @@ -949,7 +946,8 @@ macro_rules! saturating_int_impl_signed { /// ``` #[must_use] #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn is_positive(self) -> bool { self.0.is_positive() } @@ -962,7 +960,6 @@ macro_rules! saturating_int_impl_signed { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert!(Saturating(-10", stringify!($t), ").is_negative());")] @@ -970,13 +967,14 @@ macro_rules! saturating_int_impl_signed { /// ``` #[must_use] #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub const fn is_negative(self) -> bool { self.0.is_negative() } } - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] impl Neg for Saturating<$t> { type Output = Self; #[inline] @@ -985,7 +983,7 @@ macro_rules! saturating_int_impl_signed { } } forward_ref_unop! { impl Neg, neg for Saturating<$t>, - #[unstable(feature = "saturating_int_impl", issue = "87920")] } + #[stable(feature = "saturating_int_impl", since = "1.74.0")] } )*) } @@ -1001,7 +999,6 @@ macro_rules! saturating_int_impl_unsigned { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")] @@ -1009,7 +1006,8 @@ macro_rules! saturating_int_impl_unsigned { /// assert_eq!(n.leading_zeros(), 2); /// ``` #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn leading_zeros(self) -> u32 { @@ -1023,7 +1021,6 @@ macro_rules! saturating_int_impl_unsigned { /// Basic usage: /// /// ``` - /// #![feature(saturating_int_impl)] /// use std::num::Saturating; /// #[doc = concat!("assert!(Saturating(16", stringify!($t), ").is_power_of_two());")] @@ -1031,8 +1028,9 @@ macro_rules! saturating_int_impl_unsigned { /// ``` #[must_use] #[inline] - #[unstable(feature = "saturating_int_impl", issue = "87920")] - pub fn is_power_of_two(self) -> bool { + #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")] + #[stable(feature = "saturating_int_impl", since = "1.74.0")] + pub const fn is_power_of_two(self) -> bool { self.0.is_power_of_two() } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 23ca37817..a9c5312a1 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1259,6 +1259,10 @@ macro_rules! uint_impl { /// This function exists, so that all operations /// are accounted for in the wrapping operations. /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// /// # Examples /// /// Basic usage: @@ -1284,6 +1288,10 @@ macro_rules! uint_impl { /// definitions of division are equal, this /// is exactly equal to `self.wrapping_div(rhs)`. /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// /// # Examples /// /// Basic usage: @@ -1307,6 +1315,10 @@ macro_rules! uint_impl { /// This function exists, so that all operations /// are accounted for in the wrapping operations. /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// /// # Examples /// /// Basic usage: @@ -1333,6 +1345,10 @@ macro_rules! uint_impl { /// definitions of division are equal, this /// is exactly equal to `self.wrapping_rem(rhs)`. /// + /// # Panics + /// + /// This function will panic if `rhs` is 0. + /// /// # Examples /// /// Basic usage: @@ -1979,6 +1995,54 @@ macro_rules! uint_impl { acc * base } + /// Returns the square root of the number, rounded down. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn isqrt(self) -> Self { + if self < 2 { + return self; + } + + // The algorithm is based on the one presented in + // <https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)> + // which cites as source the following C code: + // <https://web.archive.org/web/20120306040058/http://medialab.freaknet.org/martin/src/sqrt/sqrt.c>. + + let mut op = self; + let mut res = 0; + let mut one = 1 << (self.ilog2() & !1); + + while one != 0 { + if op >= res + one { + op -= res + one; + res = (res >> 1) + one; + } else { + res >>= 1; + } + one >>= 2; + } + + // SAFETY: the result is positive and fits in an integer with half as many bits. + // Inform the optimizer about it. + unsafe { + intrinsics::assume(0 < res); + intrinsics::assume(res < 1 << (Self::BITS / 2)); + } + + res + } + /// Performs Euclidean division. /// /// Since, for the positive integers, all common diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs index ed354a2e5..16f0b6d91 100644 --- a/library/core/src/num/wrapping.rs +++ b/library/core/src/num/wrapping.rs @@ -39,6 +39,7 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign}; #[stable(feature = "rust1", since = "1.0.0")] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] #[repr(transparent)] +#[rustc_diagnostic_item = "Wrapping"] pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T); #[stable(feature = "rust1", since = "1.0.0")] |