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

Duration div mul extras #52813

Merged
merged 18 commits into from
Sep 21, 2018
Merged

Conversation

newpavlov
Copy link
Contributor

@newpavlov newpavlov commented Jul 28, 2018

Successor of #52556.

This PR adds the following impls:

  • impl Mul<Duration> for u32 (to allow 10*SECOND in addition to SECOND*10)
  • impl Mul<f64> for Duration (to allow 2.5*SECOND vs 2*SECOND + 500*MILLISECOND)
  • impl Mul<Duration> for f64
  • impl MulAssign<f64> for Duration
  • impl Div<f64> for Duration
  • impl DivAssign<f64> for Duration
  • impl Div<Duration> for Duration (Output = f64, can be useful e.g. for duration/MINUTE)

f64 is chosen over f32 to minimize rounding errors. (52 bits fraction precision vs Duration's ~94 bit)

@rust-highfive
Copy link
Collaborator

r? @withoutboats

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 28, 2018
@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@kennytm
Copy link
Member

kennytm commented Jul 29, 2018

Could you squash all fixups into a single commit?

@newpavlov
Copy link
Contributor Author

Done.

if !nanos_f64.is_finite() {
panic!("got non-finite value when multiplying duration by float");
}
if nanos_f64 > (u128::MAX as f64) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The upper limit is u64::MAX * NANOS_PER_SEC (1.8 × 1028) which is a much smaller number than u128::MAX (3.4 × 1038). If you check for the former you don't need the second secs > (u64::MAX as u128) below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was conservative about potential edge effects. So you think it will be enough to just check the following condition?

nanos_f64 > ((u64::MAX as u128)*(NANOS_PER_SEC as u128)) as f64

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@newpavlov Yes. But make this a const please.


fn mul(self, rhs: f64) -> Duration {
const NPS: f64 = NANOS_PER_SEC as f64;
let nanos_f64 = rhs * (NPS * (self.secs as f64) + (self.nanos as f64));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider panicking when !(rhs >= 0).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:03:58]    Compiling rustc_lsan v0.0.0 (file:///checkout/src/librustc_lsan)
[00:03:59]    Compiling rustc_asan v0.0.0 (file:///checkout/src/librustc_asan)
[00:04:00]    Compiling rustc_msan v0.0.0 (file:///checkout/src/librustc_msan)
[00:04:01]    Compiling rustc_tsan v0.0.0 (file:///checkout/src/librustc_tsan)
[00:04:02] error[E0599]: no method named `is_sign_negative` found for type `time::Duration` in the current scope
[00:04:02]     |
[00:04:02]     |
[00:04:02] 65  | pub struct Duration {
[00:04:02]     | ------------------- method `is_sign_negative` not found for this
[00:04:02] ...
[00:04:02] 544 |         if rhs.is_sign_negative() {
[00:04:02] 
[00:04:03] error: aborting due to previous error
[00:04:03] 
[00:04:03] For more information about this error, try `rustc --explain E0599`.
---
156608 ./.git/modules/src
149124 ./src/llvm-emscripten/test
145504 ./obj/build/bootstrap/debug/incremental
130636 ./obj/build/bootstrap/debug/incremental/bootstrap-c7ee2tfsizs
130632 ./obj/build/bootstrap/debug/incremental/bootstrap-c7ee2tfsizs/s-f3cg5qdtg9-1vl24hh-11rkeiafedqcr
97532 ./obj/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends
77624 ./.git/modules/src/tools
71508 ./src/llvm/lib
70304 ./obj/build/x86_64-unknown-linux-gnu/native

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@kennytm kennytm added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. relnotes Marks issues that should be documented in the release notes of the next release. labels Jul 29, 2018
fn mul(self, rhs: Duration) -> Duration {
const NPS: f64 = NANOS_PER_SEC as f64;
if self.is_sign_negative() {
panic!("duration can not be multiplied by negative float");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will trigger for a NaN with the sign bit set, which feels like it'd be better reported under non-finite, so maybe just use self < 0 here? Also, multiplying a duration by negative zero seems like it should successfully give a zero duration, not a panic.

type Output = Duration;

fn mul(self, rhs: Duration) -> Duration {
rhs.checked_mul(self).expect("overflow when multiplying scalar by duration")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just use rhs * self to avoid repeating things?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They have different panic messages "multiplying scalar by duration" vs "multiplying duration by scalar"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If having different panic messages is not important, then I'll change it and f64 impl to rhs * self.

@newpavlov
Copy link
Contributor Author

Considering Rust 1.28 release should I change stabilization version to 1.30.0?

@kennytm
Copy link
Member

kennytm commented Aug 3, 2018

@newpavlov Yes.

@@ -30,6 +30,7 @@ const NANOS_PER_MILLI: u32 = 1_000_000;
const NANOS_PER_MICRO: u32 = 1_000;
const MILLIS_PER_SEC: u64 = 1_000;
const MICROS_PER_SEC: u64 = 1_000_000;
const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128) - 1) as f64;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The - 1 here doesn't change the value because f64 doesn't have enough precision so this constant ends up being exactly 1ns greater than the largest possible Duration. Either this constant needs to be changed to the next smallest f64 or the check below needs to be changed to nanos >= MAX_NANOS_F64. from_float_secs(2f64.powi(64)) should trigger an overflow but currently it returns a Duration of 0ns.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, it should've been >=. Fixed.

@alexcrichton
Copy link
Member

@bors: r+

Looks good to me, thanks!

@bors
Copy link
Contributor

bors commented Sep 13, 2018

📌 Commit 2aca697 has been approved by alexcrichton

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 13, 2018
@alexcrichton
Copy link
Member

@bors: r-

er actually, mind filing a tracking issue and filling that in?

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Sep 13, 2018
@newpavlov
Copy link
Contributor Author

Done.

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Sep 19, 2018

📌 Commit fd7565b has been approved by alexcrichton

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 19, 2018
@bors
Copy link
Contributor

bors commented Sep 19, 2018

⌛ Testing commit fd7565b with merge 3c8c357fcf68c8348b3ced62bc0d01b7d68820f7...

@bors
Copy link
Contributor

bors commented Sep 19, 2018

💔 Test failed - status-appveyor

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Sep 19, 2018
@kennytm
Copy link
Member

kennytm commented Sep 20, 2018

@bors retry 3 hour timeout

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 20, 2018
kennytm added a commit to kennytm/rust that referenced this pull request Sep 20, 2018
…r=alexcrichton

Duration div mul extras

Successor of rust-lang#52556.

This PR adds the following `impl`s:
- `impl Mul<Duration> for u32` (to allow `10*SECOND` in addition to `SECOND*10`)
- `impl Mul<f64> for Duration` (to allow `2.5*SECOND` vs `2*SECOND + 500*MILLISECOND`)
- `impl Mul<Duration> for f64`
- `impl MulAssign<f64> for Duration`
- `impl Div<f64> for Duration`
- `impl DivAssign<f64> for Duration`
- `impl Div<Duration> for Duration` (`Output = f64`, can be useful e.g. for `duration/MINUTE`)

`f64` is chosen over `f32` to minimize rounding errors. (52 bits fraction precision vs `Duration`'s ~94 bit)
bors added a commit that referenced this pull request Sep 20, 2018
Rollup of 15 pull requests

Successful merges:

 - #52813 (Duration div mul extras)
 - #53470 (Warn about metadata loader errors)
 - #54233 (Remove LLVM 3.9 workaround.)
 - #54257 (Switch wasm math symbols to their original names)
 - #54258 (Enable fatal warnings for the wasm32 linker)
 - #54266 (Update LLVM to fix "bool" arguments on PPC32)
 - #54290 (Switch linker for aarch64-pc-windows-msvc from LLD to MSVC)
 - #54292 (Suggest array indexing when tuple indexing on an array)
 - #54295 (A few cleanups and minor improvements to rustc/traits)
 - #54298 (miri: correctly compute expected alignment for field)
 - #54333 (Update The Book to latest)
 - #54337 (Remove unneeded clone() from tests in librustdoc)
 - #54346 (rustc: future-proof error reporting for polymorphic constants in types.)
 - #54362 (Pass --batch to gdb)
 - #54367 (Add regression test for thread local static mut borrows)
@bors bors merged commit fd7565b into rust-lang:master Sep 21, 2018
@Centril Centril added this to the 1.31 milestone Apr 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.