From c533acd015c536eabc10a1b0001f4bca6558d7e5 Mon Sep 17 00:00:00 2001
From: Pyry Kontio <pyry.kontio@drasa.eu>
Date: Thu, 31 Mar 2022 00:58:43 +0900
Subject: [PATCH 1/8] Improve floating point documentation:

- Refine the "NaN as a special value" top level explanation of f32
- Refine `const NAN` docstring.
- Refine `fn is_sign_positive` and `fn is_sign_negative` docstrings.
- Refine `fn min` and `fn max` docstrings.
- Refine `fn trunc` docstrings.
- Refine `fn powi` docstrings.
- Refine `fn copysign` docstrings.
- 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" as this is told to be the default behavior in the top explanation.
- Remove "propagating NaNs", as full propagation (preservation of payloads) is not guaranteed.
---
 core/src/num/f32.rs        | 51 +++++++++++++++++++++++++-------------
 core/src/num/f64.rs        | 51 +++++++++++++++++++++++++-------------
 core/src/primitive_docs.rs | 18 +++++++++++---
 std/src/f32.rs             | 26 +++++++++++--------
 std/src/f64.rs             | 26 +++++++++++--------
 std/src/primitive_docs.rs  | 18 +++++++++++---
 6 files changed, 126 insertions(+), 64 deletions(-)

