Skip to content

Commit e0345c9

Browse files
committed
Heed target_has_reliable_f128 in Duration-float ops
1 parent 22c75ea commit e0345c9

2 files changed

Lines changed: 36 additions & 8 deletions

File tree

library/core/src/time.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,7 @@ impl Duration {
10021002

10031003
#[inline]
10041004
#[track_caller]
1005+
#[cfg(target_has_reliable_f128)]
10051006
fn from_nanos_f128_subnormal(nanos: f128) -> Duration {
10061007
// NB: the mul/div methods below are converting nanos with `f128::from_bits`, which puts
10071008
// them in the subnormal range, with the value packed in the least-significant bits of the
@@ -1023,6 +1024,7 @@ impl Duration {
10231024

10241025
#[inline]
10251026
#[track_caller]
1027+
#[cfg(target_has_reliable_f128)]
10261028
fn mul_f128(self, rhs: f128) -> Duration {
10271029
if rhs < 0.0 && self != Self::ZERO {
10281030
panic!("{}", TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::Negative });
@@ -1033,6 +1035,7 @@ impl Duration {
10331035

10341036
#[inline]
10351037
#[track_caller]
1038+
#[cfg(target_has_reliable_f128)]
10361039
fn div_f128(self, rhs: f128) -> Duration {
10371040
if rhs < 0.0 && rhs.is_finite() && self != Self::ZERO {
10381041
panic!("{}", TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::Negative });
@@ -1059,7 +1062,10 @@ impl Duration {
10591062
without modifying the original"]
10601063
#[inline]
10611064
pub fn mul_f64(self, rhs: f64) -> Duration {
1062-
self.mul_f128(rhs.into())
1065+
crate::cfg_select! {
1066+
target_has_reliable_f128 => self.mul_f128(rhs.into()),
1067+
_ => Duration::from_secs_f64(rhs * self.as_secs_f64()),
1068+
}
10631069
}
10641070

10651071
/// Multiplies `Duration` by `f32`.
@@ -1080,7 +1086,10 @@ impl Duration {
10801086
without modifying the original"]
10811087
#[inline]
10821088
pub fn mul_f32(self, rhs: f32) -> Duration {
1083-
self.mul_f128(rhs.into())
1089+
crate::cfg_select! {
1090+
target_has_reliable_f128 => self.mul_f128(rhs.into()),
1091+
_ => self.mul_f64(rhs.into()),
1092+
}
10841093
}
10851094

10861095
/// Divides `Duration` by `f64`.
@@ -1101,7 +1110,10 @@ impl Duration {
11011110
without modifying the original"]
11021111
#[inline]
11031112
pub fn div_f64(self, rhs: f64) -> Duration {
1104-
self.div_f128(rhs.into())
1113+
crate::cfg_select! {
1114+
target_has_reliable_f128 => self.div_f128(rhs.into()),
1115+
_ => Duration::from_secs_f64(self.as_secs_f64() / rhs),
1116+
}
11051117
}
11061118

11071119
/// Divides `Duration` by `f32`.
@@ -1124,7 +1136,10 @@ impl Duration {
11241136
without modifying the original"]
11251137
#[inline]
11261138
pub fn div_f32(self, rhs: f32) -> Duration {
1127-
self.div_f128(rhs.into())
1139+
crate::cfg_select! {
1140+
target_has_reliable_f128 => self.div_f128(rhs.into()),
1141+
_ => self.div_f64(rhs.into()),
1142+
}
11281143
}
11291144

11301145
/// Divides `Duration` by `Duration` and returns `f64`.

library/coretests/tests/time.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -642,15 +642,25 @@ fn duration_fp_div_negative() {
642642
}
643643

644644
const TOO_LARGE_FACTOR: f64 = Duration::MAX.as_nanos() as f64;
645-
const TOO_LARGE_DIVISOR: f64 = TOO_LARGE_FACTOR * 2.0;
646-
const SMALLEST_DIVISOR: f64 = TOO_LARGE_DIVISOR.recip() * 2.0;
647645
const SMALLEST_FACTOR: f64 = TOO_LARGE_FACTOR.recip() / 2.0;
648-
const SMALLEST_NEGFACTOR: f64 = -0.0f64;
646+
647+
cfg_select! {
648+
target_has_reliable_f128 => {
649+
const TOO_LARGE_DIVISOR: f64 = TOO_LARGE_FACTOR * 2.0;
650+
const SMALLEST_DIVISOR: f64 = TOO_LARGE_DIVISOR.recip() * 2.0;
651+
const SMALLEST_NEGFACTOR: f64 = -0.0f64;
652+
}
653+
_ => {
654+
const TOO_LARGE_DIVISOR: f64 = (Duration::MAX.as_secs_f64() * 2e9).next_up();
655+
const SMALLEST_DIVISOR: f64 = (TOO_LARGE_DIVISOR.recip() * 2.0).next_up().next_up();
656+
const SMALLEST_NEGFACTOR: f64 = (0.0f64.next_down() * 0.5e9).next_up();
657+
}
658+
}
649659

650660
#[test]
651661
fn duration_fp_boundaries() {
652662
const DURATION_BITS: u32 = Duration::MAX.as_nanos().ilog2() + 1;
653-
const PRECISION: u32 = DURATION_BITS - f64::MANTISSA_DIGITS;
663+
const PRECISION: u32 = DURATION_BITS - f64::MANTISSA_DIGITS + 1;
654664

655665
assert_eq!(Duration::MAX.mul_f64(0.0), Duration::ZERO);
656666
assert_eq!(Duration::MAX.mul_f64(-0.0), Duration::ZERO);
@@ -697,6 +707,7 @@ fn duration_fp_div_overflow() {
697707
}
698708

699709
#[test]
710+
#[cfg_attr(not(target_has_reliable_f128), ignore)]
700711
fn precise_duration_fp_mul() {
701712
let d1 = Duration::from_nanos_u128(1 << 90);
702713
let d2 = Duration::from_nanos_u128(2 << 90);
@@ -711,6 +722,7 @@ fn precise_duration_fp_mul() {
711722
}
712723

713724
#[test]
725+
#[cfg_attr(not(target_has_reliable_f128), ignore)]
714726
fn precise_duration_fp_div() {
715727
let d1 = Duration::from_nanos_u128(1 << 90);
716728
let d2 = Duration::from_nanos_u128(2 << 90);
@@ -725,6 +737,7 @@ fn precise_duration_fp_div() {
725737
}
726738

727739
#[test]
740+
#[cfg_attr(not(target_has_reliable_f128), ignore)]
728741
fn duration_fp_mul_rounding() {
729742
// This precise result in ns would start 9223372036854777855999999999.4999999999999998...
730743
// If that is rounded too early to 9223372036854777855999999999.5,

0 commit comments

Comments
 (0)