@@ -1190,6 +1190,11 @@ mod prim_f16 {}
11901190/// portable or even fully deterministic! This means that there may be some
11911191/// surprising results upon inspecting the bit patterns,
11921192/// as the same calculations might produce NaNs with different bit patterns.
1193+ /// This also affects the sign of the NaN: checking `is_sign_positive` or `is_sign_negative` on
1194+ /// a NaN is the most common way to run into these surprising results.
1195+ /// (Checking `x >= 0.0` or `x <= 0.0` avoids those surprises, but also how negative/positive
1196+ /// zero are treated.)
1197+ /// See the section below for what exactly is guaranteed about the bit pattern of a NaN.
11931198///
11941199/// When a primitive operation (addition, subtraction, multiplication, or
11951200/// division) is performed on this type, the result is rounded according to the
@@ -1211,6 +1216,79 @@ mod prim_f16 {}
12111216/// *[See also the `std::f32::consts` module](crate::f32::consts).*
12121217///
12131218/// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format
1219+ ///
1220+ /// # NaN bit patterns
1221+ ///
1222+ /// This section defines the possible NaN bit patterns returned by non-"bitwise" floating point
1223+ /// operations. The bitwise operations are unary `-`, `abs`, `copysign`; those are guaranteed to
1224+ /// exactly preserve the bit pattern of their input except for possibly changing the sign bit.
1225+ ///
1226+ /// A floating-point NaN value consists of:
1227+ /// - a sign bit
1228+ /// - a quiet/signaling bit
1229+ /// - a payload, which makes up the rest of the significand (i.e., the mantissa) except for the
1230+ /// quiet/signaling bit.
1231+ ///
1232+ /// Rust assumes that the quiet/signaling bit being set to `1` indicates a quiet NaN (QNaN), and a
1233+ /// value of `0` indicates a signaling NaN (SNaN). In the following we will hence just call it the
1234+ /// "quiet bit".
1235+ ///
1236+ /// The following rules apply when a NaN value is returned: the result has a non-deterministic sign.
1237+ /// The quiet bit and payload are non-deterministically chosen from the following set of options:
1238+ ///
1239+ /// - **Preferred NaN**: The quiet bit is set and the payload is all-zero.
1240+ /// - **Quieting NaN propagation**: The quiet bit is set and the payload is copied from any input
1241+ /// operand that is a NaN. If the inputs and outputs do not have the same payload size (i.e., for
1242+ /// `as` casts), then
1243+ /// - If the output is smaller than the input, low-order bits of the payload get dropped.
1244+ /// - If the output is larger than the input, the payload gets filled up with 0s in the low-order
1245+ /// bits.
1246+ /// - **Unchanged NaN propagation**: The quiet bit and payload are copied from any input operand
1247+ /// that is a NaN. If the inputs and outputs do not have the same size (i.e., for `as` casts), the
1248+ /// same rules as for "quieting NaN propagation" apply, with one caveat: if the output is smaller
1249+ /// than the input, droppig the low-order bits may result in a payload of 0; a payload of 0 is not
1250+ /// possible with a signaling NaN (the all-0 significand encodes an infinity) so unchanged NaN
1251+ /// propagation cannot occur with some inputs.
1252+ /// - **Target-specific NaN**: The quiet bit is set and the payload is picked from a target-specific
1253+ /// set of "extra" possible NaN payloads. The set can depend on the input operand values.
1254+ /// See the table below for the concrete NaNs this set contains on various targets.
1255+ ///
1256+ /// In particular, if all input NaNs are quiet (or if there are no input NaNs), then the output NaN
1257+ /// is definitely quiet. Signaling NaN outputs can only occur if they are provided as an input
1258+ /// value. Similarly, if all input NaNs are preferred (or if there are no input NaNs) and the target
1259+ /// does not have any "extra" NaN payloads, then the output NaN is guaranteed to be preferred.
1260+ ///
1261+ /// The non-deterministic choice happens when the operation is executed; i.e., the result of a
1262+ /// NaN-producing floating point operation is a stable bit pattern (looking at these bits multiple
1263+ /// times will yield consistent results), but running the same operation twice with the same inputs
1264+ /// can produce different results.
1265+ ///
1266+ /// These guarantees are neither stronger nor weaker than those of IEEE 754: IEEE 754 guarantees
1267+ /// that an operation never returns a signaling NaN, whereas it is possible for operations like
1268+ /// `SNAN * 1.0` to return a signaling NaN in Rust. Conversely, IEEE 754 makes no statement at all
1269+ /// about which quiet NaN is returned, whereas Rust restricts the set of possible results to the
1270+ /// ones listed above.
1271+ ///
1272+ /// Unless noted otherwise, the same rules also apply to NaNs returned by other library functions
1273+ /// (e.g. `min`, `minimum`, `max`, `maximum`); other aspects of their semantics and which IEEE 754
1274+ /// operation they correspond to are documented with the respective functions.
1275+ ///
1276+ /// When a floating-point operation is executed in `const` context, the same rules apply: no
1277+ /// guarantee is made about which of the NaN bit patterns described above will be returned. The
1278+ /// result does not have to match what happens when executing the same code at runtime, and the
1279+ /// result can vary depending on factors such as compiler version and flags.
1280+ ///
1281+ /// ### Target-specific "extra" NaN values
1282+ // FIXME: Is there a better place to put this?
1283+ ///
1284+ /// | `target_arch` | Extra payloads possible on this platform |
1285+ /// |---------------|---------|
1286+ /// | `x86`, `x86_64`, `arm`, `aarch64`, `riscv32`, `riscv64` | None |
1287+ /// | `sparc`, `sparc64` | The all-one payload |
1288+ /// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.<br> Otherwise: all possible payloads. |
1289+ ///
1290+ /// For targets not in this table, all payloads are possible.
1291+
12141292#[ stable( feature = "rust1" , since = "1.0.0" ) ]
12151293mod prim_f32 { }
12161294
0 commit comments