Skip to content

Use f128 internally for Duration-float methods#154107

Closed
cuviper wants to merge 4 commits intorust-lang:mainfrom
cuviper:duration-f128
Closed

Use f128 internally for Duration-float methods#154107
cuviper wants to merge 4 commits intorust-lang:mainfrom
cuviper:duration-f128

Conversation

@cuviper
Copy link
Copy Markdown
Member

@cuviper cuviper commented Mar 19, 2026

If we want to keep as much Duration precision as possible when
multiplying or dividing by a float, then we shouldn't convert it to
f32 nor f64 to match the operand, because their mantissas aren't
large enough to hold a full Duration. However, f128 is large enough
with MANTISSA_DIGITS = 113, since Duration::MAX only needs 94 bits.

Fixes #149794, as an alternative to #150933.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 19, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 19, 2026

r? @scottmcm

rustbot has assigned @scottmcm.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @scottmcm, libs
  • @scottmcm, libs expanded to 8 candidates
  • Random selection from Mark-Simulacrum, joboet, scottmcm

@tgross35
Copy link
Copy Markdown
Contributor

I think this is a good solution but we can't actually do this unconditionally now, f128 use still needs to be gated behind cfg(target_has_reliable_f128) due to some bugginess across the backends (and across LLVM versions)

@tgross35
Copy link
Copy Markdown
Contributor

More specific list of that:

