From c24fb126e7cdd73163af67c264bf626aebbeee84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Sun, 29 Jul 2018 07:00:13 +0300 Subject: [PATCH] duration div mul extras --- src/libcore/time.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++ src/libstd/time.rs | 26 ++++++++++ 2 files changed, 141 insertions(+) diff --git a/src/libcore/time.rs b/src/libcore/time.rs index 54973b7b7783..fcd2726b84de 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -24,6 +24,7 @@ use fmt; use iter::Sum; use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; +use {u64, u128}; const NANOS_PER_SEC: u32 = 1_000_000_000; const NANOS_PER_MILLI: u32 = 1_000_000; @@ -501,6 +502,67 @@ impl Mul for Duration { } } +#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] +impl Mul 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 for Duration { + type Output = Duration; + + 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)); + if !nanos_f64.is_finite() { + panic!("got non-finite value when multiplying duration by float"); + } + if nanos_f64 > (u128::MAX as f64) { + panic!("overflow when multiplying duration by float"); + }; + let nanos_u128 = nanos_f64 as u128; + let secs = nanos_u128 / (NANOS_PER_SEC as u128); + let nanos = nanos_u128 % (NANOS_PER_SEC as u128); + if secs > (u64::MAX as u128) { + panic!("overflow when multiplying duration by float"); + } + Duration { + secs: secs as u64, + nanos: nanos as u32, + } + } +} + +#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] +impl Mul for f64 { + type Output = Duration; + + fn mul(self, rhs: Duration) -> Duration { + const NPS: f64 = NANOS_PER_SEC as f64; + 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 > (u128::MAX as f64) { + panic!("overflow when multiplying float by duration"); + }; + let nanos_u128 = nanos_f64 as u128; + let secs = nanos_u128 / (NANOS_PER_SEC as u128); + let nanos = nanos_u128 % (NANOS_PER_SEC as u128); + if secs > (u64::MAX as u128) { + panic!("overflow when multiplying float by duration"); + } + Duration { + secs: secs as u64, + nanos: nanos as u32, + } + } +} + #[stable(feature = "time_augmented_assignment", since = "1.9.0")] impl MulAssign for Duration { fn mul_assign(&mut self, rhs: u32) { @@ -508,6 +570,13 @@ impl MulAssign for Duration { } } +#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] +impl MulAssign for Duration { + fn mul_assign(&mut self, rhs: f64) { + *self = *self * rhs; + } +} + #[stable(feature = "duration", since = "1.3.0")] impl Div for Duration { type Output = Duration; @@ -517,6 +586,44 @@ impl Div for Duration { } } +#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] +impl Div for Duration { + type Output = Duration; + + fn div(self, rhs: f64) -> Duration { + const NPS: f64 = NANOS_PER_SEC as f64; + 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 > (u128::MAX as f64) { + panic!("overflow when dividing duration by float"); + }; + let nanos_u128 = nanos_f64 as u128; + let secs = nanos_u128 / (NANOS_PER_SEC as u128); + let nanos = nanos_u128 % (NANOS_PER_SEC as u128); + if secs > (u64::MAX as u128) { + panic!("overflow when dividing duration by float"); + } + Duration { + secs: secs as u64, + nanos: nanos as u32, + } + } +} + +#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] +impl Div 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 for Duration { fn div_assign(&mut self, rhs: u32) { @@ -524,6 +631,14 @@ impl DivAssign for Duration { } } +#[stable(feature = "duration_mul_div_extras", since = "1.29.0")] +impl DivAssign for Duration { + fn div_assign(&mut self, rhs: f64) { + *self = *self / rhs; + } +} + + macro_rules! sum_durations { ($iter:expr) => {{ let mut total_secs: u64 = 0; diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 90ab34915991..640902426cdd 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -590,4 +590,30 @@ mod tests { let hundred_twenty_years = thirty_years * 4; assert!(a < hundred_twenty_years); } + + #[test] + fn duration_float_ops() { + let dur = Duration::new(2, 700_000_000); + + let dur2 = 3.14*dur; + assert_eq!(dur2, dur*3.14); + assert_eq!(dur2.as_secs(), 8); + assert_eq!(dur2.subsec_nanos(), 478_000_000); + + let dur3 = 3.14e5*dur; + assert_eq!(dur3, dur*3.14e5); + assert_eq!(dur3.as_secs(), 847_800); + assert_eq!(dur3.subsec_nanos(), 0); + + let dur4 = dur/3.14; + assert_eq!(dur4.as_secs(), 0); + assert_eq!(dur4.subsec_nanos(), 859_872_611); + + let dur5 = dur/3.14e5; + assert_eq!(dur5.as_secs(), 0); + // we are using truncation and not rounding + assert_eq!(dur5.subsec_nanos(), 8598); + + assert_eq!(dur/Duration::new(5, 400_000_000), 0.5); + } }