Skip to content

Commit fe7227f

Browse files
committed
Auto merge of #42430 - nagisa:core-float, r=alexcrichton
Re-implement float min/max in rust This also adds the relevant implementations into libcore. See #42423
2 parents b40be00 + ba6cf1d commit fe7227f

File tree

7 files changed

+122
-8
lines changed

7 files changed

+122
-8
lines changed

src/libcore/num/f32.rs

+28
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,32 @@ impl Float for f32 {
242242
let value: f32 = consts::PI;
243243
self * (value / 180.0f32)
244244
}
245+
246+
/// Returns the maximum of the two numbers.
247+
#[inline]
248+
fn max(self, other: f32) -> f32 {
249+
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
250+
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
251+
// is either x or y, canonicalized (this means results might differ among implementations).
252+
// When either x or y is a signalingNaN, then the result is according to 6.2.
253+
//
254+
// Since we do not support sNaN in Rust yet, we do not need to handle them.
255+
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
256+
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
257+
(if self < other || self.is_nan() { other } else { self }) * 1.0
258+
}
259+
260+
/// Returns the minimum of the two numbers.
261+
#[inline]
262+
fn min(self, other: f32) -> f32 {
263+
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
264+
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
265+
// is either x or y, canonicalized (this means results might differ among implementations).
266+
// When either x or y is a signalingNaN, then the result is according to 6.2.
267+
//
268+
// Since we do not support sNaN in Rust yet, we do not need to handle them.
269+
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
270+
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
271+
(if self < other || other.is_nan() { self } else { other }) * 1.0
272+
}
245273
}

src/libcore/num/f64.rs

+28
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,32 @@ impl Float for f64 {
242242
let value: f64 = consts::PI;
243243
self * (value / 180.0)
244244
}
245+
246+
/// Returns the maximum of the two numbers.
247+
#[inline]
248+
fn max(self, other: f64) -> f64 {
249+
// IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the
250+
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
251+
// is either x or y, canonicalized (this means results might differ among implementations).
252+
// When either x or y is a signalingNaN, then the result is according to 6.2.
253+
//
254+
// Since we do not support sNaN in Rust yet, we do not need to handle them.
255+
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
256+
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
257+
(if self < other || self.is_nan() { other } else { self }) * 1.0
258+
}
259+
260+
/// Returns the minimum of the two numbers.
261+
#[inline]
262+
fn min(self, other: f64) -> f64 {
263+
// IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the
264+
// canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it
265+
// is either x or y, canonicalized (this means results might differ among implementations).
266+
// When either x or y is a signalingNaN, then the result is according to 6.2.
267+
//
268+
// Since we do not support sNaN in Rust yet, we do not need to handle them.
269+
// FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by
270+
// multiplying by 1.0. Should switch to the `canonicalize` when it works.
271+
(if self < other || other.is_nan() { self } else { other }) * 1.0
272+
}
245273
}

src/libcore/num/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2459,6 +2459,13 @@ pub trait Float: Sized {
24592459
/// Convert degrees to radians.
24602460
#[stable(feature = "deg_rad_conversions", since="1.7.0")]
24612461
fn to_radians(self) -> Self;
2462+
2463+
/// Returns the maximum of the two numbers.
2464+
#[stable(feature = "core_float_min_max", since="1.20.0")]
2465+
fn max(self, other: Self) -> Self;
2466+
/// Returns the minimum of the two numbers.
2467+
#[stable(feature = "core_float_min_max", since="1.20.0")]
2468+
fn min(self, other: Self) -> Self;
24622469
}
24632470

