Skip to content

Commit

Permalink
Rollup merge of #95483 - golddranks:improve_float_docs, r=joshtriplett
Browse files Browse the repository at this point in the history
Improve floating point documentation

This is my attempt to improve/solve rust-lang/rust#95468 and rust-lang/rust#73328 .

Added/refined explanations:
- Refine the "NaN as a special value" top level explanation of f32
- Refine `const NAN` docstring: add an explanation about there being multitude of NaN bitpatterns and disclaimer about the portability/stability guarantees.
- Refine `fn is_sign_positive` and `fn is_sign_negative` docstrings: add disclaimer about the sign bit of NaNs.
- Refine `fn min` and `fn max` docstrings: explain the semantics and their relationship to the standard and libm better.
- Refine `fn trunc` docstrings: explain the semantics slightly more.
- Refine `fn powi` docstrings: add disclaimer that the rounding behaviour might be different from `powf`.
- Refine `fn copysign` docstrings: add disclaimer about payloads of NaNs.
- Refine `minimum` and `maximum`: add disclaimer that "propagating NaN" doesn't mean that propagating the NaN bit patterns is guaranteed.
- Refine `max` and `min` docstrings: add "ignoring NaN" to bring the one-row explanation to parity with `minimum` and `maximum`.

Cosmetic changes:
- Reword `NaN` and `NAN` as plain "NaN", unless they refer to the specific `const NAN`.
- Reword "a number" to `self` in function docstrings to clarify.
- Remove "Returns NAN if the number is NAN" from `abs`, as this is told to be the default behavior in the top explanation.
matthiaskrgr authored May 9, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 6f54d0d + f535aed commit e5bb4d2
Showing 6 changed files with 182 additions and 68 deletions.
79 changes: 60 additions & 19 deletions core/src/num/f32.rs
Original file line number Diff line number Diff line change
@@ -393,6 +393,15 @@ impl f32 {
pub const MAX_10_EXP: i32 = 38;

/// Not a Number (NaN).
///
/// Note that IEEE-745 doesn't define just a single NaN value;
/// a plethora of bit patterns are considered to be NaN.
/// Furthermore, the standard makes a difference
/// between a "signaling" and a "quiet" NaN,
/// and allows inspecting its "payload" (the unspecified bits in the bit pattern).
/// This constant isn't guaranteed to equal to any specific NaN bitpattern,
/// and the stability of its representation over Rust versions
/// and target platforms isn't guaranteed.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const NAN: f32 = 0.0_f32 / 0.0_f32;
/// Infinity (∞).
@@ -402,7 +411,7 @@ impl f32 {
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;

/// Returns `true` if this value is `NaN`.
/// Returns `true` if this value is NaN.
///
/// ```
/// let nan = f32::NAN;
@@ -455,7 +464,7 @@ impl f32 {
(self == f32::INFINITY) | (self == f32::NEG_INFINITY)
}

/// Returns `true` if this number is neither infinite nor `NaN`.
/// Returns `true` if this number is neither infinite nor NaN.
///
/// ```
/// let f = 7.0f32;
@@ -506,7 +515,7 @@ impl f32 {
}

/// Returns `true` if the number is neither zero, infinite,
/// [subnormal], or `NaN`.
/// [subnormal], or NaN.
///
/// ```
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
@@ -622,8 +631,12 @@ impl f32 {
}
}

/// Returns `true` if `self` has a positive sign, including `+0.0`, `NaN`s with
/// positive sign bit and positive infinity.
/// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
/// positive sign bit and positive infinity. Note that IEEE-745 doesn't assign any
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
/// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
/// See [explanation of NaN as a special value](f32) for more info.
///
/// ```
/// let f = 7.0_f32;
@@ -640,8 +653,12 @@ impl f32 {
!self.is_sign_negative()
}

/// Returns `true` if `self` has a negative sign, including `-0.0`, `NaN`s with
/// negative sign bit and negative infinity.
/// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
/// negative sign bit and negative infinity. Note that IEEE-745 doesn't assign any
/// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
/// the bit pattern of NaNs are conserved over arithmetic operations, the result of
/// `is_sign_negative` on a NaN might produce an unexpected result in some cases.
/// See [explanation of NaN as a special value](f32) for more info.
///
/// ```
/// let f = 7.0f32;
@@ -713,47 +730,47 @@ impl f32 {
self * (value / 180.0f32)
}

/// Returns the maximum of the two numbers.
/// Returns the maximum of the two numbers, ignoring NaN.
///
/// Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs.
/// This matches the behavior of libm’s fmax.
/// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
/// This also matches the behavior of libm’s fmax.
///
/// ```
/// let x = 1.0f32;
/// let y = 2.0f32;
///
/// assert_eq!(x.max(y), y);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max(self, other: f32) -> f32 {
intrinsics::maxnumf32(self, other)
}

/// Returns the minimum of the two numbers.
/// Returns the minimum of the two numbers, ignoring NaN.
///
/// Follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs.
/// This matches the behavior of libm’s fmin.
/// If one of the arguments is NaN, then the other argument is returned.
/// This follows the IEEE-754 2008 semantics for minNum, except for handling of signaling NaNs;
/// this function handles all NaNs the same way and avoids minNum's problems with associativity.
/// This also matches the behavior of libm’s fmin.
///
/// ```
/// let x = 1.0f32;
/// let y = 2.0f32;
///
/// assert_eq!(x.min(y), x);
/// ```
///
/// If one of the arguments is NaN, then the other argument is returned.
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min(self, other: f32) -> f32 {
intrinsics::minnumf32(self, other)
}

/// Returns the maximum of the two numbers, propagating NaNs.
/// Returns the maximum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f32::max`] which only returns NaN when *both* arguments are NaN.
@@ -770,6 +787,9 @@ impl f32 {
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the semantics specified in IEEE 754-2019.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see [explanation of NaN as a special value](f32) for more info.
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
@@ -785,7 +805,7 @@ impl f32 {
}
}

/// Returns the minimum of the two numbers, propagating NaNs.
/// Returns the minimum of the two numbers, propagating NaN.
///
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f32::min`] which only returns NaN when *both* arguments are NaN.
@@ -802,6 +822,9 @@ impl f32 {
/// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
/// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
/// Note that this follows the semantics specified in IEEE 754-2019.
///
/// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
/// operand is conserved; see [explanation of NaN as a special value](f32) for more info.
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
@@ -1009,6 +1032,9 @@ impl f32 {
/// Return the memory representation of this floating point number as a byte array in
/// big-endian (network) byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
///
/// # Examples
///
/// ```
@@ -1027,6 +1053,9 @@ impl f32 {
/// Return the memory representation of this floating point number as a byte array in
/// little-endian byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
///
/// # Examples
///
/// ```
@@ -1051,6 +1080,9 @@ impl f32 {
/// [`to_be_bytes`]: f32::to_be_bytes
/// [`to_le_bytes`]: f32::to_le_bytes
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
///
/// # Examples
///
/// ```
@@ -1075,6 +1107,9 @@ impl f32 {

/// Create a floating point value from its representation as a byte array in big endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
///
/// # Examples
///
/// ```
@@ -1091,6 +1126,9 @@ impl f32 {

/// Create a floating point value from its representation as a byte array in little endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
///
/// # Examples
///
/// ```
@@ -1114,6 +1152,9 @@ impl f32 {
/// [`from_be_bytes`]: f32::from_be_bytes
/// [`from_le_bytes`]: f32::from_le_bytes
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
///
/// # Examples
///
/// ```
Loading

0 comments on commit e5bb4d2

Please sign in to comment.