about summary refs log tree commit diff
diff options
context:
space:
mode:
authorАртём Павлов [Artyom Pavlov] <newpavlov@gmail.com>2018-07-29 07:00:13 +0300
committerАртём Павлов [Artyom Pavlov] <newpavlov@gmail.com>2018-07-29 07:00:13 +0300
commitc24fb126e7cdd73163af67c264bf626aebbeee84 (patch)
treef1fb9b0e439db9cc118cb8952b3d19b74c19243c
parentc7cba3d33f564be140275c4fb9e33c6dc2c97b21 (diff)
downloadrust-c24fb126e7cdd73163af67c264bf626aebbeee84.tar.gz
rust-c24fb126e7cdd73163af67c264bf626aebbeee84.zip
duration div mul extras
-rw-r--r--src/libcore/time.rs115
-rw-r--r--src/libstd/time.rs26
2 files changed, 141 insertions, 0 deletions
diff --git a/src/libcore/time.rs b/src/libcore/time.rs
index 54973b7b778..fcd2726b84d 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<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;
+        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<Duration> 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<u32> for Duration {
     fn mul_assign(&mut self, rhs: u32) {
@@ -508,6 +570,13 @@ impl MulAssign<u32> for Duration {
     }
 }
 
+#[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,6 +586,44 @@ 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;
+        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<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) {
@@ -524,6 +631,14 @@ impl DivAssign<u32> for Duration {
     }
 }
 
+#[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;
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index 90ab3491599..640902426cd 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);
+    }
 }