diff --git a/core/src/num/f32.rs b/core/src/num/f32.rs
index 17ca85476..835651c50 100644
--- a/core/src/num/f32.rs
+++ b/core/src/num/f32.rs
@@ -418,6 +418,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 (∞).
@@ -427,7 +436,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;
@@ -476,7 +485,7 @@ impl f32 {
         self.abs_private() == Self::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;
@@ -527,7 +536,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
@@ -582,8 +591,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;
@@ -600,8 +613,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_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.0f32;
@@ -674,8 +691,10 @@ impl f32 {
 
     /// Returns the maximum of the two numbers.
     ///
-    /// 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;
@@ -683,8 +702,6 @@ impl f32 {
     ///
     /// 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]
@@ -694,8 +711,10 @@ impl f32 {
 
     /// Returns the minimum of the two numbers.
     ///
-    /// 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;
@@ -703,8 +722,6 @@ impl f32 {
     ///
     /// 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]
@@ -712,7 +729,7 @@ impl f32 {
         intrinsics::minnumf32(self, other)
     }
 
-    /// Returns the maximum of the two numbers, propagating NaNs.
+    /// Returns the maximum of the two numbers.
     ///
     /// This returns NaN when *either* argument is NaN, as opposed to
     /// [`f32::max`] which only returns NaN when *both* arguments are NaN.
@@ -744,7 +761,7 @@ impl f32 {
         }
     }
 
-    /// Returns the minimum of the two numbers, propagating NaNs.
+    /// Returns the minimum of the two numbers.
     ///
     /// This returns NaN when *either* argument is NaN, as opposed to
     /// [`f32::min`] which only returns NaN when *both* arguments are NaN.
diff --git a/core/src/num/f64.rs b/core/src/num/f64.rs
index 350d8529d..b0971233f 100644
--- a/core/src/num/f64.rs
+++ b/core/src/num/f64.rs
@@ -417,6 +417,15 @@ impl f64 {
     pub const MAX_10_EXP: i32 = 308;
 
     /// 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: f64 = 0.0_f64 / 0.0_f64;
     /// Infinity (∞).
@@ -426,7 +435,7 @@ impl f64 {
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
 
-    /// Returns `true` if this value is `NaN`.
+    /// Returns `true` if this value is NaN.
     ///
     /// ```
     /// let nan = f64::NAN;
@@ -475,7 +484,7 @@ impl f64 {
         self.abs_private() == Self::INFINITY
     }
 
-    /// Returns `true` if this number is neither infinite nor `NaN`.
+    /// Returns `true` if this number is neither infinite nor NaN.
     ///
     /// ```
     /// let f = 7.0f64;
@@ -526,7 +535,7 @@ impl f64 {
     }
 
     /// Returns `true` if the number is neither zero, infinite,
-    /// [subnormal], or `NaN`.
+    /// [subnormal], or NaN.
     ///
     /// ```
     /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
@@ -581,8 +590,12 @@ impl f64 {
         }
     }
 
-    /// 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_f64;
@@ -608,8 +621,12 @@ impl f64 {
         self.is_sign_positive()
     }
 
-    /// 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_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_f64;
@@ -690,8 +707,10 @@ impl f64 {
 
     /// Returns the maximum of the two numbers.
     ///
-    /// 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.0_f64;
@@ -699,8 +718,6 @@ impl f64 {
     ///
     /// 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]
@@ -710,8 +727,10 @@ impl f64 {
 
     /// Returns the minimum of the two numbers.
     ///
-    /// 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.0_f64;
@@ -719,8 +738,6 @@ impl f64 {
     ///
     /// 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]
@@ -728,7 +745,7 @@ impl f64 {
         intrinsics::minnumf64(self, other)
     }
 
-    /// Returns the maximum of the two numbers, propagating NaNs.
+    /// Returns the maximum of the two numbers.
     ///
     /// This returns NaN when *either* argument is NaN, as opposed to
     /// [`f64::max`] which only returns NaN when *both* arguments are NaN.
@@ -760,7 +777,7 @@ impl f64 {
         }
     }
 
-    /// Returns the minimum of the two numbers, propagating NaNs.
+    /// Returns the minimum of the two numbers.
     ///
     /// This returns NaN when *either* argument is NaN, as opposed to
     /// [`f64::min`] which only returns NaN when *both* arguments are NaN.
diff --git a/core/src/primitive_docs.rs b/core/src/primitive_docs.rs
index 225a679ef..188cb8f98 100644
--- a/core/src/primitive_docs.rs
+++ b/core/src/primitive_docs.rs
@@ -977,10 +977,20 @@ mod prim_tuple {}
 ///   like `1.0 / 0.0`.
 /// - [NaN (not a number)](#associatedconstant.NAN): this value results from
 ///   calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
-///   behavior: it is unequal to any float, including itself! It is also neither
-///   smaller nor greater than any float, making it impossible to sort. Lastly,
-///   it is considered infectious as almost all calculations where one of the
-///   operands is NaN will also result in NaN.
+///   behavior:
+///   - It is unequal to any float, including itself!
+///   - It is also neither smaller nor greater than any float, making it
+///     impossible to sort by the default comparison operation. This is the
+///     reason `f32` doesn't implement the `Ord` and `Eq` traits.
+///   - It is also considered *infectious* as almost all calculations where one
+///     of the operands is NaN will also result in NaN. The explanations on this
+///     page only explicitly document behavior on NaN operands if this default
+///     is *not* observed by the operation.
+///   - Lastly, there are multiple bit patterns that are considered NaN.
+///     Rust does not currently guarantee that the bit patterns of NaN are
+///     preserved over arithmetic operations,
+///     so there may be some surprising results upon inspecting the bit patterns,
+///     as the same calculations might produce NaNs with different bit patterns.
 ///
 /// For more information on floating point numbers, see [Wikipedia][wikipedia].
 ///
diff --git a/std/src/f32.rs b/std/src/f32.rs
index 70b5941c7..469db1b7c 100644
--- a/std/src/f32.rs
+++ b/std/src/f32.rs
@@ -30,7 +30,7 @@ pub use core::f32::{
 #[cfg(not(test))]
 #[cfg_attr(bootstrap, lang = "f32_runtime")]
 impl f32 {
-    /// Returns the largest integer less than or equal to a number.
+    /// Returns the largest integer less than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -51,7 +51,7 @@ impl f32 {
         unsafe { intrinsics::floorf32(self) }
     }
 
-    /// Returns the smallest integer greater than or equal to a number.
+    /// Returns the smallest integer greater than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -70,7 +70,7 @@ impl f32 {
         unsafe { intrinsics::ceilf32(self) }
     }
 
-    /// Returns the nearest integer to a number. Round half-way cases away from
+    /// Returns the nearest integer to `self`. Round half-way cases away from
     /// `0.0`.
     ///
     /// # Examples
@@ -90,7 +90,8 @@ impl f32 {
         unsafe { intrinsics::roundf32(self) }
     }
 
-    /// Returns the integer part of a number.
+    /// Returns the integer part of `self`.
+    /// This means that non-integer numbers are always truncated towards zero.
     ///
     /// # Examples
     ///
@@ -111,7 +112,7 @@ impl f32 {
         unsafe { intrinsics::truncf32(self) }
     }
 
-    /// Returns the fractional part of a number.
+    /// Returns the fractional part of `self`.
     ///
     /// # Examples
     ///
@@ -132,8 +133,7 @@ impl f32 {
         self - self.trunc()
     }
 
-    /// Computes the absolute value of `self`. Returns `NAN` if the
-    /// number is `NAN`.
+    /// Computes the absolute value of `self`.
     ///
     /// # Examples
     ///
@@ -161,7 +161,7 @@ impl f32 {
     ///
     /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
-    /// - `NAN` if the number is `NAN`
+    /// - NaN if the number is NaN
     ///
     /// # Examples
     ///
@@ -185,8 +185,10 @@ impl f32 {
     /// `sign`.
     ///
     /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
-    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
-    /// `sign` is returned.
+    /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
+    /// `sign` is returned. Note, however, that conserving the sign bit on NaN
+    /// across arithmetical operations is not generally guaranteed.
+    /// See [explanation of NaN as a special value](primitive@f32) for more info.
     ///
     /// # Examples
     ///
@@ -299,7 +301,9 @@ impl f32 {
 
     /// Raises a number to an integer power.
     ///
-    /// Using this function is generally faster than using `powf`
+    /// Using this function is generally faster than using `powf`.
+    /// It might have different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
     ///
     /// # Examples
     ///
diff --git a/std/src/f64.rs b/std/src/f64.rs
index b90d068ec..a291a777e 100644
--- a/std/src/f64.rs
+++ b/std/src/f64.rs
@@ -30,7 +30,7 @@ pub use core::f64::{
 #[cfg(not(test))]
 #[cfg_attr(bootstrap, lang = "f64_runtime")]
 impl f64 {
-    /// Returns the largest integer less than or equal to a number.
+    /// Returns the largest integer less than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -51,7 +51,7 @@ impl f64 {
         unsafe { intrinsics::floorf64(self) }
     }
 
-    /// Returns the smallest integer greater than or equal to a number.
+    /// Returns the smallest integer greater than or equal to `self`.
     ///
     /// # Examples
     ///
@@ -70,7 +70,7 @@ impl f64 {
         unsafe { intrinsics::ceilf64(self) }
     }
 
-    /// Returns the nearest integer to a number. Round half-way cases away from
+    /// Returns the nearest integer to `self`. Round half-way cases away from
     /// `0.0`.
     ///
     /// # Examples
@@ -90,7 +90,8 @@ impl f64 {
         unsafe { intrinsics::roundf64(self) }
     }
 
-    /// Returns the integer part of a number.
+    /// Returns the integer part of `self`.
+    /// This means that non-integer numbers are always truncated towards zero.
     ///
     /// # Examples
     ///
@@ -111,7 +112,7 @@ impl f64 {
         unsafe { intrinsics::truncf64(self) }
     }
 
-    /// Returns the fractional part of a number.
+    /// Returns the fractional part of `self`.
     ///
     /// # Examples
     ///
@@ -132,8 +133,7 @@ impl f64 {
         self - self.trunc()
     }
 
-    /// Computes the absolute value of `self`. Returns `NAN` if the
-    /// number is `NAN`.
+    /// Computes the absolute value of `self`.
     ///
     /// # Examples
     ///
@@ -161,7 +161,7 @@ impl f64 {
     ///
     /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
     /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
-    /// - `NAN` if the number is `NAN`
+    /// - NaN if the number is NaN
     ///
     /// # Examples
     ///
@@ -185,8 +185,10 @@ impl f64 {
     /// `sign`.
     ///
     /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
-    /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
-    /// `sign` is returned.
+    /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
+    /// `sign` is returned. Note, however, that conserving the sign bit on NaN
+    /// across arithmetical operations is not generally guaranteed.
+    /// See [explanation of NaN as a special value](primitive@f32) for more info.
     ///
     /// # Examples
     ///
@@ -299,7 +301,9 @@ impl f64 {
 
     /// Raises a number to an integer power.
     ///
-    /// Using this function is generally faster than using `powf`
+    /// Using this function is generally faster than using `powf`.
+    /// It might have different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
     ///
     /// # Examples
     ///
diff --git a/std/src/primitive_docs.rs b/std/src/primitive_docs.rs
index 225a679ef..188cb8f98 100644
--- a/std/src/primitive_docs.rs
+++ b/std/src/primitive_docs.rs
@@ -977,10 +977,20 @@ mod prim_tuple {}
 ///   like `1.0 / 0.0`.
 /// - [NaN (not a number)](#associatedconstant.NAN): this value results from
 ///   calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
-///   behavior: it is unequal to any float, including itself! It is also neither
-///   smaller nor greater than any float, making it impossible to sort. Lastly,
-///   it is considered infectious as almost all calculations where one of the
-///   operands is NaN will also result in NaN.
+///   behavior:
+///   - It is unequal to any float, including itself!
+///   - It is also neither smaller nor greater than any float, making it
+///     impossible to sort by the default comparison operation. This is the
+///     reason `f32` doesn't implement the `Ord` and `Eq` traits.
+///   - It is also considered *infectious* as almost all calculations where one
+///     of the operands is NaN will also result in NaN. The explanations on this
+///     page only explicitly document behavior on NaN operands if this default
+///     is *not* observed by the operation.
+///   - Lastly, there are multiple bit patterns that are considered NaN.
+///     Rust does not currently guarantee that the bit patterns of NaN are
+///     preserved over arithmetic operations,
+///     so there may be some surprising results upon inspecting the bit patterns,
+///     as the same calculations might produce NaNs with different bit patterns.
 ///
 /// For more information on floating point numbers, see [Wikipedia][wikipedia].
 ///

From 6901f67bbdd00b36f64b337cd1b53feee8a8c782 Mon Sep 17 00:00:00 2001
From: Pyry Kontio <pyry.kontio@drasa.eu>
Date: Thu, 31 Mar 2022 02:22:26 +0900
Subject: [PATCH 2/8] Fix: is_sign_positive -> is_sign_negative

---
 core/src/num/f32.rs | 2 +-
 core/src/num/f64.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/core/src/num/f32.rs b/core/src/num/f32.rs
index 835651c50..cae7c2694 100644
--- a/core/src/num/f32.rs
+++ b/core/src/num/f32.rs
@@ -617,7 +617,7 @@ impl f32 {
     /// 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_positive` on a NaN might produce an unexpected result in some cases.
+    /// `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.
     ///
     /// ```
diff --git a/core/src/num/f64.rs b/core/src/num/f64.rs
index b0971233f..eefb04507 100644
--- a/core/src/num/f64.rs
+++ b/core/src/num/f64.rs
@@ -625,7 +625,7 @@ impl f64 {
     /// 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_positive` on a NaN might produce an unexpected result in some cases.
+    /// `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.
     ///
     /// ```

From 699b94738524346304be1b3c98db75c5df917b62 Mon Sep 17 00:00:00 2001
From: Pyry Kontio <pyry.kontio@drasa.eu>
Date: Thu, 31 Mar 2022 02:28:52 +0900
Subject: [PATCH 3/8] Add references to explanation about portability to
 f{32,64}::{from,to}_{be,le,ne}_bytes

---
 core/src/num/f32.rs | 18 ++++++++++++++++++
 core/src/num/f64.rs | 18 ++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/core/src/num/f32.rs b/core/src/num/f32.rs
index cae7c2694..b408b5d3d 100644
--- a/core/src/num/f32.rs
+++ b/core/src/num/f32.rs
@@ -902,6 +902,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
     ///
     /// ```
@@ -920,6 +923,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
     ///
     /// ```
@@ -944,6 +950,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
     ///
     /// ```
@@ -968,6 +977,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
     ///
     /// ```
@@ -984,6 +996,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
     ///
     /// ```
@@ -1007,6 +1022,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
     ///
     /// ```
diff --git a/core/src/num/f64.rs b/core/src/num/f64.rs
index eefb04507..db3961226 100644
--- a/core/src/num/f64.rs
+++ b/core/src/num/f64.rs
@@ -918,6 +918,9 @@ impl f64 {
     /// 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
     ///
     /// ```
@@ -936,6 +939,9 @@ impl f64 {
     /// 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
     ///
     /// ```
@@ -960,6 +966,9 @@ impl f64 {
     /// [`to_be_bytes`]: f64::to_be_bytes
     /// [`to_le_bytes`]: f64::to_le_bytes
     ///
+    /// See [`from_bits`](Self::from_bits) for some discussion of the
+    /// portability of this operation (there are almost no issues).
+    ///
     /// # Examples
     ///
     /// ```
@@ -984,6 +993,9 @@ impl f64 {
 
     /// 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
     ///
     /// ```
@@ -1000,6 +1012,9 @@ impl f64 {
 
     /// 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
     ///
     /// ```
@@ -1023,6 +1038,9 @@ impl f64 {
     /// [`from_be_bytes`]: f64::from_be_bytes
     /// [`from_le_bytes`]: f64::from_le_bytes
     ///
+    /// See [`from_bits`](Self::from_bits) for some discussion of the
+    /// portability of this operation (there are almost no issues).
+    ///
     /// # Examples
     ///
     /// ```

From 2c961e5bcc64e09976507256d13030bc49c791d1 Mon Sep 17 00:00:00 2001
From: Pyry Kontio <pyry.kontio@drasa.eu>
Date: Thu, 31 Mar 2022 11:27:23 +0900
Subject: [PATCH 4/8] Improve wording of "NaN as a special value" top level
 explanation

---
 core/src/primitive_docs.rs | 9 +++++----
 std/src/primitive_docs.rs  | 9 +++++----
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/core/src/primitive_docs.rs b/core/src/primitive_docs.rs
index 188cb8f98..ab4bb0f26 100644
--- a/core/src/primitive_docs.rs
+++ b/core/src/primitive_docs.rs
@@ -978,14 +978,15 @@ mod prim_tuple {}
 /// - [NaN (not a number)](#associatedconstant.NAN): this value results from
 ///   calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
 ///   behavior:
-///   - It is unequal to any float, including itself!
+///   - It is unequal to any float, including itself! This is the reason `f32`
+///     doesn't implement the `Eq` trait.
 ///   - It is also neither smaller nor greater than any float, making it
-///     impossible to sort by the default comparison operation. This is the
-///     reason `f32` doesn't implement the `Ord` and `Eq` traits.
+///     impossible to sort by the default comparison operation, which is the
+///     reason `f32` doesn't implement the `Ord` trait.
 ///   - It is also considered *infectious* as almost all calculations where one
 ///     of the operands is NaN will also result in NaN. The explanations on this
 ///     page only explicitly document behavior on NaN operands if this default
-///     is *not* observed by the operation.
+///     is deviated from.
 ///   - Lastly, there are multiple bit patterns that are considered NaN.
 ///     Rust does not currently guarantee that the bit patterns of NaN are
 ///     preserved over arithmetic operations,
diff --git a/std/src/primitive_docs.rs b/std/src/primitive_docs.rs
index 188cb8f98..ab4bb0f26 100644
--- a/std/src/primitive_docs.rs
+++ b/std/src/primitive_docs.rs
@@ -978,14 +978,15 @@ mod prim_tuple {}
 /// - [NaN (not a number)](#associatedconstant.NAN): this value results from
 ///   calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
 ///   behavior:
-///   - It is unequal to any float, including itself!
+///   - It is unequal to any float, including itself! This is the reason `f32`
+///     doesn't implement the `Eq` trait.
 ///   - It is also neither smaller nor greater than any float, making it
-///     impossible to sort by the default comparison operation. This is the
-///     reason `f32` doesn't implement the `Ord` and `Eq` traits.
+///     impossible to sort by the default comparison operation, which is the
+///     reason `f32` doesn't implement the `Ord` trait.
 ///   - It is also considered *infectious* as almost all calculations where one
 ///     of the operands is NaN will also result in NaN. The explanations on this
 ///     page only explicitly document behavior on NaN operands if this default
-///     is *not* observed by the operation.
+///     is deviated from.
 ///   - Lastly, there are multiple bit patterns that are considered NaN.
 ///     Rust does not currently guarantee that the bit patterns of NaN are
 ///     preserved over arithmetic operations,

From 32841ec93a594f196e10e37c41ac81f5dd77a04f Mon Sep 17 00:00:00 2001
From: Pyry Kontio <pyry.kontio@drasa.eu>
Date: Thu, 31 Mar 2022 17:59:36 +0900
Subject: [PATCH 5/8] Re-introduce "propagating NaN" to `maximum`/`minimum`,
 add "ignoring NaN" to `max`/`min`, add disclaimer about the "propagation".

---
 core/src/num/f32.rs | 14 ++++++++++----
 core/src/num/f64.rs | 14 ++++++++++----
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/core/src/num/f32.rs b/core/src/num/f32.rs
index b408b5d3d..e3d40b58a 100644
--- a/core/src/num/f32.rs
+++ b/core/src/num/f32.rs
@@ -689,7 +689,7 @@ impl f32 {
         self * (value / 180.0f32)
     }
 
-    /// Returns the maximum of the two numbers.
+    /// Returns the maximum of the two numbers, ignoring NaN.
     ///
     /// 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;
@@ -709,7 +709,7 @@ impl f32 {
         intrinsics::maxnumf32(self, other)
     }
 
-    /// Returns the minimum of the two numbers.
+    /// Returns the minimum of the two numbers, ignoring NaN.
     ///
     /// 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;
@@ -729,7 +729,7 @@ impl f32 {
         intrinsics::minnumf32(self, other)
     }
 
-    /// Returns the maximum of the two numbers.
+    /// 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.
@@ -746,6 +746,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 mean that the bitpattern of a NaN operand
+    /// is necessarily 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]
@@ -761,7 +764,7 @@ impl f32 {
         }
     }
 
-    /// Returns the minimum of the two numbers.
+    /// 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.
@@ -778,6 +781,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 mean that the bitpattern of a NaN operand
+    /// is necessarily 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]
diff --git a/core/src/num/f64.rs b/core/src/num/f64.rs
index db3961226..51ccf7e85 100644
--- a/core/src/num/f64.rs
+++ b/core/src/num/f64.rs
@@ -705,7 +705,7 @@ impl f64 {
         self * (value / 180.0)
     }
 
-    /// Returns the maximum of the two numbers.
+    /// Returns the maximum of the two numbers, ignoring NaN.
     ///
     /// 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;
@@ -725,7 +725,7 @@ impl f64 {
         intrinsics::maxnumf64(self, other)
     }
 
-    /// Returns the minimum of the two numbers.
+    /// Returns the minimum of the two numbers, ignoring NaN.
     ///
     /// 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;
@@ -745,7 +745,7 @@ impl f64 {
         intrinsics::minnumf64(self, other)
     }
 
-    /// Returns the maximum of the two numbers.
+    /// Returns the maximum of the two numbers, propagating NaN.
     ///
     /// This returns NaN when *either* argument is NaN, as opposed to
     /// [`f64::max`] which only returns NaN when *both* arguments are NaN.
@@ -762,6 +762,9 @@ impl f64 {
     /// 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 mean that the bitpattern of a NaN operand
+    /// is necessarily 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]
@@ -777,7 +780,7 @@ impl f64 {
         }
     }
 
-    /// Returns the minimum of the two numbers.
+    /// Returns the minimum of the two numbers, propagating NaN.
     ///
     /// This returns NaN when *either* argument is NaN, as opposed to
     /// [`f64::min`] which only returns NaN when *both* arguments are NaN.
@@ -794,6 +797,9 @@ impl f64 {
     /// 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 mean that the bitpattern of a NaN operand
+    /// is necessarily 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]

From 1add72d8e9ce51bacde40fff2f4e0020a41b4595 Mon Sep 17 00:00:00 2001
From: Pyry Kontio <pyry.kontio@drasa.eu>
Date: Thu, 31 Mar 2022 18:18:10 +0900
Subject: [PATCH 6/8] Further refine the disclaimer about NaN bit patterns.

---
 core/src/primitive_docs.rs | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/core/src/primitive_docs.rs b/core/src/primitive_docs.rs
index ab4bb0f26..ac4e66811 100644
--- a/core/src/primitive_docs.rs
+++ b/core/src/primitive_docs.rs
@@ -989,8 +989,9 @@ mod prim_tuple {}
 ///     is deviated from.
 ///   - Lastly, there are multiple bit patterns that are considered NaN.
 ///     Rust does not currently guarantee that the bit patterns of NaN are
-///     preserved over arithmetic operations,
-///     so there may be some surprising results upon inspecting the bit patterns,
+///     preserved over arithmetic operations, and they are not guaranteed to be
+///     portable or even fully deterministic! This means that there may be some
+///     surprising results upon inspecting the bit patterns,
 ///     as the same calculations might produce NaNs with different bit patterns.
 ///
 /// For more information on floating point numbers, see [Wikipedia][wikipedia].

From c18aee76036bad42f6e48af9fb502f18ff81f5ec Mon Sep 17 00:00:00 2001
From: Pyry Kontio <pyry.kontio@drasa.eu>
Date: Thu, 31 Mar 2022 18:50:14 +0900
Subject: [PATCH 7/8] match std f32 primitive docs to core f32 primitive docs

---
 std/src/primitive_docs.rs | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/std/src/primitive_docs.rs b/std/src/primitive_docs.rs
index ab4bb0f26..ac4e66811 100644
--- a/std/src/primitive_docs.rs
+++ b/std/src/primitive_docs.rs
@@ -989,8 +989,9 @@ mod prim_tuple {}
 ///     is deviated from.
 ///   - Lastly, there are multiple bit patterns that are considered NaN.
 ///     Rust does not currently guarantee that the bit patterns of NaN are
-///     preserved over arithmetic operations,
-///     so there may be some surprising results upon inspecting the bit patterns,
+///     preserved over arithmetic operations, and they are not guaranteed to be
+///     portable or even fully deterministic! This means that there may be some
+///     surprising results upon inspecting the bit patterns,
 ///     as the same calculations might produce NaNs with different bit patterns.
 ///
 /// For more information on floating point numbers, see [Wikipedia][wikipedia].

From f535aed977d7410be491aa284628b7b91222fad1 Mon Sep 17 00:00:00 2001
From: Pyry Kontio <pyry.kontio@drasa.eu>
Date: Mon, 2 May 2022 23:29:02 +0900
Subject: [PATCH 8/8] Fix nits

---
 core/src/num/f32.rs | 8 ++++----
 core/src/num/f64.rs | 8 ++++----
 std/src/f32.rs      | 2 +-
 std/src/f64.rs      | 2 +-
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/core/src/num/f32.rs b/core/src/num/f32.rs
index e3d40b58a..74d337f1d 100644
--- a/core/src/num/f32.rs
+++ b/core/src/num/f32.rs
@@ -747,8 +747,8 @@ impl f32 {
     /// 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 mean that the bitpattern of a NaN operand
-    /// is necessarily conserved; see [explanation of NaN as a special value](f32) for more info.
+    /// 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]
@@ -782,8 +782,8 @@ impl f32 {
     /// 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 mean that the bitpattern of a NaN operand
-    /// is necessarily conserved; see [explanation of NaN as a special value](f32) for more info.
+    /// 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]
diff --git a/core/src/num/f64.rs b/core/src/num/f64.rs
index 51ccf7e85..c8ce6f0e3 100644
--- a/core/src/num/f64.rs
+++ b/core/src/num/f64.rs
@@ -763,8 +763,8 @@ impl f64 {
     /// 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 mean that the bitpattern of a NaN operand
-    /// is necessarily conserved; see [explanation of NaN as a special value](f32) for more info.
+    /// 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]
@@ -798,8 +798,8 @@ impl f64 {
     /// 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 mean that the bitpattern of a NaN operand
-    /// is necessarily conserved; see [explanation of NaN as a special value](f32) for more info.
+    /// 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]
diff --git a/std/src/f32.rs b/std/src/f32.rs
index 469db1b7c..4cf234a52 100644
--- a/std/src/f32.rs
+++ b/std/src/f32.rs
@@ -302,7 +302,7 @@ impl f32 {
     /// Raises a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`.
-    /// It might have different sequence of rounding operations than `powf`,
+    /// It might have a different sequence of rounding operations than `powf`,
     /// so the results are not guaranteed to agree.
     ///
     /// # Examples
diff --git a/std/src/f64.rs b/std/src/f64.rs
index a291a777e..d28bd386c 100644
--- a/std/src/f64.rs
+++ b/std/src/f64.rs
@@ -302,7 +302,7 @@ impl f64 {
     /// Raises a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`.
-    /// It might have different sequence of rounding operations than `powf`,
+    /// It might have a different sequence of rounding operations than `powf`,
     /// so the results are not guaranteed to agree.
     ///
     /// # Examples