I think there are currently two problems with floats:
-
they are required in libcore, so targets that either can't support them (e.g. the backend does not support them at all and errors on use) or don't want to use them (e.g. a kernel module), end up having a not so great experience
-
part of the methods of these types are implemented in libcore (e.g. f32::add) while part of the methods are implemented in libstd (e.g. f32::sin). This isn't only 100% magic, but it also means that
#![no_std]
crates cannot use math functions likef32::sin
even when they are actually linked to the binary, because these methods are not available (we have a pure rustlibm
in rust-lang/libm).
Does someone else think that this is a problem worth solving ? And if so, has anyone already invested time thinking about solutions ?
Since we can't break any code, we could start by making f32
/f64
optional in libcore, e.g., behind a #[cfg(target_has_float = "f32")]
cfg feature, that would need to be defined to true for all targets that do actually support floats (most targets). This would allow a kernel module to, e.g., fabricate a slightly different target specification that disables floats, while for embedded targets that can't support them, these just wouldn't be there at all.
Then I'd suggest moving the math functions to a library on top of libcore, e.g., libfloat
, which lives in parallel to liballoc
in the hierarchy. This crate would be in charge of linking libm
and implementing the float methods (still 100% magically because the types are defined in libcore..). This will allow #[no_std]
users to pull libfloat
just like how they pull liballoc
today.
Ideally, libfloat
would, at some point, be configurable, allowing users not only to link the system's math library, but to override it with another math library if they want to (e.g. if you wanted to use sleef as your math library, you could rebuild your target by enabling some libfloat cargo feature). I've wanted to use a different math library a couple of times already, and depending on how your system libm looks like, it might go from just a simple LD_PRELOAD to having to fully replace the whole libc.
If we ever add portable simd support for libcore, we'd need to add support for libmvec
or similar as well to support, e.g., f32x4::sin
and friends. I don't know what would be the best way to do that. I think that ideally, libcore just would not have any floats at all, and if you want to use f32 you'd need to use libfloat, but I guess its too late for that. For packed vectors, we could just provide the float vectors in a libfloatvec
crate, so that they are opt-in from the start.