Skip to content

Commit e6c5601

Browse files
cuviperkpreid
andauthored
Don't call "NaN boxing" an optimization
Co-authored-by: Kevin Reid <[email protected]>
1 parent c4b85e3 commit e6c5601

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

posts/2024-10-17-Rust-1.82.0.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ To avoid interfering with crates that wish to support several Rust versions, `ma
8989

9090
Operations on floating-point values (of type `f32` and `f64`) are famously subtle. One of the reasons for this is the existence of "NaN values": this is short for "Not a Number", and is used to represent e.g. the result of `0.0 / 0.0`. What makes NaN values subtle is that more than one possible NaN value exists: a NaN value has a sign that can be checked with `f.is_sign_positive()`, and it has a "payload" that can be extracted with `f.to_bits()`. Despite very successful efforts to standardize the behavior of floating-point operations across hardware architectures, the details of when a NaN is positive or negative and what its exact payload is differ across architectures. To make matters even more complicated, Rust and its LLVM backend apply optimizations to floating-point operations when the exact numeric result is guaranteed not to change, but those optimizations can change which NaN value is produced. For instance, `f * 1.0` may be optimized to just `f`. However, if `f` is a NaN, this can change the exact bit pattern of the result!
9191

92-
With this release, Rust standardizes on a set of rules for how NaN values behave. This set of rules is *not* fully deterministic, which means that the result of operations like `(0.0 / 0.0).is_sign_positive()` can differ depending on the hardware architecture, optimization levels, and the surrounding code. Code that aims to be fully portable should avoid using `to_bits` and should use `f.signum() == 1.0` instead of `f.is_sign_positive()`. However, the rules are carefully chosen to still allow advanced optimization techniques such as NaN boxing to be realized in Rust code. For more details on what the exact rules are, check out our [documentation](https://doc.rust-lang.org/std/primitive.f32.html#nan-bit-patterns).
92+
With this release, Rust standardizes on a set of rules for how NaN values behave. This set of rules is *not* fully deterministic, which means that the result of operations like `(0.0 / 0.0).is_sign_positive()` can differ depending on the hardware architecture, optimization levels, and the surrounding code. Code that aims to be fully portable should avoid using `to_bits` and should use `f.signum() == 1.0` instead of `f.is_sign_positive()`. However, the rules are carefully chosen to still allow advanced data representation techniques such as NaN boxing to be implemented in Rust code. For more details on what the exact rules are, check out our [documentation](https://doc.rust-lang.org/std/primitive.f32.html#nan-bit-patterns).
9393

9494
With the semantics for NaN values settled, this release also permits the use of floating-point operations in `const fn`. Due to the reasons described above, operations like `(0.0 / 0.0).is_sign_positive()` can produce a different result when executed at compile-time vs at run-time; this is not a bug and code must not rely on a `const fn` always producing the exact same result.
9595

0 commit comments

Comments
 (0)