"Raw" hex and binary literals that adhere to IEE 754-2008 for floats

Allowing the use of hex and binary literals that specify all the bits for the float type, at least where the type is known, would be really nice. Look up tables aren't that uncommon to speed up certain things, and while it is possible to do this in a const or static context, even in stable, using

unsafe{ (std/core)::mem:transmute::<integer_type, float_type>(src) }

this get's really horrible if you have to do this in large look up tables, in my case i ran into this while coding a const look up table for f32 cos and sin values at 0.5° steps.

Would making f32::from_bits() and friends const fns solve this for you?

Edit: Turns out that this is already being done.

Remember that https://doc.rust-lang.org/std/primitive.f32.html#method.from_bits exists; you don't need unsafe for this.

But for something like a sin/cos lookup table, why can't you just put the decimal version? 17 significant digits is enough to uniquely specify an f64, and 9 is enough for f32, for non-NANs.

2 Likes

f32::from_bits(), as far as i read, is is just unsafe{ std::mem:transmute::<u32, f32>(src) } under the hood, but simply hasn't moved to stable yet, while transmute has. Essentially I could just do move to nightly right now.

Honestly this an aesthetic/intuitive issue. If the type is specified I feel like i should have the option to not need a function to convert from hex or binary, in the case of sin/cos tables i absolutely could use decimal. I'm only starting to learn rust, and this is coming from a feeling of "The behaviour of the language to not allow me to use fully specified literals in 0b and 0x, just for floats is inconsistent and weird".

It can also be clearer to express some constants in hex, e.g. 0x1p52 is more meaningful than the same number in decimal.

2 Likes

EDIT: this was based on an incorrect assumption.

Given the relatively uncommon usage of hex floats, I think f32::from_bits(...) seems preferable instead of dedicated syntax, as long as it works in const contexts. I'd be hesitant to add dedicated syntax for this unless it gives access to some feature that wouldn't otherwise be possible.

2 Likes

from the perspective of literals in 0x or 0b simply being written using a different numerical base and that using them is possible for all integers the necessity to use f32::from_bits() is dedicated syntax for float literals.

Note that hex integers, though in a different base, are still given in terms of integer semantics and not encoding. In particular, you can't write -128_i8 as 0xff_i8— The compiler will complain that the value you've given is out of range. The underlying encoding of integers can even vary from platform to platform: The byte order could be big- or little-endian, and I'm not even sure that Rust guarantees that they are stored as twos-complement under the hood.

Adding a float literal syntax based not on semantics but on on a specific encoding (IEEE 754) is unprecedented in Rust, and probably needs heavy justification. The floating-point equivalent of current integer hexadecimal support would be something like C's 0x...p... notation, which represents an arbitrary rational number, exactly equivalent to decimal e notation. Unlike from_bits or transmute, this can't be used to produce a denormalized representation— The compiler will still pick the best representation of the given number in the floating-point encoding that it's using.

1 Like

I’m a bit confused by this thread. There are floating point hex literals that actually have precedent (eg. C99) and are repr-independent at least in theory and then there’s “floating point from bit/byte representation literals” which AFAIK are not a thing in any major language and absolutely seem like an extreme niche feature.

2 Likes

The Rust Reference says that they are: Numeric types - The Rust Reference

I didn't realize that hex float literals were not encoding-specific. (In practice, Rust's floats are going to use that encoding, but that doesn't necessarily mean we should force people to translate through it.)

I was confused too. I don't want to write literals like 0x4330000000000000 but I would definitely use 0x1p52 all over the place if I could.

1 Like

FYI, there's an ancient issue for this here: Add support for hexadecimal float literals · Issue #1433 · rust-lang/rust · GitHub

Also, :+1: to this. I've wanted it before, and it seems inconsistent that we can have hex/binary literals for ints but not floats. It can also make translating code from C to Rust more difficult.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.