Skip to content

Commit

Permalink
duration div mul extras
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov committed Jul 29, 2018
1 parent c7cba3d commit c24fb12
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
115 changes: 115 additions & 0 deletions src/libcore/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -501,13 +502,81 @@ 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) {
*self = *self * rhs;
}
}

#[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;
Expand All @@ -517,13 +586,59 @@ 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) {
*self = *self / rhs;
}
}

#[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;
Expand Down
26 changes: 26 additions & 0 deletions src/libstd/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

0 comments on commit c24fb12

Please sign in to comment.