Optimize sum of Durations by using custom function

This commit is contained in:
Pazzaz 2018-06-16 20:19:19 +02:00
parent 253205658e
commit d22ad76ca8
2 changed files with 46 additions and 2 deletions

View File

@ -161,6 +161,20 @@ fn checked_div() {
assert_eq!(Duration::new(2, 0).checked_div(0), None);
}
#[test]
fn correct_sum() {
let durations = [
Duration::new(1, 999_999_999),
Duration::new(2, 999_999_999),
Duration::new(0, 999_999_999),
Duration::new(0, 999_999_999),
Duration::new(0, 999_999_999),
Duration::new(5, 0),
];
let sum = durations.iter().sum::<Duration>();
assert_eq!(sum, Duration::new(1+2+5+4, 1_000_000_000 - 5));
}
#[test]
fn debug_formatting_extreme_values() {
assert_eq!(

View File

@ -524,17 +524,47 @@ impl DivAssign<u32> for Duration {
}
}
macro_rules! sum_durations {
($iter:expr) => {{
let mut total_secs: u64 = 0;
let mut total_nanos: u64 = 0;
for entry in $iter {
total_secs = total_secs
.checked_add(entry.secs)
.expect("overflow in iter::sum over durations");
total_nanos = match total_nanos.checked_add(entry.nanos as u64) {
Some(n) => n,
None => {
total_secs = total_secs
.checked_add(total_nanos / NANOS_PER_SEC as u64)
.expect("overflow in iter::sum over durations");
(total_nanos % NANOS_PER_SEC as u64) + entry.nanos as u64
}
};
}
total_secs = total_secs
.checked_add(total_nanos / NANOS_PER_SEC as u64)
.expect("overflow in iter::sum over durations");
total_nanos = total_nanos % NANOS_PER_SEC as u64;
Duration {
secs: total_secs,
nanos: total_nanos as u32,
}
}};
}
#[stable(feature = "duration_sum", since = "1.16.0")]
impl Sum for Duration {
fn sum<I: Iterator<Item=Duration>>(iter: I) -> Duration {
iter.fold(Duration::new(0, 0), |a, b| a + b)
sum_durations!(iter)
}
}
#[stable(feature = "duration_sum", since = "1.16.0")]
impl<'a> Sum<&'a Duration> for Duration {
fn sum<I: Iterator<Item=&'a Duration>>(iter: I) -> Duration {
iter.fold(Duration::new(0, 0), |a, b| a + *b)
sum_durations!(iter)
}
}