Skip to content

Commit c24fb12

Browse files
committed
duration div mul extras
1 parent c7cba3d commit c24fb12

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

src/libcore/time.rs

+115
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use fmt;
2525
use iter::Sum;
2626
use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
27+
use {u64, u128};
2728

2829
const NANOS_PER_SEC: u32 = 1_000_000_000;
2930
const NANOS_PER_MILLI: u32 = 1_000_000;
@@ -501,13 +502,81 @@ impl Mul<u32> for Duration {
501502
}
502503
}
503504

505+
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")]
506+
impl Mul<Duration> for u32 {
507+
type Output = Duration;
508+
509+
fn mul(self, rhs: Duration) -> Duration {
510+
rhs.checked_mul(self).expect("overflow when multiplying scalar by duration")
511+
}
512+
}
513+
514+
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")]
515+
impl Mul<f64> for Duration {
516+
type Output = Duration;
517+
518+
fn mul(self, rhs: f64) -> Duration {
519+
const NPS: f64 = NANOS_PER_SEC as f64;
520+
let nanos_f64 = rhs * (NPS * (self.secs as f64) + (self.nanos as f64));
521+
if !nanos_f64.is_finite() {
522+
panic!("got non-finite value when multiplying duration by float");
523+
}
524+
if nanos_f64 > (u128::MAX as f64) {
525+
panic!("overflow when multiplying duration by float");
526+
};
527+
let nanos_u128 = nanos_f64 as u128;
528+
let secs = nanos_u128 / (NANOS_PER_SEC as u128);
529+
let nanos = nanos_u128 % (NANOS_PER_SEC as u128);
530+
if secs > (u64::MAX as u128) {
531+
panic!("overflow when multiplying duration by float");
532+
}
533+
Duration {
534+
secs: secs as u64,
535+
nanos: nanos as u32,
536+
}
537+
}
538+
}
539+
540+
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")]
541+
impl Mul<Duration> for f64 {
542+
type Output = Duration;
543+
544+
fn mul(self, rhs: Duration) -> Duration {
545+
const NPS: f64 = NANOS_PER_SEC as f64;
546+
let nanos_f64 = self * (NPS * (rhs.secs as f64) + (rhs.nanos as f64));
547+
if !nanos_f64.is_finite() {
548+
panic!("got non-finite value when multiplying float by duration");
549+
}
550+
if nanos_f64 > (u128::MAX as f64) {
551+
panic!("overflow when multiplying float by duration");
552+
};
553+
let nanos_u128 = nanos_f64 as u128;
554+
let secs = nanos_u128 / (NANOS_PER_SEC as u128);
555+
let nanos = nanos_u128 % (NANOS_PER_SEC as u128);
556+
if secs > (u64::MAX as u128) {
557+
panic!("overflow when multiplying float by duration");
558+
}
559+
Duration {
560+
secs: secs as u64,
561+
nanos: nanos as u32,
562+
}
563+
}
564+
}
565+
504566
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
505567
impl MulAssign<u32> for Duration {
506568
fn mul_assign(&mut self, rhs: u32) {
507569
*self = *self * rhs;
508570
}
509571
}
510572

573+
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")]
574+
impl MulAssign<f64> for Duration {
575+
fn mul_assign(&mut self, rhs: f64) {
576+
*self = *self * rhs;
577+
}
578+
}
579+
511580
#[stable(feature = "duration", since = "1.3.0")]
512581
impl Div<u32> for Duration {
513582
type Output = Duration;
@@ -517,13 +586,59 @@ impl Div<u32> for Duration {
517586
}
518587
}
519588

589+
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")]
590+
impl Div<f64> for Duration {
591+
type Output = Duration;
592+
593+
fn div(self, rhs: f64) -> Duration {
594+
const NPS: f64 = NANOS_PER_SEC as f64;
595+
let nanos_f64 = (NPS * (self.secs as f64) + (self.nanos as f64)) / rhs;
596+
if !nanos_f64.is_finite() {
597+
panic!("got non-finite value when dividing duration by float");
598+
}
599+
if nanos_f64 > (u128::MAX as f64) {
600+
panic!("overflow when dividing duration by float");
601+
};
602+
let nanos_u128 = nanos_f64 as u128;
603+
let secs = nanos_u128 / (NANOS_PER_SEC as u128);
604+
let nanos = nanos_u128 % (NANOS_PER_SEC as u128);
605+
if secs > (u64::MAX as u128) {
606+
panic!("overflow when dividing duration by float");
607+
}
608+
Duration {
609+
secs: secs as u64,
610+
nanos: nanos as u32,
611+
}
612+
}
613+
}
614+
615+
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")]
616+
impl Div<Duration> for Duration {
617+
type Output = f64;
618+
619+
fn div(self, rhs: Duration) -> f64 {
620+
const NPS: f64 = NANOS_PER_SEC as f64;
621+
let nanos1 = NPS * (self.secs as f64) + (self.nanos as f64);
622+
let nanos2 = NPS * (rhs.secs as f64) + (rhs.nanos as f64);
623+
nanos1/nanos2
624+
}
625+
}
626+
520627
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
521628
impl DivAssign<u32> for Duration {
522629
fn div_assign(&mut self, rhs: u32) {
523630
*self = *self / rhs;
524631
}
525632
}
526633

634+
#[stable(feature = "duration_mul_div_extras", since = "1.29.0")]
635+
impl DivAssign<f64> for Duration {
636+
fn div_assign(&mut self, rhs: f64) {
637+
*self = *self / rhs;
638+
}
639+
}
640+
641+
527642
macro_rules! sum_durations {
528643
($iter:expr) => {{
529644
let mut total_secs: u64 = 0;

src/libstd/time.rs

+26
Original file line numberDiff line numberDiff line change
@@ -590,4 +590,30 @@ mod tests {
590590
let hundred_twenty_years = thirty_years * 4;
591591
assert!(a < hundred_twenty_years);
592592
}
593+
594+
#[test]
595+
fn duration_float_ops() {
596+
let dur = Duration::new(2, 700_000_000);
597+
598+
let dur2 = 3.14*dur;
599+
assert_eq!(dur2, dur*3.14);
600+
assert_eq!(dur2.as_secs(), 8);
601+
assert_eq!(dur2.subsec_nanos(), 478_000_000);
602+
603+
let dur3 = 3.14e5*dur;
604+
assert_eq!(dur3, dur*3.14e5);
605+
assert_eq!(dur3.as_secs(), 847_800);
606+
assert_eq!(dur3.subsec_nanos(), 0);
607+
608+
let dur4 = dur/3.14;
609+
assert_eq!(dur4.as_secs(), 0);
610+
assert_eq!(dur4.subsec_nanos(), 859_872_611);
611+
612+
let dur5 = dur/3.14e5;
613+
assert_eq!(dur5.as_secs(), 0);
614+
// we are using truncation and not rounding
615+
assert_eq!(dur5.subsec_nanos(), 8598);
616+
617+
assert_eq!(dur/Duration::new(5, 400_000_000), 0.5);
618+
}
593619
}

0 commit comments

Comments
 (0)