cfg.has_reliable_f128 = match (target_arch, target_os) {
// Unsupported https://github.com/llvm/llvm-project/issues/121122
(Arch::AmdGpu, _) => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
(Arch::Arm64EC, _) => false,
// Selection bug <https://github.com/llvm/llvm-project/issues/95471>. This issue is closed
// but basic math still does not work.
(Arch::Nvptx64, _) => false,
// ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
// list at <https://github.com/rust-lang/rust/issues/116909>)
(Arch::PowerPC | Arch::PowerPC64, _) => false,
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
(Arch::Sparc, _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
(Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != Abi::Llvm => false,
// There are no known problems on other platforms, so the only requirement is that symbols
// are available. `compiler-builtins` provides all symbols required for core `f128`
// support, so this should work for everything else.
_ => true,
};

@cuviper
Copy link
Copy Markdown
Member Author

cuviper commented Mar 19, 2026

Hmm, conditional implementation would be straightforward, but conditional testing would be quite annoying. I'll wait for feedback whether we actually want this change before I attempt that.

@clarfonthey
Copy link
Copy Markdown
Contributor

Since a software float implementation would effectively be identical to the other PR, it does feel like this might be a better long-term change, but perhaps in the short-term the other PR is better?

As in, leave a FIXME: maybe use f128 when more reliable comment but still go with that method.

@cuviper
Copy link
Copy Markdown
Member Author

cuviper commented Mar 19, 2026

@tgross35 is it possible to use explicit software mul/div from e.g. compiler-builtins on the non-reliable targets?

@tgross35
Copy link
Copy Markdown
Contributor

tgross35 commented Mar 19, 2026

We need LLVM to not crash when it sees a f128 so c-b gates the implementations behind #[cfg(target_has_reliable_f128)]. In theory we could expose the same algorithms using i128 in the signature reasonably easy, but I don't know that it's worth the effort for something that should be short term.

Could we stomach some platform differences for now and use f128 where it is well-supported?

Comment thread library/core/src/time.rs Outdated
@scottmcm
Copy link
Copy Markdown
Member

To match #150933,
r? tgross35

@rustbot rustbot assigned tgross35 and unassigned scottmcm Mar 20, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 20, 2026

tgross35 is currently at their maximum review capacity.
They may take a while to respond.

@cuviper
Copy link
Copy Markdown
Member Author

cuviper commented Mar 21, 2026

I added conditions for target_has_reliable_f128, including tests. It works for me on x86_64-unknown-linux-gnu using f128, and on x86_64-pc-windows-gnu (via Wine) using the fallback.

cuviper added 4 commits April 7, 2026 12:21
If we want to keep as much `Duration` precision as possible when
multiplying or dividing by a float, then we shouldn't convert it to
`f32` nor `f64` to match the operand, because their mantissas aren't
large enough to hold a full `Duration`. However, `f128` is large enough
with `MANTISSA_DIGITS = 113`, since `Duration::MAX` only needs 94 bits.
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 7, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@tgross35
Copy link
Copy Markdown
Contributor

tgross35 commented Apr 7, 2026

Sorry if you're waiting on me here, did you maybe want to nominate for libs?

@cuviper
Copy link
Copy Markdown
Member Author

cuviper commented Apr 7, 2026

Sure -- I guess the discussion topic is, do we want to preserve Duration precision in its floating-point methods? And if so, is it ok to only bother when we have reliable f128 support? (avoiding the complexity of #150933)

@rustbot label I-libs-nominated

@rustbot rustbot added the I-libs-nominated Nominated for discussion during a libs team meeting. label Apr 7, 2026
cuviper added a commit to cuviper/rust that referenced this pull request Apr 10, 2026
A `Duration` is essentially a 94-bit value (64-bit sec and ~30-bit ns),
so there's some inherent loss when converting to floating-point for
`mul_f64` and `div_f64`. We could go to greater lengths to compute these
with more accuracy, like rust-lang#150933 or rust-lang#154107,
but it's not clear that it's worth the effort. The least we can do is
document that some rounding is to be expected, which this commit does
with simple examples that only multiply or divide by `1.0`.

This also changes the `f32` methods to just forward to `f64`, so we keep
more of that duration precision, as the range is otherwise much more
limited there.
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Apr 22, 2026
Document precision considerations of `Duration`-float methods

A `Duration` is essentially a 94-bit value (64-bit sec and ~30-bit ns),
so there's some inherent loss when converting to floating-point for
`mul_f64` and `div_f64`. We could go to greater lengths to compute these
with more accuracy, like rust-lang#150933 or rust-lang#154107,
but it's not clear that it's worth the effort. The least we can do is
document that some rounding is to be expected, which this commit does
with simple examples that only multiply or divide by `1.0`.

This also changes the `f32` methods to just forward to `f64`, so we keep
more of that duration precision, as the range is otherwise much more
limited there.
rust-timer added a commit that referenced this pull request Apr 22, 2026
Rollup merge of #155133 - cuviper:duration_fp_docs, r=the8472

Document precision considerations of `Duration`-float methods

A `Duration` is essentially a 94-bit value (64-bit sec and ~30-bit ns),
so there's some inherent loss when converting to floating-point for
`mul_f64` and `div_f64`. We could go to greater lengths to compute these
with more accuracy, like #150933 or #154107,
but it's not clear that it's worth the effort. The least we can do is
document that some rounding is to be expected, which this commit does
with simple examples that only multiply or divide by `1.0`.

This also changes the `f32` methods to just forward to `f64`, so we keep
more of that duration precision, as the range is otherwise much more
limited there.
@cuviper
Copy link
Copy Markdown
Member Author

cuviper commented Apr 22, 2026

Closed in favor of #155133, which just merged. The code is here if we ever want to revisit this idea.

@cuviper cuviper closed this Apr 22, 2026
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 22, 2026
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 22, 2026

☔ The latest upstream changes (presumably #155655) made this pull request unmergeable. Please resolve the merge conflicts.

github-actions Bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Apr 24, 2026
Document precision considerations of `Duration`-float methods

A `Duration` is essentially a 94-bit value (64-bit sec and ~30-bit ns),
so there's some inherent loss when converting to floating-point for
`mul_f64` and `div_f64`. We could go to greater lengths to compute these
with more accuracy, like rust-lang/rust#150933 or rust-lang/rust#154107,
but it's not clear that it's worth the effort. The least we can do is
document that some rounding is to be expected, which this commit does
with simple examples that only multiply or divide by `1.0`.

This also changes the `f32` methods to just forward to `f64`, so we keep
more of that duration precision, as the range is otherwise much more
limited there.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

I-libs-nominated Nominated for discussion during a libs team meeting. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Loss of precision in Duration::mul_f32 (and mul_f64)

6 participants