Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #91983

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,8 @@ extern "rust-intrinsic" {
/// The preferred alignment of a type.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_pref_align_of", issue = "none")]
/// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971).
#[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")]
pub fn pref_align_of<T>() -> usize;

/// The size of the referenced value in bytes.
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/mem/manually_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl<T> ManuallyDrop<T> {
/// ```
#[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
#[stable(feature = "manually_drop", since = "1.20.0")]
#[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
#[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
#[inline(always)]
pub const fn new(value: T) -> ManuallyDrop<T> {
ManuallyDrop { value }
Expand All @@ -82,7 +82,7 @@ impl<T> ManuallyDrop<T> {
/// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
/// ```
#[stable(feature = "manually_drop", since = "1.20.0")]
#[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
#[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
#[inline(always)]
pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
slot.value
Expand Down
100 changes: 100 additions & 0 deletions library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,106 @@ impl f32 {
self.to_bits() & 0x8000_0000 != 0
}

/// Returns the least number greater than `self`.
///
/// Let `TINY` be the smallest representable positive `f32`. Then,
/// - if `self.is_nan()`, this returns `self`;
/// - if `self` is [`NEG_INFINITY`], this returns [`MIN`];
/// - if `self` is `-TINY`, this returns -0.0;
/// - if `self` is -0.0 or +0.0, this returns `TINY`;
/// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`];
/// - otherwise the unique least value greater than `self` is returned.
///
/// The identity `x.next_up() == -(-x).next_down()` holds for all `x`. When `x`
/// is finite `x == x.next_up().next_down()` also holds.
///
/// ```rust
/// #![feature(float_next_up_down)]
/// // f32::EPSILON is the difference between 1.0 and the next number up.
/// assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
/// // But not for most numbers.
/// assert!(0.1f32.next_up() < 0.1 + f32::EPSILON);
/// assert_eq!(16777216f32.next_up(), 16777218.0);
/// ```
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_up(self) -> Self {
// We must use strictly integer arithmetic to prevent denormals from
// flushing to zero after an arithmetic operation on some platforms.
const TINY_BITS: u32 = 0x1; // Smallest positive f32.
const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff;

let bits = self.to_bits();
if self.is_nan() || bits == Self::INFINITY.to_bits() {
return self;
}

let abs = bits & CLEAR_SIGN_MASK;
let next_bits = if abs == 0 {
TINY_BITS
} else if bits == abs {
bits + 1
} else {
bits - 1
};
Self::from_bits(next_bits)
}

/// Returns the greatest number less than `self`.
///
/// Let `TINY` be the smallest representable positive `f32`. Then,
/// - if `self.is_nan()`, this returns `self`;
/// - if `self` is [`INFINITY`], this returns [`MAX`];
/// - if `self` is `TINY`, this returns 0.0;
/// - if `self` is -0.0 or +0.0, this returns `-TINY`;
/// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`];
/// - otherwise the unique greatest value less than `self` is returned.
///
/// The identity `x.next_down() == -(-x).next_up()` holds for all `x`. When `x`
/// is finite `x == x.next_down().next_up()` also holds.
///
/// ```rust
/// #![feature(float_next_up_down)]
/// let x = 1.0f32;
/// // Clamp value into range [0, 1).
/// let clamped = x.clamp(0.0, 1.0f32.next_down());
/// assert!(clamped < 1.0);
/// assert_eq!(clamped.next_up(), 1.0);
/// ```
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_down(self) -> Self {
// We must use strictly integer arithmetic to prevent denormals from
// flushing to zero after an arithmetic operation on some platforms.
const NEG_TINY_BITS: u32 = 0x8000_0001; // Smallest (in magnitude) negative f32.
const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff;

let bits = self.to_bits();
if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() {
return self;
}

let abs = bits & CLEAR_SIGN_MASK;
let next_bits = if abs == 0 {
NEG_TINY_BITS
} else if bits == abs {
bits - 1
} else {
bits + 1
};
Self::from_bits(next_bits)
}

/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```
Expand Down
100 changes: 100 additions & 0 deletions library/core/src/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,106 @@ impl f64 {
self.is_sign_negative()
}

/// Returns the least number greater than `self`.
///
/// Let `TINY` be the smallest representable positive `f64`. Then,
/// - if `self.is_nan()`, this returns `self`;
/// - if `self` is [`NEG_INFINITY`], this returns [`MIN`];
/// - if `self` is `-TINY`, this returns -0.0;
/// - if `self` is -0.0 or +0.0, this returns `TINY`;
/// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`];
/// - otherwise the unique least value greater than `self` is returned.
///
/// The identity `x.next_up() == -(-x).next_down()` holds for all `x`. When `x`
/// is finite `x == x.next_up().next_down()` also holds.
///
/// ```rust
/// #![feature(float_next_up_down)]
/// // f64::EPSILON is the difference between 1.0 and the next number up.
/// assert_eq!(1.0f64.next_up(), 1.0 + f64::EPSILON);
/// // But not for most numbers.
/// assert!(0.1f64.next_up() < 0.1 + f64::EPSILON);
/// assert_eq!(9007199254740992f64.next_up(), 9007199254740994.0);
/// ```
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_up(self) -> Self {
// We must use strictly integer arithmetic to prevent denormals from
// flushing to zero after an arithmetic operation on some platforms.
const TINY_BITS: u64 = 0x1; // Smallest positive f64.
const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff;

let bits = self.to_bits();
if self.is_nan() || bits == Self::INFINITY.to_bits() {
return self;
}

let abs = bits & CLEAR_SIGN_MASK;
let next_bits = if abs == 0 {
TINY_BITS
} else if bits == abs {
bits + 1
} else {
bits - 1
};
Self::from_bits(next_bits)
}

/// Returns the greatest number less than `self`.
///
/// Let `TINY` be the smallest representable positive `f64`. Then,
/// - if `self.is_nan()`, this returns `self`;
/// - if `self` is [`INFINITY`], this returns [`MAX`];
/// - if `self` is `TINY`, this returns 0.0;
/// - if `self` is -0.0 or +0.0, this returns `-TINY`;
/// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`];
/// - otherwise the unique greatest value less than `self` is returned.
///
/// The identity `x.next_down() == -(-x).next_up()` holds for all `x`. When `x`
/// is finite `x == x.next_down().next_up()` also holds.
///
/// ```rust
/// #![feature(float_next_up_down)]
/// let x = 1.0f64;
/// // Clamp value into range [0, 1).
/// let clamped = x.clamp(0.0, 1.0f64.next_down());
/// assert!(clamped < 1.0);
/// assert_eq!(clamped.next_up(), 1.0);
/// ```
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_down(self) -> Self {
// We must use strictly integer arithmetic to prevent denormals from
// flushing to zero after an arithmetic operation on some platforms.
const NEG_TINY_BITS: u64 = 0x8000_0000_0000_0001; // Smallest (in magnitude) negative f64.
const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff;

let bits = self.to_bits();
if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() {
return self;
}

let abs = bits & CLEAR_SIGN_MASK;
let next_bits = if abs == 0 {
NEG_TINY_BITS
} else if bits == abs {
bits - 1
} else {
bits + 1
};
Self::from_bits(next_bits)
}

/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```
Expand Down
75 changes: 75 additions & 0 deletions library/std/src/f32/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,81 @@ fn test_is_sign_negative() {
assert!((-f32::NAN).is_sign_negative());
}

#[test]
fn test_next_up() {
let tiny = f32::from_bits(1);
let tiny_up = f32::from_bits(2);
let max_down = f32::from_bits(0x7f7f_fffe);
let largest_subnormal = f32::from_bits(0x007f_ffff);
let smallest_normal = f32::from_bits(0x0080_0000);

// Check that NaNs roundtrip.
// Ignore test on x87 floating point, the code is still correct but these
// platforms do not guarantee NaN payloads are preserved, which caused these
// tests to fail.
#[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))]
{
let nan0 = f32::NAN;
let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa);
let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555);
assert_eq!(nan0.next_up().to_bits(), nan0.to_bits());
assert_eq!(nan1.next_up().to_bits(), nan1.to_bits());
assert_eq!(nan2.next_up().to_bits(), nan2.to_bits());
}

assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN);
assert_eq!(f32::MIN.next_up(), -max_down);
assert_eq!((-1.0 - f32::EPSILON).next_up(), -1.0);
assert_eq!((-smallest_normal).next_up(), -largest_subnormal);
assert_eq!((-tiny_up).next_up(), -tiny);
assert_eq!((-tiny).next_up().to_bits(), (-0.0f32).to_bits());
assert_eq!((-0.0f32).next_up(), tiny);
assert_eq!(0.0f32.next_up(), tiny);
assert_eq!(tiny.next_up(), tiny_up);
assert_eq!(largest_subnormal.next_up(), smallest_normal);
assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
assert_eq!(f32::MAX.next_up(), f32::INFINITY);
assert_eq!(f32::INFINITY.next_up(), f32::INFINITY);
}

#[test]
fn test_next_down() {
let tiny = f32::from_bits(1);
let tiny_up = f32::from_bits(2);
let max_down = f32::from_bits(0x7f7f_fffe);
let largest_subnormal = f32::from_bits(0x007f_ffff);
let smallest_normal = f32::from_bits(0x0080_0000);

// Check that NaNs roundtrip.
// Ignore test on x87 floating point, the code is still correct but these
// platforms do not guarantee NaN payloads are preserved, which caused these
// tests to fail.
#[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))]
{
let nan0 = f32::NAN;
let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa);
let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555);
assert_eq!(nan0.next_down().to_bits(), nan0.to_bits());
assert_eq!(nan1.next_down().to_bits(), nan1.to_bits());
assert_eq!(nan2.next_down().to_bits(), nan2.to_bits());
}

assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY);
assert_eq!((-max_down).next_down(), f32::MIN);
assert_eq!((-1.0f32).next_down(), -1.0 - f32::EPSILON);
assert_eq!((-largest_subnormal).next_down(), -smallest_normal);
assert_eq!((-tiny).next_down(), -tiny_up);
assert_eq!((-0.0f32).next_down(), -tiny);
assert_eq!((0.0f32).next_down(), -tiny);
assert_eq!(tiny.next_down().to_bits(), 0.0f32.to_bits());
assert_eq!(tiny_up.next_down(), tiny);
assert_eq!(smallest_normal.next_down(), largest_subnormal);
assert_eq!((1.0 + f32::EPSILON).next_down(), 1.0f32);
assert_eq!(f32::MAX.next_down(), max_down);
assert_eq!(f32::INFINITY.next_down(), f32::MAX);
}

#[test]
fn test_mul_add() {
let nan: f32 = f32::NAN;
Expand Down
Loading