@@ -1190,6 +1190,11 @@ mod prim_f16 {}
1190
1190
/// portable or even fully deterministic! This means that there may be some
1191
1191
/// surprising results upon inspecting the bit patterns,
1192
1192
/// 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.
1193
1198
///
1194
1199
/// When a primitive operation (addition, subtraction, multiplication, or
1195
1200
/// division) is performed on this type, the result is rounded according to the
@@ -1211,6 +1216,79 @@ mod prim_f16 {}
1211
1216
/// *[See also the `std::f32::consts` module](crate::f32::consts).*
1212
1217
///
1213
1218
/// [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
+
1214
1292
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1215
1293
mod prim_f32 { }
1216
1294
0 commit comments