-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Duration div mul extras #52813
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
Changes from 3 commits
c24fb12
12d8f27
3e07236
2c300fa
2cab0de
d48a649
0673417
36dff2a
206ca68
07c15ea
c5cbea6
533c0f0
c11281f
37972ae
8a0aa9f
9e78cb2
2aca697
fd7565b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,7 @@ | |
//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5)); | ||
//! ``` | ||
|
||
use fmt; | ||
use {fmt, u64}; | ||
use iter::Sum; | ||
use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; | ||
|
||
|
@@ -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)*(NANOS_PER_SEC as u128)) as f64; | ||
|
||
/// A `Duration` type to represent a span of time, typically used for system | ||
/// timeouts. | ||
|
@@ -501,13 +502,77 @@ impl Mul<u32> for Duration { | |
} | ||
} | ||
|
||
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] | ||
impl Mul<Duration> for u32 { | ||
type Output = Duration; | ||
|
||
fn mul(self, rhs: Duration) -> Duration { | ||
rhs.checked_mul(self).expect("overflow when multiplying scalar by duration") | ||
} | ||
} | ||
|
||
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] | ||
impl Mul<f64> for Duration { | ||
type Output = Duration; | ||
|
||
fn mul(self, rhs: f64) -> Duration { | ||
const NPS: f64 = NANOS_PER_SEC as f64; | ||
if rhs.is_sign_negative() { | ||
panic!("duration can not be multiplied by negative float"); | ||
} | ||
let nanos_f64 = rhs * (NPS * (self.secs as f64) + (self.nanos as f64)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider panicking when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. |
||
if !nanos_f64.is_finite() { | ||
panic!("got non-finite value when multiplying duration by float"); | ||
} | ||
if nanos_f64 > MAX_NANOS_F64 { | ||
panic!("overflow when multiplying duration by float"); | ||
}; | ||
let nanos_u128 = nanos_f64 as u128; | ||
Duration { | ||
secs: (nanos_u128 / (NANOS_PER_SEC as u128)) as u64, | ||
nanos: (nanos_u128 % (NANOS_PER_SEC as u128)) as u32, | ||
} | ||
} | ||
} | ||
|
||
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] | ||
impl Mul<Duration> for f64 { | ||
type Output = Duration; | ||
|
||
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"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
} | ||
let nanos_f64 = self * (NPS * (rhs.secs as f64) + (rhs.nanos as f64)); | ||
if !nanos_f64.is_finite() { | ||
panic!("got non-finite value when multiplying float by duration"); | ||
} | ||
if nanos_f64 > MAX_NANOS_F64 { | ||
panic!("overflow when multiplying float by duration"); | ||
}; | ||
let nanos_u128 = nanos_f64 as u128; | ||
Duration { | ||
secs: (nanos_u128 / (NANOS_PER_SEC as u128)) as u64, | ||
nanos: (nanos_u128 % (NANOS_PER_SEC as u128)) as u32, | ||
} | ||
} | ||
} | ||
|
||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] | ||
impl MulAssign<u32> for Duration { | ||
fn mul_assign(&mut self, rhs: u32) { | ||
*self = *self * rhs; | ||
} | ||
} | ||
|
||
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] | ||
impl MulAssign<f64> for Duration { | ||
fn mul_assign(&mut self, rhs: f64) { | ||
*self = *self * rhs; | ||
} | ||
} | ||
|
||
#[stable(feature = "duration", since = "1.3.0")] | ||
impl Div<u32> for Duration { | ||
type Output = Duration; | ||
|
@@ -517,13 +582,57 @@ impl Div<u32> for Duration { | |
} | ||
} | ||
|
||
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] | ||
impl Div<f64> for Duration { | ||
type Output = Duration; | ||
|
||
fn div(self, rhs: f64) -> Duration { | ||
const NPS: f64 = NANOS_PER_SEC as f64; | ||
if rhs.is_sign_negative() { | ||
panic!("duration can not be divided by negative float"); | ||
} | ||
let nanos_f64 = (NPS * (self.secs as f64) + (self.nanos as f64)) / rhs; | ||
if !nanos_f64.is_finite() { | ||
panic!("got non-finite value when dividing duration by float"); | ||
} | ||
if nanos_f64 > MAX_NANOS_F64 { | ||
panic!("overflow when dividing duration by float"); | ||
}; | ||
let nanos_u128 = nanos_f64 as u128; | ||
Duration { | ||
secs: (nanos_u128 / (NANOS_PER_SEC as u128)) as u64, | ||
nanos: (nanos_u128 % (NANOS_PER_SEC as u128)) as u32, | ||
} | ||
} | ||
} | ||
|
||
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] | ||
impl Div<Duration> for Duration { | ||
type Output = f64; | ||
|
||
fn div(self, rhs: Duration) -> f64 { | ||
const NPS: f64 = NANOS_PER_SEC as f64; | ||
let nanos1 = NPS * (self.secs as f64) + (self.nanos as f64); | ||
let nanos2 = NPS * (rhs.secs as f64) + (rhs.nanos as f64); | ||
nanos1/nanos2 | ||
} | ||
} | ||
|
||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] | ||
impl DivAssign<u32> for Duration { | ||
fn div_assign(&mut self, rhs: u32) { | ||
*self = *self / rhs; | ||
} | ||
} | ||
|
||
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] | ||
impl DivAssign<f64> for Duration { | ||
fn div_assign(&mut self, rhs: f64) { | ||
*self = *self / rhs; | ||
} | ||
} | ||
|
||
|
||
macro_rules! sum_durations { | ||
($iter:expr) => {{ | ||
let mut total_secs: u64 = 0; | ||
|
There was a problem hiding this comment.
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?There was a problem hiding this comment.
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"
There was a problem hiding this comment.
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 torhs * self
.