-
Notifications
You must be signed in to change notification settings - Fork 422
Description
The following code worked for cross v0.1.14, so any issues were introduced with the latest release.
Targets
- powerpc-unknown-linux-gnu
- powerpc64-unknown-linux-gnu
- powerpc64le-unknown-linux-gnu
Failing Code
pub fn main() {
let f: f32 = 1e-45;
println!("to_bits={:#b}", f.to_bits());
let p = &f as *const f32;
let p = p as *const i32;
unsafe {
println!("transmuted as integer={:#b}", *p);
}
}
Results
to_bits=0b100
transmuted as integer=0b1
The value of f.to_bits()
is 4
, rather than 1
, as expected, since 1e-45
is the smallest denormal 32-bit floating point number. The direct type-pun through a pointer alias gets the correct value of 1
. to_bits directly calls mem::transmute
, which should just pun the bytes to a new type.
Explanation
The binary representation for the IEEE-754 single-precision floating point number 1e-45 is:
0 | 00000000 | 00000000000000000000001
The first group is the sign bit, the second group is the exponent (including the hidden bit), and the third group is the significant digits (mantissa). The endianness of floats should be the same as integers on the architecture. Therefore, f.to_bits()
should return 1
, instead, for some unknown reason, it returns 4
.
Minimal Steps to Reproduce
- Create a repository (
cargo new --bin sample
). - Copy the failing code into
main.rs
. - Run the binary on a PowerPC architecture (
cross run --target powerpc-unknown-linux-gnu
).