Description
Currently, libm
's 32-bit floating-point math functions (e.g., sinf
, cosf
, etc.) are ports to Rust of musl implementations. This means that many of these 32-bit functions (e.g., sinf
) use f64
intermediate values (presumably to avoid accumulating intermediate rounding errors). This works well on CPUs with double-precision FPUs, but makes these functions unusable on many embedded systems with only single-precision floating-point support. There have been a number of issues raised/PRs submitted for newlib implementations (see "Related issues/PRs" section at the end of this post), which use pure 32-bit implementations. But, as far as I'm aware none of these PRs have made it into the libm
source code. It seems like a few questions need to be addressed before implementing pure 32-bit math functions:
- Does
libm
want pure 32-bit implementations? - If so, what implementations should be used/ported? newlib/something else/custom?
- What is the best way to incorporate these functions into
libm
? - Can these 32-bit implementations be added progressively?
As I see it, the tradeoff between using 32-bit FP or 64-bit FP intermediate values for 32-bit functions is that 64-bit implementations give better precision with equivalent performance in many non-embedded environments. The benefit of 32-bit implementations (as already stated) is that they are usable on platforms with only single-precision floating-point support. Any other important considerations?
There are a number of options here:
- Keep the 64-bit implementations.
- Replace the 64-bit implementations of 32-bit math functions with pure 32-bit implementations.
- Add 32-bit implementations to supplement the existing 64-bit implementations.
Although option 3 accommodates the greatest number of use cases, it would require 2 implementations of 32-bit math functions, which is confusing to users and more work to maintain. Therefore, it is probably the least desirable option. Option 2 seems to be the best in my mind. This would make libm
applicable to a broader range of embedded devices. Additionally, many applications that benefit from the 64-bit implementations are already served by std
, or can use the f64
implementations. Are there any major use cases that would be neglected by transitioning to pure 32-bit implementations?