24642471
macro_rules! from_str_radix_int_impl {

src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#![feature(box_syntax)]
1414
#![feature(char_escape_debug)]
1515
#![feature(const_fn)]
16+
#![feature(core_float)]
1617
#![feature(core_private_bignum)]
1718
#![feature(core_private_diy_float)]
1819
#![feature(dec2flt)]

src/libcore/tests/num/mod.rs

+54
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,57 @@ test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 }
399399
test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 }
400400
test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 }
401401
test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 }
402+
403+
macro_rules! test_float {
404+
($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { mod $modname {
405+
use core::num::Float;
406+
// FIXME(nagisa): these tests should test for sign of -0.0
407+
#[test]
408+
fn min() {
409+
assert_eq!(0.0.min(0.0), 0.0);
410+
assert_eq!((-0.0).min(-0.0), -0.0);
411+
assert_eq!(9.0.min(9.0), 9.0);
412+
assert_eq!((-9.0).min(0.0), -9.0);
413+
assert_eq!(0.0.min(9.0), 0.0);
414+
assert_eq!((-0.0).min(-9.0), -9.0);
415+
assert_eq!($inf.min(9.0), 9.0);
416+
assert_eq!(9.0.min($inf), 9.0);
417+
assert_eq!($inf.min(-9.0), -9.0);
418+
assert_eq!((-9.0).min($inf), -9.0);
419+
assert_eq!($neginf.min(9.0), $neginf);
420+
assert_eq!(9.0.min($neginf), $neginf);
421+
assert_eq!($neginf.min(-9.0), $neginf);
422+
assert_eq!((-9.0).min($neginf), $neginf);
423+
assert_eq!($nan.min(9.0), 9.0);
424+
assert_eq!($nan.min(-9.0), -9.0);
425+
assert_eq!(9.0.min($nan), 9.0);
426+
assert_eq!((-9.0).min($nan), -9.0);
427+
assert!($nan.min($nan).is_nan());
428+
}
429+
#[test]
430+
fn max() {
431+
assert_eq!(0.0.max(0.0), 0.0);
432+
assert_eq!((-0.0).max(-0.0), -0.0);
433+
assert_eq!(9.0.max(9.0), 9.0);
434+
assert_eq!((-9.0).max(0.0), 0.0);
435+
assert_eq!(0.0.max(9.0), 9.0);
436+
assert_eq!((-0.0).max(-9.0), -0.0);
437+
assert_eq!($inf.max(9.0), $inf);
438+
assert_eq!(9.0.max($inf), $inf);
439+
assert_eq!($inf.max(-9.0), $inf);
440+
assert_eq!((-9.0).max($inf), $inf);
441+
assert_eq!($neginf.max(9.0), 9.0);
442+
assert_eq!(9.0.max($neginf), 9.0);
443+
assert_eq!($neginf.max(-9.0), -9.0);
444+
assert_eq!((-9.0).max($neginf), -9.0);
445+
assert_eq!($nan.max(9.0), 9.0);
446+
assert_eq!($nan.max(-9.0), -9.0);
447+
assert_eq!(9.0.max($nan), 9.0);
448+
assert_eq!((-9.0).max($nan), -9.0);
449+
assert!($nan.max($nan).is_nan());
450+
}
451+
} }
452+
}
453+
454+
test_float!(f32, f32, ::core::f32::INFINITY, ::core::f32::NEG_INFINITY, ::core::f32::NAN);
455+
test_float!(f64, f64, ::core::f64::INFINITY, ::core::f64::NEG_INFINITY, ::core::f64::NAN);

src/libstd/f32.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ mod cmath {
4646
pub fn erfcf(n: c_float) -> c_float;
4747
pub fn expm1f(n: c_float) -> c_float;
4848
pub fn fdimf(a: c_float, b: c_float) -> c_float;
49-
pub fn fmaxf(a: c_float, b: c_float) -> c_float;
50-
pub fn fminf(a: c_float, b: c_float) -> c_float;
5149
pub fn fmodf(a: c_float, b: c_float) -> c_float;
5250
pub fn ilogbf(n: c_float) -> c_int;
5351
pub fn logbf(n: c_float) -> c_float;
@@ -673,7 +671,7 @@ impl f32 {
673671
#[stable(feature = "rust1", since = "1.0.0")]
674672
#[inline]
675673
pub fn max(self, other: f32) -> f32 {
676-
unsafe { cmath::fmaxf(self, other) }
674+
num::Float::max(self, other)
677675
}
678676

679677
/// Returns the minimum of the two numbers.
@@ -689,7 +687,7 @@ impl f32 {
689687
#[stable(feature = "rust1", since = "1.0.0")]
690688
#[inline]
691689
pub fn min(self, other: f32) -> f32 {
692-
unsafe { cmath::fminf(self, other) }
690+
num::Float::min(self, other)
693691
}
694692

695693
/// The positive difference of two numbers.

src/libstd/f64.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ mod cmath {
5151
pub fn erfc(n: c_double) -> c_double;
5252
pub fn expm1(n: c_double) -> c_double;
5353
pub fn fdim(a: c_double, b: c_double) -> c_double;
54-
pub fn fmax(a: c_double, b: c_double) -> c_double;
55-
pub fn fmin(a: c_double, b: c_double) -> c_double;
5654
pub fn fmod(a: c_double, b: c_double) -> c_double;
5755
pub fn frexp(n: c_double, value: &mut c_int) -> c_double;
5856
pub fn ilogb(n: c_double) -> c_int;
@@ -587,7 +585,7 @@ impl f64 {
587585
#[stable(feature = "rust1", since = "1.0.0")]
588586
#[inline]
589587
pub fn max(self, other: f64) -> f64 {
590-
unsafe { cmath::fmax(self, other) }
588+
num::Float::max(self, other)
591589
}
592590

593591
/// Returns the minimum of the two numbers.
@@ -603,7 +601,7 @@ impl f64 {
603601
#[stable(feature = "rust1", since = "1.0.0")]
604602
#[inline]
605603
pub fn min(self, other: f64) -> f64 {
606-
unsafe { cmath::fmin(self, other) }
604+
num::Float::min(self, other)
607605
}
608606

609607
/// The positive difference of two numbers.

0 commit comments

Comments
 (0)