Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pure 32-bit versions of 32-bit math functions #248

Open
matthuszagh opened this issue Nov 22, 2020 · 6 comments
Open

Pure 32-bit versions of 32-bit math functions #248

matthuszagh opened this issue Nov 22, 2020 · 6 comments

Comments

@matthuszagh
Copy link

matthuszagh commented Nov 22, 2020

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:

  1. Does libm want pure 32-bit implementations?
  2. If so, what implementations should be used/ported? newlib/something else/custom?
  3. What is the best way to incorporate these functions into libm?
  4. 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:

  1. Keep the 64-bit implementations.
  2. Replace the 64-bit implementations of 32-bit math functions with pure 32-bit implementations.
  3. 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?

cc @alexcrichton @japaric

Related issues/PRs (might not be exhaustive)

@Lokathor
Copy link
Contributor

  • We should absolutely have high quality pure 32-bit impls available within rust.
  • They could be "the" impl of each libm function on 32-bit CPUs (or whatever criteria) via cfg, or all the time, without having to start a new crate.
  • As long as the implementation is correct, the origin of the impl doesn't seem important.

So, yeah, option 2 seems best.

@burrbull
Copy link
Contributor

Don't forget that we have target attributes: #[cfg(target_pointer_width = "64")]

@CryZe
Copy link
Contributor

CryZe commented Nov 22, 2020

target_pointer_width tells you nothing about whether f64 is natively supported or not.

@alexcrichton
Copy link
Member

I would personally think that actually having both the 64-bit emulation as well as the 32-bit implementation is a viable option. I would imagine that implementing the 32-bit operation in terms of the 64-bit operation improves code-size if you use both, which might be important for some situations (?).

Additionally I would expected that any 32-bit-specific version would be thoroughly tested, so the maintenance burden doesn't seem like it would be especially high to have two versions (assuming the 32-bit version is a trivial wrapper around the 64-bit version).

The important bit here though I think is the 32-bit-specific CI. I think we'd need a target on CI that verifies that 64-bit things weren't used in the implementation, but I'm not sure how to write that CI myself.

@burrbull
Copy link
Contributor

We can use 64-bit version for 64-bit systems and have cargo option like force-i32 for special use cases.

@nickmertin
Copy link

Has there been any movement on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants