Skip to content

Commit fb574b2

Browse files
committed
Implement Duration::{mul,div}_u64
Due to inference issues, these unfortunately can't be Mul and Div impls :(
1 parent 346d0d5 commit fb574b2

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

src/libstd/time/duration.rs

+54
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,45 @@ impl Duration {
8686
/// fractional portion of a second (e.g. it is less than one billion).
8787
#[stable(feature = "duration", since = "1.3.0")]
8888
pub fn subsec_nanos(&self) -> u32 { self.nanos }
89+
90+
/// Multiplies this `Duration`.
91+
///
92+
/// This method takes a `u64` in contrast to `Duration`'s `Mul`
93+
/// implementation which takes an `i32`. For technical reasons, this cannot
94+
/// be provided as an additional `Mul` implementation, though that may
95+
/// change in the future in which case this method will be deprecated.
96+
#[unstable(feature = "duration_u64", reason = "newly added", issue = "0")]
97+
pub fn mul_u64(&self, rhs: u64) -> Duration {
98+
// for nanos, treat rhs as (NANOS_PER_SEC * a + b), where b < NANOS_PER_SEC
99+
let a = rhs / NANOS_PER_SEC as u64;
100+
let b = rhs % NANOS_PER_SEC as u64;
101+
let total_nanos = self.nanos as u64 * b; // can't overflow
102+
let nanos = (total_nanos % NANOS_PER_SEC as u64) as u32;
103+
104+
let secs = self.secs
105+
.checked_mul(rhs)
106+
.and_then(|s| s.checked_add(total_nanos / NANOS_PER_SEC as u64))
107+
.and_then(|s| s.checked_add(self.nanos as u64 * a))
108+
.expect("overflow when multiplying duration");
109+
debug_assert!(nanos < NANOS_PER_SEC);
110+
Duration { secs: secs, nanos: nanos }
111+
}
112+
113+
/// Divides this `Duration`.
114+
///
115+
/// This method takes a `u64` in contrast to `Duration`'s `Div`
116+
/// implementation which takes an `i32`. For technical reasons, this cannot
117+
/// be provided as an additional `Div` implementation, though that may
118+
/// change in the future in which case this method will be deprecated.
119+
#[unstable(feature = "duration_u64", reason = "newly added", issue = "0")]
120+
pub fn div_u64(&self, rhs: u64) -> Duration {
121+
let secs = self.secs / rhs;
122+
let carry = self.secs - secs * rhs;
123+
let extra_nanos = carry * (NANOS_PER_SEC as u64) / rhs;
124+
let nanos = (self.nanos as u64 / rhs + extra_nanos) as u32;
125+
debug_assert!(nanos < NANOS_PER_SEC);
126+
Duration { secs: secs, nanos: nanos }
127+
}
89128
}
90129

91130
#[stable(feature = "duration", since = "1.3.0")]
@@ -250,6 +289,14 @@ mod tests {
250289
assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
251290
assert_eq!(Duration::new(0, 500_000_001) * 4000,
252291
Duration::new(2000, 4000));
292+
293+
assert_eq!(Duration::new(0, 1).mul_u64(2), Duration::new(0, 2));
294+
assert_eq!(Duration::new(1, 1).mul_u64(3), Duration::new(3, 3));
295+
assert_eq!(Duration::new(0, 500_000_001).mul_u64(4), Duration::new(2, 4));
296+
assert_eq!(Duration::new(0, 500_000_001).mul_u64(4000),
297+
Duration::new(2000, 4000));
298+
assert_eq!(Duration::new(0, 500_000_000).mul_u64(1 << 63),
299+
Duration::new(1 << 62, 0));
253300
}
254301

255302
#[test]
@@ -258,5 +305,12 @@ mod tests {
258305
assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
259306
assert_eq!(Duration::new(99, 999_999_000) / 100,
260307
Duration::new(0, 999_999_990));
308+
309+
assert_eq!(Duration::new(0, 1).div_u64(2), Duration::new(0, 0));
310+
assert_eq!(Duration::new(1, 1).div_u64(3), Duration::new(0, 333_333_333));
311+
assert_eq!(Duration::new(99, 999_999_000).div_u64(100),
312+
Duration::new(0, 999_999_990));
313+
assert_eq!(Duration::new(1 << 62, 0).div_u64(1 << 63),
314+
Duration::new(0, 500_000_000));
261315
}
262316
}

0 commit comments

Comments
 (0)