]> git.lizzy.rs Git - rust.git/blobdiff - src/libcore/time.rs
Move float ops to unstable inherent methods
[rust.git] / src / libcore / time.rs
index 25721b7fcecbb8f93a317df1f99ddf4dcb4548ba..64cb13c7eae75f7477e81a3309284e7bca676fd1 100644 (file)
@@ -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_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.
@@ -208,7 +209,7 @@ pub const fn from_nanos(nanos: u64) -> Duration {
     #[inline]
     pub const fn as_secs(&self) -> u64 { self.secs }
 
-    /// Returns the fractional part of this `Duration`, in milliseconds.
+    /// Returns the fractional part of this `Duration`, in whole milliseconds.
     ///
     /// This method does **not** return the length of the duration when
     /// represented by milliseconds. The returned number always represents a
@@ -228,7 +229,7 @@ pub const fn as_secs(&self) -> u64 { self.secs }
     #[inline]
     pub const fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
 
-    /// Returns the fractional part of this `Duration`, in microseconds.
+    /// Returns the fractional part of this `Duration`, in whole microseconds.
     ///
     /// This method does **not** return the length of the duration when
     /// represented by microseconds. The returned number always represents a
@@ -268,7 +269,7 @@ pub const fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
     #[inline]
     pub const fn subsec_nanos(&self) -> u32 { self.nanos }
 
-    /// Returns the total number of milliseconds contained by this `Duration`.
+    /// Returns the total number of whole milliseconds contained by this `Duration`.
     ///
     /// # Examples
     ///
@@ -285,7 +286,7 @@ pub fn as_millis(&self) -> u128 {
         self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128
     }
 
-    /// Returns the total number of microseconds contained by this `Duration`.
+    /// Returns the total number of whole microseconds contained by this `Duration`.
     ///
     /// # Examples
     ///
@@ -458,6 +459,88 @@ pub fn checked_div(self, rhs: u32) -> Option<Duration> {
             None
         }
     }
+
+    /// Multiply `Duration` by `f64`.
+    ///
+    /// # Examples
+    /// ```
+    /// let dur = Duration::new(2, 700_000_000);
+    /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
+    /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
+    /// ```
+    #[unstable(feature = "duration_float_ops",
+               reason = "duration/floats operations are unstabe",
+               issue = "0")]
+    #[inline]
+    pub fn mul_f64(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 > MAX_NANOS_F64 {
+            panic!("overflow when multiplying duration by float");
+        }
+        if nanos_f64 < 0.0 {
+            panic!("underflow 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,
+        }
+    }
+
+    /// Divide `Duration` by `f64`.
+    ///
+    /// # Examples
+    /// ```
+    /// let dur = Duration::new(2, 700_000_000);
+    /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
+    /// // note that truncation is used, not rounding
+    /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598));
+    /// ```
+    #[unstable(feature = "duration_float_ops",
+               reason = "duration/floats operations are unstabe",
+               issue = "0")]
+    #[inline]
+    pub fn div_f64(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 > MAX_NANOS_F64 {
+            panic!("overflow when dividing duration by float");
+        }
+        if nanos_f64 < 0.0 {
+            panic!("underflow 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,
+        }
+    }
+
+    /// Divide `Duration` by `Duration` and return `f64`.
+    ///
+    /// # Examples
+    /// ```
+    /// let dur1 = Duration::new(2, 700_000_000);
+    /// let dur2 = Duration::new(5, 400_000_000);
+    /// assert_eq!(dur1.div_duration(dur2), 0.5);
+    /// ```
+    #[unstable(feature = "duration_float_ops",
+               reason = "duration/floats operations are unstabe",
+               issue = "0")]
+    #[inline]
+    pub fn div_duration(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 = "duration", since = "1.3.0")]
@@ -501,6 +584,15 @@ fn mul(self, rhs: u32) -> Duration {
     }
 }
 
+#[stable(feature = "symmetric_u32_duration_mul", since = "1.30.0")]
+impl Mul<Duration> for u32 {
+    type Output = Duration;
+
+    fn mul(self, rhs: Duration) -> Duration {
+        rhs * self
+    }
+}
+
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 impl MulAssign<u32> for Duration {
     fn mul_assign(&mut self, rhs: u32) {
@@ -524,6 +616,7 @@ fn div_assign(&mut self, rhs: u32) {
     }
 }
 
+
 macro_rules! sum_durations {
     ($iter:expr) => {{
         let mut total_secs: u64 = 0;