about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/Cargo.lock1
-rw-r--r--library/alloc/src/raw_vec/mod.rs2
-rw-r--r--library/alloc/src/string.rs48
-rw-r--r--library/alloc/src/vec/mod.rs6
-rw-r--r--library/core/Cargo.toml6
-rw-r--r--library/core/src/array/mod.rs1
-rw-r--r--library/core/src/char/methods.rs21
-rw-r--r--library/core/src/convert/mod.rs10
-rw-r--r--library/core/src/fmt/float.rs36
-rw-r--r--library/core/src/fmt/num.rs28
-rw-r--r--library/core/src/lib.rs4
-rw-r--r--library/core/src/num/dec2flt/float.rs57
-rw-r--r--library/core/src/num/dec2flt/mod.rs16
-rw-r--r--library/core/src/num/f128.rs410
-rw-r--r--library/core/src/num/f16.rs445
-rw-r--r--library/core/src/num/f32.rs413
-rw-r--r--library/core/src/num/f64.rs406
-rw-r--r--library/core/src/num/flt2dec/decoder.rs7
-rw-r--r--library/core/src/num/libm.rs11
-rw-r--r--library/core/src/num/mod.rs21
-rw-r--r--library/core/src/pin.rs10
-rw-r--r--library/core/src/ptr/non_null.rs6
-rw-r--r--library/core/src/str/mod.rs22
-rw-r--r--library/coretests/Cargo.toml11
-rw-r--r--library/coretests/tests/array.rs2
-rw-r--r--library/coretests/tests/floats/f128.rs790
-rw-r--r--library/coretests/tests/floats/f16.rs753
-rw-r--r--library/coretests/tests/floats/f32.rs702
-rw-r--r--library/coretests/tests/floats/f64.rs682
-rw-r--r--library/coretests/tests/floats/mod.rs40
-rw-r--r--library/coretests/tests/lib.rs7
-rw-r--r--library/coretests/tests/num/dec2flt/decimal.rs14
-rw-r--r--library/coretests/tests/num/dec2flt/float.rs40
-rw-r--r--library/coretests/tests/num/dec2flt/lemire.rs133
-rw-r--r--library/coretests/tests/num/dec2flt/mod.rs65
-rw-r--r--library/coretests/tests/num/dec2flt/parse.rs23
-rw-r--r--library/coretests/tests/num/flt2dec/mod.rs234
-rw-r--r--library/coretests/tests/num/flt2dec/random.rs60
-rw-r--r--library/coretests/tests/num/flt2dec/strategy/dragon.rs5
-rw-r--r--library/coretests/tests/num/flt2dec/strategy/grisu.rs4
-rw-r--r--library/coretests/tests/num/mod.rs332
-rw-r--r--library/panic_abort/Cargo.toml7
-rw-r--r--library/panic_abort/src/lib.rs76
-rw-r--r--library/panic_unwind/src/hermit.rs20
-rw-r--r--library/std/src/f128.rs396
-rw-r--r--library/std/src/f16.rs431
-rw-r--r--library/std/src/f32.rs32
-rw-r--r--library/std/src/f64.rs32
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--library/std/src/os/unix/net/stream.rs4
-rw-r--r--library/std/src/os/wasi/fs.rs2
-rw-r--r--library/std/src/os/windows/process.rs36
-rw-r--r--library/std/src/rt.rs9
-rw-r--r--library/std/src/sys/cmath.rs4
-rw-r--r--library/std/src/sys/fs/unix.rs3
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs9
-rw-r--r--library/std/src/sys/pal/sgx/mod.rs7
-rw-r--r--library/std/src/sys/pal/uefi/mod.rs8
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs144
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow/thread_info.rs129
-rw-r--r--library/std/src/sys/pal/unix/thread.rs12
-rw-r--r--library/std/src/sys/pal/windows/mod.rs8
-rw-r--r--library/std/src/sys/pal/xous/mod.rs6
-rw-r--r--library/std/src/sys/pal/xous/os.rs8
-rw-r--r--library/std/src/sys/process/windows.rs36
-rw-r--r--library/std/tests/floats/f128.rs762
-rw-r--r--library/std/tests/floats/f16.rs722
-rw-r--r--library/std/tests/floats/f32.rs687
-rw-r--r--library/std/tests/floats/f64.rs668
-rw-r--r--library/std/tests/floats/lib.rs3
m---------library/stdarch0
71 files changed, 6002 insertions, 4145 deletions
diff --git a/library/Cargo.lock b/library/Cargo.lock
index 97ca3cb06b2..02018057ed5 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -196,7 +196,6 @@ name = "panic_abort"
 version = "0.0.0"
 dependencies = [
  "alloc",
- "cfg-if",
  "compiler_builtins",
  "core",
  "libc",
diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs
index a989e5b55b3..3e006a2d1bd 100644
--- a/library/alloc/src/raw_vec/mod.rs
+++ b/library/alloc/src/raw_vec/mod.rs
@@ -287,7 +287,7 @@ impl<T, A: Allocator> RawVec<T, A> {
     }
 
     #[inline]
-    pub(crate) fn non_null(&self) -> NonNull<T> {
+    pub(crate) const fn non_null(&self) -> NonNull<T> {
         self.inner.non_null()
     }
 
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 4e42a5da7ea..37614a7ca45 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2826,7 +2826,54 @@ impl SpecToString for bool {
     }
 }
 
+macro_rules! impl_to_string {
+    ($($signed:ident, $unsigned:ident,)*) => {
+        $(
+        #[cfg(not(no_global_oom_handling))]
+        #[cfg(not(feature = "optimize_for_size"))]
+        impl SpecToString for $signed {
+            #[inline]
+            fn spec_to_string(&self) -> String {
+                const SIZE: usize = $signed::MAX.ilog(10) as usize + 1;
+                let mut buf = [core::mem::MaybeUninit::<u8>::uninit(); SIZE];
+                // Only difference between signed and unsigned are these 8 lines.
+                let mut out;
+                if *self < 0 {
+                    out = String::with_capacity(SIZE + 1);
+                    out.push('-');
+                } else {
+                    out = String::with_capacity(SIZE);
+                }
+
+                out.push_str(self.unsigned_abs()._fmt(&mut buf));
+                out
+            }
+        }
+        #[cfg(not(no_global_oom_handling))]
+        #[cfg(not(feature = "optimize_for_size"))]
+        impl SpecToString for $unsigned {
+            #[inline]
+            fn spec_to_string(&self) -> String {
+                const SIZE: usize = $unsigned::MAX.ilog(10) as usize + 1;
+                let mut buf = [core::mem::MaybeUninit::<u8>::uninit(); SIZE];
+
+                self._fmt(&mut buf).to_string()
+            }
+        }
+        )*
+    }
+}
+
+impl_to_string! {
+    i8, u8,
+    i16, u16,
+    i32, u32,
+    i64, u64,
+    isize, usize,
+}
+
 #[cfg(not(no_global_oom_handling))]
+#[cfg(feature = "optimize_for_size")]
 impl SpecToString for u8 {
     #[inline]
     fn spec_to_string(&self) -> String {
@@ -2846,6 +2893,7 @@ impl SpecToString for u8 {
 }
 
 #[cfg(not(no_global_oom_handling))]
+#[cfg(feature = "optimize_for_size")]
 impl SpecToString for i8 {
     #[inline]
     fn spec_to_string(&self) -> String {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index a97912304c8..59879f23d78 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1816,10 +1816,10 @@ impl<T, A: Allocator> Vec<T, A> {
     /// [`as_ptr`]: Vec::as_ptr
     /// [`as_non_null`]: Vec::as_non_null
     #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
+    #[rustc_const_unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
     #[inline]
-    pub fn as_non_null(&mut self) -> NonNull<T> {
-        // SAFETY: A `Vec` always has a non-null pointer.
-        unsafe { NonNull::new_unchecked(self.as_mut_ptr()) }
+    pub const fn as_non_null(&mut self) -> NonNull<T> {
+        self.buf.non_null()
     }
 
     /// Returns a reference to the underlying allocator.
diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml
index 99e52d0ada0..83ba17b93f5 100644
--- a/library/core/Cargo.toml
+++ b/library/core/Cargo.toml
@@ -35,4 +35,10 @@ check-cfg = [
     # and to stdarch `core_arch` crate which messes-up with Cargo list
     # of declared features, we therefor expect any feature cfg
     'cfg(feature, values(any()))',
+    # Internal features aren't marked known config by default, we use these to
+    # gate tests.
+    'cfg(target_has_reliable_f16)',
+    'cfg(target_has_reliable_f16_math)',
+    'cfg(target_has_reliable_f128)',
+    'cfg(target_has_reliable_f128_math)',
 ]
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index efa7bed7c8e..4476e3f7923 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -531,6 +531,7 @@ impl<T, const N: usize> [T; N] {
     /// let y = x.map(|v| v.len());
     /// assert_eq!(y, [6, 9, 3, 3]);
     /// ```
+    #[must_use]
     #[stable(feature = "array_map", since = "1.55.0")]
     pub fn map<F, U>(self, f: F) -> [U; N]
     where
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 042925a352f..af2edf141b2 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -4,6 +4,7 @@ use super::*;
 use crate::panic::const_panic;
 use crate::slice;
 use crate::str::from_utf8_unchecked_mut;
+use crate::ub_checks::assert_unsafe_precondition;
 use crate::unicode::printable::is_printable;
 use crate::unicode::{self, conversions};
 
@@ -1202,6 +1203,26 @@ impl char {
         }
     }
 
+    /// Converts this char into an [ASCII character](`ascii::Char`), without
+    /// checking whether it is valid.
+    ///
+    /// # Safety
+    ///
+    /// This char must be within the ASCII range, or else this is UB.
+    #[must_use]
+    #[unstable(feature = "ascii_char", issue = "110998")]
+    #[inline]
+    pub const unsafe fn as_ascii_unchecked(&self) -> ascii::Char {
+        assert_unsafe_precondition!(
+            check_library_ub,
+            "as_ascii_unchecked requires that the char is valid ASCII",
+            (it: &char = self) => it.is_ascii()
+        );
+
+        // SAFETY: the caller promised that this char is ASCII.
+        unsafe { ascii::Char::from_u8_unchecked(*self as u8) }
+    }
+
     /// Makes a copy of the value in its ASCII upper case equivalent.
     ///
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index e1b10e1074d..c542a28beb8 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -464,8 +464,8 @@ pub trait Into<T>: Sized {
 /// orphaning rules.
 /// See [`Into`] for more details.
 ///
-/// Prefer using [`Into`] over using `From` when specifying trait bounds on a generic function.
-/// This way, types that directly implement [`Into`] can be used as arguments as well.
+/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function
+/// to ensure that types that only implement [`Into`] can be used as well.
 ///
 /// The `From` trait is also very useful when performing error handling. When constructing a function
 /// that is capable of failing, the return type will generally be of the form `Result<T, E>`.
@@ -597,6 +597,9 @@ pub trait From<T>: Sized {
 /// standard library. For more information on this, see the
 /// documentation for [`Into`].
 ///
+/// Prefer using [`TryInto`] over [`TryFrom`] when specifying trait bounds on a generic function
+/// to ensure that types that only implement [`TryInto`] can be used as well.
+///
 /// # Implementing `TryInto`
 ///
 /// This suffers the same restrictions and reasoning as implementing
@@ -636,6 +639,9 @@ pub trait TryInto<T>: Sized {
 /// When the [`!`] type is stabilized [`Infallible`] and [`!`] will be
 /// equivalent.
 ///
+/// Prefer using [`TryInto`] over [`TryFrom`] when specifying trait bounds on a generic function
+/// to ensure that types that only implement [`TryInto`] can be used as well.
+///
 /// `TryFrom<T>` can be implemented as follows:
 ///
 /// ```
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 870ad9df4fd..556db239f24 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -20,6 +20,8 @@ macro_rules! impl_general_format {
     }
 }
 
+#[cfg(target_has_reliable_f16)]
+impl_general_format! { f16 }
 impl_general_format! { f32 f64 }
 
 // Don't inline this so callers don't use the stack space this function
@@ -231,6 +233,13 @@ macro_rules! floating {
 
 floating! { f32 f64 }
 
+#[cfg(target_has_reliable_f16)]
+floating! { f16 }
+
+// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order
+// to avoid ICEs.
+
+#[cfg(not(target_has_reliable_f16))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for f16 {
     #[inline]
@@ -239,6 +248,33 @@ impl Debug for f16 {
     }
 }
 
+#[cfg(not(target_has_reliable_f16))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Display for f16 {
+    #[inline]
+    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
+        Debug::fmt(self, fmt)
+    }
+}
+
+#[cfg(not(target_has_reliable_f16))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl LowerExp for f16 {
+    #[inline]
+    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
+        Debug::fmt(self, fmt)
+    }
+}
+
+#[cfg(not(target_has_reliable_f16))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl UpperExp for f16 {
+    #[inline]
+    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
+        Debug::fmt(self, fmt)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for f128 {
     #[inline]
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index 4467b37bd45..ba30518d70b 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -208,7 +208,11 @@ macro_rules! impl_Display {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 #[cfg(not(feature = "optimize_for_size"))]
                 {
-                    self._fmt(true, f)
+                    const MAX_DEC_N: usize = $unsigned::MAX.ilog(10) as usize + 1;
+                    // Buffer decimals for $unsigned with right alignment.
+                    let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
+
+                    f.pad_integral(true, "", self._fmt(&mut buf))
                 }
                 #[cfg(feature = "optimize_for_size")]
                 {
@@ -222,7 +226,11 @@ macro_rules! impl_Display {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 #[cfg(not(feature = "optimize_for_size"))]
                 {
-                    return self.unsigned_abs()._fmt(*self >= 0, f);
+                    const MAX_DEC_N: usize = $unsigned::MAX.ilog(10) as usize + 1;
+                    // Buffer decimals for $unsigned with right alignment.
+                    let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
+
+                    f.pad_integral(*self >= 0, "", self.unsigned_abs()._fmt(&mut buf))
                 }
                 #[cfg(feature = "optimize_for_size")]
                 {
@@ -233,10 +241,13 @@ macro_rules! impl_Display {
 
         #[cfg(not(feature = "optimize_for_size"))]
         impl $unsigned {
-            fn _fmt(self, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                const MAX_DEC_N: usize = $unsigned::MAX.ilog(10) as usize + 1;
-                // Buffer decimals for $unsigned with right alignment.
-                let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
+            #[doc(hidden)]
+            #[unstable(
+                feature = "fmt_internals",
+                reason = "specialized method meant to only be used by `SpecToString` implementation",
+                issue = "none"
+            )]
+            pub fn _fmt<'a>(self, buf: &'a mut [MaybeUninit::<u8>]) -> &'a str {
                 // Count the number of bytes in buf that are not initialized.
                 let mut offset = buf.len();
                 // Consume the least-significant decimals from a working copy.
@@ -301,13 +312,12 @@ macro_rules! impl_Display {
                 // SAFETY: All buf content since offset is set.
                 let written = unsafe { buf.get_unchecked(offset..) };
                 // SAFETY: Writes use ASCII from the lookup table exclusively.
-                let as_str = unsafe {
+                unsafe {
                     str::from_utf8_unchecked(slice::from_raw_parts(
                           MaybeUninit::slice_as_ptr(written),
                           written.len(),
                     ))
-                };
-                f.pad_integral(is_nonnegative, "", as_str)
+                }
             }
         })*
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 64a7ec8906b..e605d7e0d78 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -101,6 +101,7 @@
 #![feature(bstr)]
 #![feature(bstr_internals)]
 #![feature(cfg_match)]
+#![feature(cfg_target_has_reliable_f16_f128)]
 #![feature(const_carrying_mul_add)]
 #![feature(const_eval_select)]
 #![feature(core_intrinsics)]
@@ -111,7 +112,6 @@
 #![feature(is_ascii_octdigit)]
 #![feature(lazy_get)]
 #![feature(link_cfg)]
-#![feature(non_null_from_ref)]
 #![feature(offset_of_enum)]
 #![feature(panic_internals)]
 #![feature(ptr_alignment_type)]
@@ -188,9 +188,9 @@
 //
 // Target features:
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(avx512_target_feature))]
 #![feature(aarch64_unstable_target_feature)]
 #![feature(arm_target_feature)]
-#![feature(avx512_target_feature)]
 #![feature(hexagon_target_feature)]
 #![feature(keylocker_x86)]
 #![feature(loongarch_target_feature)]
diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs
index b8a28a67569..5bf0faf0bc9 100644
--- a/library/core/src/num/dec2flt/float.rs
+++ b/library/core/src/num/dec2flt/float.rs
@@ -45,7 +45,7 @@ macro_rules! int {
     }
 }
 
-int!(u32, u64);
+int!(u16, u32, u64);
 
 /// A helper trait to avoid duplicating basically all the conversion code for IEEE floats.
 ///
@@ -189,9 +189,14 @@ pub trait RawFloat:
 
     /// Returns the mantissa, exponent and sign as integers.
     ///
-    /// That is, this returns `(m, p, s)` such that `s * m * 2^p` represents the original float.
-    /// For 0, the exponent will be `-(EXP_BIAS + SIG_BITS`, which is the
-    /// minimum subnormal power.
+    /// This returns `(m, p, s)` such that `s * m * 2^p` represents the original float. For 0, the
+    /// exponent will be `-(EXP_BIAS + SIG_BITS)`, which is the minimum subnormal power. For
+    /// infinity or NaN, the exponent will be `EXP_SAT - EXP_BIAS - SIG_BITS`.
+    ///
+    /// If subnormal, the mantissa will be shifted one bit to the left. Otherwise, it is returned
+    /// with the explicit bit set but otherwise unshifted
+    ///
+    /// `s` is only ever +/-1.
     fn integer_decode(self) -> (u64, i16, i8) {
         let bits = self.to_bits();
         let sign: i8 = if bits >> (Self::BITS - 1) == Self::Int::ZERO { 1 } else { -1 };
@@ -213,6 +218,50 @@ const fn pow2_to_pow10(a: i64) -> i64 {
     res as i64
 }
 
+#[cfg(target_has_reliable_f16)]
+impl RawFloat for f16 {
+    type Int = u16;
+
+    const INFINITY: Self = Self::INFINITY;
+    const NEG_INFINITY: Self = Self::NEG_INFINITY;
+    const NAN: Self = Self::NAN;
+    const NEG_NAN: Self = -Self::NAN;
+
+    const BITS: u32 = 16;
+    const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
+    const EXP_MASK: Self::Int = Self::EXP_MASK;
+    const SIG_MASK: Self::Int = Self::MAN_MASK;
+
+    const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -22;
+    const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 5;
+    const SMALLEST_POWER_OF_TEN: i32 = -27;
+
+    #[inline]
+    fn from_u64(v: u64) -> Self {
+        debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
+        v as _
+    }
+
+    #[inline]
+    fn from_u64_bits(v: u64) -> Self {
+        Self::from_bits((v & 0xFFFF) as u16)
+    }
+
+    fn pow10_fast_path(exponent: usize) -> Self {
+        #[allow(clippy::use_self)]
+        const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
+        TABLE[exponent & 7]
+    }
+
+    fn to_bits(self) -> Self::Int {
+        self.to_bits()
+    }
+
+    fn classify(self) -> FpCategory {
+        self.classify()
+    }
+}
+
 impl RawFloat for f32 {
     type Int = u32;
 
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index d1a0e1db313..abad7acb104 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -171,9 +171,25 @@ macro_rules! from_str_float_impl {
         }
     };
 }
+
+#[cfg(target_has_reliable_f16)]
+from_str_float_impl!(f16);
 from_str_float_impl!(f32);
 from_str_float_impl!(f64);
 
+// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order
+// to avoid ICEs.
+
+#[cfg(not(target_has_reliable_f16))]
+impl FromStr for f16 {
+    type Err = ParseFloatError;
+
+    #[inline]
+    fn from_str(_src: &str) -> Result<Self, ParseFloatError> {
+        unimplemented!("requires target_has_reliable_f16")
+    }
+}
+
 /// An error which can be returned when parsing a float.
 ///
 /// This error is used as the error type for the [`FromStr`] implementation
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 7e470185c86..0c2c4155d66 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -1415,3 +1415,413 @@ impl f128 {
         intrinsics::frem_algebraic(self, rhs)
     }
 }
+
+// Functions in this module fall into `core_float_math`
+// FIXME(f16_f128): all doctests must be gated to platforms that have `long double` === `_Float128`
+// due to https://github.com/llvm/llvm-project/issues/44744. aarch64 linux matches this.
+// #[unstable(feature = "core_float_math", issue = "137578")]
+#[cfg(not(test))]
+impl f128 {
+    /// Returns the largest integer less than or equal to `self`.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let f = 3.7_f128;
+    /// let g = 3.0_f128;
+    /// let h = -3.7_f128;
+    ///
+    /// assert_eq!(f.floor(), 3.0);
+    /// assert_eq!(g.floor(), 3.0);
+    /// assert_eq!(h.floor(), -4.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn floor(self) -> f128 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::floorf128(self) }
+    }
+
+    /// Returns the smallest integer greater than or equal to `self`.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let f = 3.01_f128;
+    /// let g = 4.0_f128;
+    ///
+    /// assert_eq!(f.ceil(), 4.0);
+    /// assert_eq!(g.ceil(), 4.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[doc(alias = "ceiling")]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn ceil(self) -> f128 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::ceilf128(self) }
+    }
+
+    /// Returns the nearest integer to `self`. If a value is half-way between two
+    /// integers, round away from `0.0`.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let f = 3.3_f128;
+    /// let g = -3.3_f128;
+    /// let h = -3.7_f128;
+    /// let i = 3.5_f128;
+    /// let j = 4.5_f128;
+    ///
+    /// assert_eq!(f.round(), 3.0);
+    /// assert_eq!(g.round(), -3.0);
+    /// assert_eq!(h.round(), -4.0);
+    /// assert_eq!(i.round(), 4.0);
+    /// assert_eq!(j.round(), 5.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn round(self) -> f128 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::roundf128(self) }
+    }
+
+    /// Returns the nearest integer to a number. Rounds half-way cases to the number
+    /// with an even least significant digit.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let f = 3.3_f128;
+    /// let g = -3.3_f128;
+    /// let h = 3.5_f128;
+    /// let i = 4.5_f128;
+    ///
+    /// assert_eq!(f.round_ties_even(), 3.0);
+    /// assert_eq!(g.round_ties_even(), -3.0);
+    /// assert_eq!(h.round_ties_even(), 4.0);
+    /// assert_eq!(i.round_ties_even(), 4.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn round_ties_even(self) -> f128 {
+        intrinsics::round_ties_even_f128(self)
+    }
+
+    /// Returns the integer part of `self`.
+    /// This means that non-integer numbers are always truncated towards zero.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let f = 3.7_f128;
+    /// let g = 3.0_f128;
+    /// let h = -3.7_f128;
+    ///
+    /// assert_eq!(f.trunc(), 3.0);
+    /// assert_eq!(g.trunc(), 3.0);
+    /// assert_eq!(h.trunc(), -3.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[doc(alias = "truncate")]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn trunc(self) -> f128 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::truncf128(self) }
+    }
+
+    /// Returns the fractional part of `self`.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let x = 3.6_f128;
+    /// let y = -3.6_f128;
+    /// let abs_difference_x = (x.fract() - 0.6).abs();
+    /// let abs_difference_y = (y.fract() - (-0.6)).abs();
+    ///
+    /// assert!(abs_difference_x <= f128::EPSILON);
+    /// assert!(abs_difference_y <= f128::EPSILON);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn fract(self) -> f128 {
+        self - self.trunc()
+    }
+
+    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
+    /// error, yielding a more accurate result than an unfused multiply-add.
+    ///
+    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
+    /// the target architecture has a dedicated `fma` CPU instruction. However,
+    /// this is not always true, and will be heavily dependant on designing
+    /// algorithms with specific target hardware in mind.
+    ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result. It is specified by IEEE 754 as
+    /// `fusedMultiplyAdd` and guaranteed not to change.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let m = 10.0_f128;
+    /// let x = 4.0_f128;
+    /// let b = 60.0_f128;
+    ///
+    /// assert_eq!(m.mul_add(x, b), 100.0);
+    /// assert_eq!(m * x + b, 100.0);
+    ///
+    /// let one_plus_eps = 1.0_f128 + f128::EPSILON;
+    /// let one_minus_eps = 1.0_f128 - f128::EPSILON;
+    /// let minus_one = -1.0_f128;
+    ///
+    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+    /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f128::EPSILON * f128::EPSILON);
+    /// // Different rounding with the non-fused multiply and add.
+    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[doc(alias = "fmaf128", alias = "fusedMultiplyAdd")]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn mul_add(self, a: f128, b: f128) -> f128 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::fmaf128(self, a, b) }
+    }
+
+    /// Calculates Euclidean division, the matching method for `rem_euclid`.
+    ///
+    /// This computes the integer `n` such that
+    /// `self = n * rhs + self.rem_euclid(rhs)`.
+    /// In other words, the result is `self / rhs` rounded to the integer `n`
+    /// such that `self >= n * rhs`.
+    ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let a: f128 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
+    /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
+    /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
+    /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn div_euclid(self, rhs: f128) -> f128 {
+        let q = (self / rhs).trunc();
+        if self % rhs < 0.0 {
+            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+        }
+        q
+    }
+
+    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
+    ///
+    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
+    /// most cases. However, due to a floating point round-off error it can
+    /// result in `r == rhs.abs()`, violating the mathematical definition, if
+    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
+    /// This result is not an element of the function's codomain, but it is the
+    /// closest floating point number in the real numbers and thus fulfills the
+    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
+    /// approximately.
+    ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let a: f128 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.rem_euclid(b), 3.0);
+    /// assert_eq!((-a).rem_euclid(b), 1.0);
+    /// assert_eq!(a.rem_euclid(-b), 3.0);
+    /// assert_eq!((-a).rem_euclid(-b), 1.0);
+    /// // limitation due to round-off error
+    /// assert!((-f128::EPSILON).rem_euclid(3.0) != 0.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[doc(alias = "modulo", alias = "mod")]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn rem_euclid(self, rhs: f128) -> f128 {
+        let r = self % rhs;
+        if r < 0.0 { r + rhs.abs() } else { r }
+    }
+
+    /// Raises a number to an integer power.
+    ///
+    /// Using this function is generally faster than using `powf`.
+    /// It might have a different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let x = 2.0_f128;
+    /// let abs_difference = (x.powi(2) - (x * x)).abs();
+    /// assert!(abs_difference <= f128::EPSILON);
+    ///
+    /// assert_eq!(f128::powi(f128::NAN, 0), 1.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn powi(self, n: i32) -> f128 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::powif128(self, n) }
+    }
+
+    /// Returns the square root of a number.
+    ///
+    /// Returns NaN if `self` is a negative number other than `-0.0`.
+    ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
+    /// and guaranteed not to change.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f128_math)] {
+    ///
+    /// let positive = 4.0_f128;
+    /// let negative = -4.0_f128;
+    /// let negative_zero = -0.0_f128;
+    ///
+    /// assert_eq!(positive.sqrt(), 2.0);
+    /// assert!(negative.sqrt().is_nan());
+    /// assert!(negative_zero.sqrt() == negative_zero);
+    /// # }
+    /// ```
+    #[inline]
+    #[doc(alias = "squareRoot")]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f128", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn sqrt(self) -> f128 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::sqrtf128(self) }
+    }
+}
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index e47900cba55..1a859f2277f 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -13,6 +13,8 @@
 
 use crate::convert::FloatToInt;
 use crate::num::FpCategory;
+#[cfg(not(test))]
+use crate::num::libm;
 use crate::panic::const_assert;
 use crate::{intrinsics, mem};
 
@@ -1391,3 +1393,446 @@ impl f16 {
         intrinsics::frem_algebraic(self, rhs)
     }
 }
+
+// Functions in this module fall into `core_float_math`
+// #[unstable(feature = "core_float_math", issue = "137578")]
+#[cfg(not(test))]
+impl f16 {
+    /// Returns the largest integer less than or equal to `self`.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let f = 3.7_f16;
+    /// let g = 3.0_f16;
+    /// let h = -3.7_f16;
+    ///
+    /// assert_eq!(f.floor(), 3.0);
+    /// assert_eq!(g.floor(), 3.0);
+    /// assert_eq!(h.floor(), -4.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn floor(self) -> f16 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::floorf16(self) }
+    }
+
+    /// Returns the smallest integer greater than or equal to `self`.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let f = 3.01_f16;
+    /// let g = 4.0_f16;
+    ///
+    /// assert_eq!(f.ceil(), 4.0);
+    /// assert_eq!(g.ceil(), 4.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[doc(alias = "ceiling")]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn ceil(self) -> f16 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::ceilf16(self) }
+    }
+
+    /// Returns the nearest integer to `self`. If a value is half-way between two
+    /// integers, round away from `0.0`.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let f = 3.3_f16;
+    /// let g = -3.3_f16;
+    /// let h = -3.7_f16;
+    /// let i = 3.5_f16;
+    /// let j = 4.5_f16;
+    ///
+    /// assert_eq!(f.round(), 3.0);
+    /// assert_eq!(g.round(), -3.0);
+    /// assert_eq!(h.round(), -4.0);
+    /// assert_eq!(i.round(), 4.0);
+    /// assert_eq!(j.round(), 5.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn round(self) -> f16 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::roundf16(self) }
+    }
+
+    /// Returns the nearest integer to a number. Rounds half-way cases to the number
+    /// with an even least significant digit.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let f = 3.3_f16;
+    /// let g = -3.3_f16;
+    /// let h = 3.5_f16;
+    /// let i = 4.5_f16;
+    ///
+    /// assert_eq!(f.round_ties_even(), 3.0);
+    /// assert_eq!(g.round_ties_even(), -3.0);
+    /// assert_eq!(h.round_ties_even(), 4.0);
+    /// assert_eq!(i.round_ties_even(), 4.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn round_ties_even(self) -> f16 {
+        intrinsics::round_ties_even_f16(self)
+    }
+
+    /// Returns the integer part of `self`.
+    /// This means that non-integer numbers are always truncated towards zero.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let f = 3.7_f16;
+    /// let g = 3.0_f16;
+    /// let h = -3.7_f16;
+    ///
+    /// assert_eq!(f.trunc(), 3.0);
+    /// assert_eq!(g.trunc(), 3.0);
+    /// assert_eq!(h.trunc(), -3.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[doc(alias = "truncate")]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn trunc(self) -> f16 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::truncf16(self) }
+    }
+
+    /// Returns the fractional part of `self`.
+    ///
+    /// This function always returns the precise result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let x = 3.6_f16;
+    /// let y = -3.6_f16;
+    /// let abs_difference_x = (x.fract() - 0.6).abs();
+    /// let abs_difference_y = (y.fract() - (-0.6)).abs();
+    ///
+    /// assert!(abs_difference_x <= f16::EPSILON);
+    /// assert!(abs_difference_y <= f16::EPSILON);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn fract(self) -> f16 {
+        self - self.trunc()
+    }
+
+    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
+    /// error, yielding a more accurate result than an unfused multiply-add.
+    ///
+    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
+    /// the target architecture has a dedicated `fma` CPU instruction. However,
+    /// this is not always true, and will be heavily dependant on designing
+    /// algorithms with specific target hardware in mind.
+    ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result. It is specified by IEEE 754 as
+    /// `fusedMultiplyAdd` and guaranteed not to change.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let m = 10.0_f16;
+    /// let x = 4.0_f16;
+    /// let b = 60.0_f16;
+    ///
+    /// assert_eq!(m.mul_add(x, b), 100.0);
+    /// assert_eq!(m * x + b, 100.0);
+    ///
+    /// let one_plus_eps = 1.0_f16 + f16::EPSILON;
+    /// let one_minus_eps = 1.0_f16 - f16::EPSILON;
+    /// let minus_one = -1.0_f16;
+    ///
+    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+    /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f16::EPSILON * f16::EPSILON);
+    /// // Different rounding with the non-fused multiply and add.
+    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[doc(alias = "fmaf16", alias = "fusedMultiplyAdd")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn mul_add(self, a: f16, b: f16) -> f16 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::fmaf16(self, a, b) }
+    }
+
+    /// Calculates Euclidean division, the matching method for `rem_euclid`.
+    ///
+    /// This computes the integer `n` such that
+    /// `self = n * rhs + self.rem_euclid(rhs)`.
+    /// In other words, the result is `self / rhs` rounded to the integer `n`
+    /// such that `self >= n * rhs`.
+    ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let a: f16 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
+    /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
+    /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
+    /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn div_euclid(self, rhs: f16) -> f16 {
+        let q = (self / rhs).trunc();
+        if self % rhs < 0.0 {
+            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+        }
+        q
+    }
+
+    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
+    ///
+    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
+    /// most cases. However, due to a floating point round-off error it can
+    /// result in `r == rhs.abs()`, violating the mathematical definition, if
+    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
+    /// This result is not an element of the function's codomain, but it is the
+    /// closest floating point number in the real numbers and thus fulfills the
+    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
+    /// approximately.
+    ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let a: f16 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.rem_euclid(b), 3.0);
+    /// assert_eq!((-a).rem_euclid(b), 1.0);
+    /// assert_eq!(a.rem_euclid(-b), 3.0);
+    /// assert_eq!((-a).rem_euclid(-b), 1.0);
+    /// // limitation due to round-off error
+    /// assert!((-f16::EPSILON).rem_euclid(3.0) != 0.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[doc(alias = "modulo", alias = "mod")]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn rem_euclid(self, rhs: f16) -> f16 {
+        let r = self % rhs;
+        if r < 0.0 { r + rhs.abs() } else { r }
+    }
+
+    /// Raises a number to an integer power.
+    ///
+    /// Using this function is generally faster than using `powf`.
+    /// It might have a different sequence of rounding operations than `powf`,
+    /// so the results are not guaranteed to agree.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let x = 2.0_f16;
+    /// let abs_difference = (x.powi(2) - (x * x)).abs();
+    /// assert!(abs_difference <= f16::EPSILON);
+    ///
+    /// assert_eq!(f16::powi(f16::NAN, 0), 1.0);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn powi(self, n: i32) -> f16 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::powif16(self, n) }
+    }
+
+    /// Returns the square root of a number.
+    ///
+    /// Returns NaN if `self` is a negative number other than `-0.0`.
+    ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
+    /// and guaranteed not to change.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let positive = 4.0_f16;
+    /// let negative = -4.0_f16;
+    /// let negative_zero = -0.0_f16;
+    ///
+    /// assert_eq!(positive.sqrt(), 2.0);
+    /// assert!(negative.sqrt().is_nan());
+    /// assert!(negative_zero.sqrt() == negative_zero);
+    /// # }
+    /// ```
+    #[inline]
+    #[doc(alias = "squareRoot")]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn sqrt(self) -> f16 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::sqrtf16(self) }
+    }
+
+    /// Returns the cube root of a number.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `cbrtf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// # #![feature(cfg_target_has_reliable_f16_f128)]
+    /// # #![expect(internal_features)]
+    /// # #[cfg(not(miri))]
+    /// # #[cfg(target_has_reliable_f16_math)] {
+    ///
+    /// let x = 8.0f16;
+    ///
+    /// // x^(1/3) - 2 == 0
+    /// let abs_difference = (x.cbrt() - 2.0).abs();
+    ///
+    /// assert!(abs_difference <= f16::EPSILON);
+    /// # }
+    /// ```
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    #[unstable(feature = "f16", issue = "116909")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn cbrt(self) -> f16 {
+        libm::cbrtf(self as f32) as f16
+    }
+}
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 5fbc6eb33f1..9525bdb6762 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -12,7 +12,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::convert::FloatToInt;
-use crate::num::FpCategory;
+use crate::num::{FpCategory, libm};
 use crate::panic::const_assert;
 use crate::{cfg_match, intrinsics, mem};
 
@@ -1556,3 +1556,414 @@ impl f32 {
         intrinsics::frem_algebraic(self, rhs)
     }
 }
+
+/// Experimental version of `floor` in `core`. See [`f32::floor`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let f = 3.7_f32;
+/// let g = 3.0_f32;
+/// let h = -3.7_f32;
+///
+/// assert_eq!(f32::floor(f), 3.0);
+/// assert_eq!(f32::floor(g), 3.0);
+/// assert_eq!(f32::floor(h), -4.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::floor`]: ../../std/primitive.f32.html#method.floor
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn floor(x: f32) -> f32 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::floorf32(x) }
+}
+
+/// Experimental version of `ceil` in `core`. See [`f32::ceil`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let f = 3.01_f32;
+/// let g = 4.0_f32;
+///
+/// assert_eq!(f32::ceil(f), 4.0);
+/// assert_eq!(f32::ceil(g), 4.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::ceil`]: ../../std/primitive.f32.html#method.ceil
+#[inline]
+#[doc(alias = "ceiling")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+#[unstable(feature = "core_float_math", issue = "137578")]
+pub fn ceil(x: f32) -> f32 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::ceilf32(x) }
+}
+
+/// Experimental version of `round` in `core`. See [`f32::round`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let f = 3.3_f32;
+/// let g = -3.3_f32;
+/// let h = -3.7_f32;
+/// let i = 3.5_f32;
+/// let j = 4.5_f32;
+///
+/// assert_eq!(f32::round(f), 3.0);
+/// assert_eq!(f32::round(g), -3.0);
+/// assert_eq!(f32::round(h), -4.0);
+/// assert_eq!(f32::round(i), 4.0);
+/// assert_eq!(f32::round(j), 5.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::round`]: ../../std/primitive.f32.html#method.round
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn round(x: f32) -> f32 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::roundf32(x) }
+}
+
+/// Experimental version of `round_ties_even` in `core`. See [`f32::round_ties_even`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let f = 3.3_f32;
+/// let g = -3.3_f32;
+/// let h = 3.5_f32;
+/// let i = 4.5_f32;
+///
+/// assert_eq!(f32::round_ties_even(f), 3.0);
+/// assert_eq!(f32::round_ties_even(g), -3.0);
+/// assert_eq!(f32::round_ties_even(h), 4.0);
+/// assert_eq!(f32::round_ties_even(i), 4.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::round_ties_even`]: ../../std/primitive.f32.html#method.round_ties_even
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn round_ties_even(x: f32) -> f32 {
+    intrinsics::round_ties_even_f32(x)
+}
+
+/// Experimental version of `trunc` in `core`. See [`f32::trunc`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let f = 3.7_f32;
+/// let g = 3.0_f32;
+/// let h = -3.7_f32;
+///
+/// assert_eq!(f32::trunc(f), 3.0);
+/// assert_eq!(f32::trunc(g), 3.0);
+/// assert_eq!(f32::trunc(h), -3.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::trunc`]: ../../std/primitive.f32.html#method.trunc
+#[inline]
+#[doc(alias = "truncate")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+#[unstable(feature = "core_float_math", issue = "137578")]
+pub fn trunc(x: f32) -> f32 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::truncf32(x) }
+}
+
+/// Experimental version of `fract` in `core`. See [`f32::fract`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let x = 3.6_f32;
+/// let y = -3.6_f32;
+/// let abs_difference_x = (f32::fract(x) - 0.6).abs();
+/// let abs_difference_y = (f32::fract(y) - (-0.6)).abs();
+///
+/// assert!(abs_difference_x <= f32::EPSILON);
+/// assert!(abs_difference_y <= f32::EPSILON);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::fract`]: ../../std/primitive.f32.html#method.fract
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn fract(x: f32) -> f32 {
+    x - trunc(x)
+}
+
+/// Experimental version of `mul_add` in `core`. See [`f32::mul_add`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// # // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
+/// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
+/// use core::f32;
+///
+/// let m = 10.0_f32;
+/// let x = 4.0_f32;
+/// let b = 60.0_f32;
+///
+/// assert_eq!(f32::mul_add(m, x, b), 100.0);
+/// assert_eq!(m * x + b, 100.0);
+///
+/// let one_plus_eps = 1.0_f32 + f32::EPSILON;
+/// let one_minus_eps = 1.0_f32 - f32::EPSILON;
+/// let minus_one = -1.0_f32;
+///
+/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+/// assert_eq!(f32::mul_add(one_plus_eps, one_minus_eps, minus_one), -f32::EPSILON * f32::EPSILON);
+/// // Different rounding with the non-fused multiply and add.
+/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
+/// # }
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::mul_add`]: ../../std/primitive.f32.html#method.mul_add
+#[inline]
+#[doc(alias = "fmaf", alias = "fusedMultiplyAdd")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+#[unstable(feature = "core_float_math", issue = "137578")]
+pub fn mul_add(x: f32, y: f32, z: f32) -> f32 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::fmaf32(x, y, z) }
+}
+
+/// Experimental version of `div_euclid` in `core`. See [`f32::div_euclid`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let a: f32 = 7.0;
+/// let b = 4.0;
+/// assert_eq!(f32::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
+/// assert_eq!(f32::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
+/// assert_eq!(f32::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
+/// assert_eq!(f32::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::div_euclid`]: ../../std/primitive.f32.html#method.div_euclid
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn div_euclid(x: f32, rhs: f32) -> f32 {
+    let q = trunc(x / rhs);
+    if x % rhs < 0.0 {
+        return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+    }
+    q
+}
+
+/// Experimental version of `rem_euclid` in `core`. See [`f32::rem_euclid`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let a: f32 = 7.0;
+/// let b = 4.0;
+/// assert_eq!(f32::rem_euclid(a, b), 3.0);
+/// assert_eq!(f32::rem_euclid(-a, b), 1.0);
+/// assert_eq!(f32::rem_euclid(a, -b), 3.0);
+/// assert_eq!(f32::rem_euclid(-a, -b), 1.0);
+/// // limitation due to round-off error
+/// assert!(f32::rem_euclid(-f32::EPSILON, 3.0) != 0.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::rem_euclid`]: ../../std/primitive.f32.html#method.rem_euclid
+#[inline]
+#[doc(alias = "modulo", alias = "mod")]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn rem_euclid(x: f32, rhs: f32) -> f32 {
+    let r = x % rhs;
+    if r < 0.0 { r + rhs.abs() } else { r }
+}
+
+/// Experimental version of `powi` in `core`. See [`f32::powi`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let x = 2.0_f32;
+/// let abs_difference = (f32::powi(x, 2) - (x * x)).abs();
+/// assert!(abs_difference <= f32::EPSILON);
+///
+/// assert_eq!(f32::powi(f32::NAN, 0), 1.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::powi`]: ../../std/primitive.f32.html#method.powi
+#[inline]
+#[must_use = "method returns a new number and does not mutate the original value"]
+#[unstable(feature = "core_float_math", issue = "137578")]
+pub fn powi(x: f32, n: i32) -> f32 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::powif32(x, n) }
+}
+
+/// Experimental version of `sqrt` in `core`. See [`f32::sqrt`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let positive = 4.0_f32;
+/// let negative = -4.0_f32;
+/// let negative_zero = -0.0_f32;
+///
+/// assert_eq!(f32::sqrt(positive), 2.0);
+/// assert!(f32::sqrt(negative).is_nan());
+/// assert_eq!(f32::sqrt(negative_zero), negative_zero);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::sqrt`]: ../../std/primitive.f32.html#method.sqrt
+#[inline]
+#[doc(alias = "squareRoot")]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn sqrt(x: f32) -> f32 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::sqrtf32(x) }
+}
+
+/// Experimental version of `abs_sub` in `core`. See [`f32::abs_sub`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let x = 3.0f32;
+/// let y = -3.0f32;
+///
+/// let abs_difference_x = (f32::abs_sub(x, 1.0) - 2.0).abs();
+/// let abs_difference_y = (f32::abs_sub(y, 1.0) - 0.0).abs();
+///
+/// assert!(abs_difference_x <= f32::EPSILON);
+/// assert!(abs_difference_y <= f32::EPSILON);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::abs_sub`]: ../../std/primitive.f32.html#method.abs_sub
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(
+    since = "1.10.0",
+    note = "you probably meant `(self - other).abs()`: \
+            this operation is `(self - other).max(0.0)` \
+            except that `abs_sub` also propagates NaNs (also \
+            known as `fdimf` in C). If you truly need the positive \
+            difference, consider using that expression or the C function \
+            `fdimf`, depending on how you wish to handle NaN (please consider \
+            filing an issue describing your use-case too)."
+)]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn abs_sub(x: f32, other: f32) -> f32 {
+    libm::fdimf(x, other)
+}
+
+/// Experimental version of `cbrt` in `core`. See [`f32::cbrt`] for details.
+///
+/// # Unspecified precision
+///
+/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
+/// can even differ within the same execution from one invocation to the next.
+/// This function currently corresponds to the `cbrtf` from libc on Unix
+/// and Windows. Note that this might change in the future.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f32;
+///
+/// let x = 8.0f32;
+///
+/// // x^(1/3) - 2 == 0
+/// let abs_difference = (f32::cbrt(x) - 2.0).abs();
+///
+/// assert!(abs_difference <= f32::EPSILON);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f32::cbrt`]: ../../std/primitive.f32.html#method.cbrt
+#[inline]
+#[must_use = "method returns a new number and does not mutate the original value"]
+#[unstable(feature = "core_float_math", issue = "137578")]
+pub fn cbrt(x: f32) -> f32 {
+    libm::cbrtf(x)
+}
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 81ab0f14c2b..76c4e5d1a6f 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -12,7 +12,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::convert::FloatToInt;
-use crate::num::FpCategory;
+use crate::num::{FpCategory, libm};
 use crate::panic::const_assert;
 use crate::{intrinsics, mem};
 
@@ -1555,3 +1555,407 @@ impl f64 {
         intrinsics::frem_algebraic(self, rhs)
     }
 }
+
+/// Experimental version of `floor` in `core`. See [`f64::floor`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let f = 3.7_f64;
+/// let g = 3.0_f64;
+/// let h = -3.7_f64;
+///
+/// assert_eq!(f64::floor(f), 3.0);
+/// assert_eq!(f64::floor(g), 3.0);
+/// assert_eq!(f64::floor(h), -4.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::floor`]: ../../std/primitive.f64.html#method.floor
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn floor(x: f64) -> f64 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::floorf64(x) }
+}
+
+/// Experimental version of `ceil` in `core`. See [`f64::ceil`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let f = 3.01_f64;
+/// let g = 4.0_f64;
+///
+/// assert_eq!(f64::ceil(f), 4.0);
+/// assert_eq!(f64::ceil(g), 4.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::ceil`]: ../../std/primitive.f64.html#method.ceil
+#[inline]
+#[doc(alias = "ceiling")]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn ceil(x: f64) -> f64 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::ceilf64(x) }
+}
+
+/// Experimental version of `round` in `core`. See [`f64::round`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let f = 3.3_f64;
+/// let g = -3.3_f64;
+/// let h = -3.7_f64;
+/// let i = 3.5_f64;
+/// let j = 4.5_f64;
+///
+/// assert_eq!(f64::round(f), 3.0);
+/// assert_eq!(f64::round(g), -3.0);
+/// assert_eq!(f64::round(h), -4.0);
+/// assert_eq!(f64::round(i), 4.0);
+/// assert_eq!(f64::round(j), 5.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::round`]: ../../std/primitive.f64.html#method.round
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn round(x: f64) -> f64 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::roundf64(x) }
+}
+
+/// Experimental version of `round_ties_even` in `core`. See [`f64::round_ties_even`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let f = 3.3_f64;
+/// let g = -3.3_f64;
+/// let h = 3.5_f64;
+/// let i = 4.5_f64;
+///
+/// assert_eq!(f64::round_ties_even(f), 3.0);
+/// assert_eq!(f64::round_ties_even(g), -3.0);
+/// assert_eq!(f64::round_ties_even(h), 4.0);
+/// assert_eq!(f64::round_ties_even(i), 4.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::round_ties_even`]: ../../std/primitive.f64.html#method.round_ties_even
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn round_ties_even(x: f64) -> f64 {
+    intrinsics::round_ties_even_f64(x)
+}
+
+/// Experimental version of `trunc` in `core`. See [`f64::trunc`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let f = 3.7_f64;
+/// let g = 3.0_f64;
+/// let h = -3.7_f64;
+///
+/// assert_eq!(f64::trunc(f), 3.0);
+/// assert_eq!(f64::trunc(g), 3.0);
+/// assert_eq!(f64::trunc(h), -3.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::trunc`]: ../../std/primitive.f64.html#method.trunc
+#[inline]
+#[doc(alias = "truncate")]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn trunc(x: f64) -> f64 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::truncf64(x) }
+}
+
+/// Experimental version of `fract` in `core`. See [`f64::fract`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let x = 3.6_f64;
+/// let y = -3.6_f64;
+/// let abs_difference_x = (f64::fract(x) - 0.6).abs();
+/// let abs_difference_y = (f64::fract(y) - (-0.6)).abs();
+///
+/// assert!(abs_difference_x < 1e-10);
+/// assert!(abs_difference_y < 1e-10);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::fract`]: ../../std/primitive.f64.html#method.fract
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn fract(x: f64) -> f64 {
+    x - trunc(x)
+}
+
+/// Experimental version of `mul_add` in `core`. See [`f64::mul_add`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// # // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
+/// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
+/// use core::f64;
+///
+/// let m = 10.0_f64;
+/// let x = 4.0_f64;
+/// let b = 60.0_f64;
+///
+/// assert_eq!(f64::mul_add(m, x, b), 100.0);
+/// assert_eq!(m * x + b, 100.0);
+///
+/// let one_plus_eps = 1.0_f64 + f64::EPSILON;
+/// let one_minus_eps = 1.0_f64 - f64::EPSILON;
+/// let minus_one = -1.0_f64;
+///
+/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+/// assert_eq!(f64::mul_add(one_plus_eps, one_minus_eps, minus_one), -f64::EPSILON * f64::EPSILON);
+/// // Different rounding with the non-fused multiply and add.
+/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
+/// # }
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::mul_add`]: ../../std/primitive.f64.html#method.mul_add
+#[inline]
+#[doc(alias = "fma", alias = "fusedMultiplyAdd")]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn mul_add(x: f64, a: f64, b: f64) -> f64 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::fmaf64(x, a, b) }
+}
+
+/// Experimental version of `div_euclid` in `core`. See [`f64::div_euclid`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let a: f64 = 7.0;
+/// let b = 4.0;
+/// assert_eq!(f64::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
+/// assert_eq!(f64::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
+/// assert_eq!(f64::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
+/// assert_eq!(f64::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::div_euclid`]: ../../std/primitive.f64.html#method.div_euclid
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn div_euclid(x: f64, rhs: f64) -> f64 {
+    let q = trunc(x / rhs);
+    if x % rhs < 0.0 {
+        return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+    }
+    q
+}
+
+/// Experimental version of `rem_euclid` in `core`. See [`f64::rem_euclid`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let a: f64 = 7.0;
+/// let b = 4.0;
+/// assert_eq!(f64::rem_euclid(a, b), 3.0);
+/// assert_eq!(f64::rem_euclid(-a, b), 1.0);
+/// assert_eq!(f64::rem_euclid(a, -b), 3.0);
+/// assert_eq!(f64::rem_euclid(-a, -b), 1.0);
+/// // limitation due to round-off error
+/// assert!(f64::rem_euclid(-f64::EPSILON, 3.0) != 0.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::rem_euclid`]: ../../std/primitive.f64.html#method.rem_euclid
+#[inline]
+#[doc(alias = "modulo", alias = "mod")]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn rem_euclid(x: f64, rhs: f64) -> f64 {
+    let r = x % rhs;
+    if r < 0.0 { r + rhs.abs() } else { r }
+}
+
+/// Experimental version of `powi` in `core`. See [`f64::powi`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let x = 2.0_f64;
+/// let abs_difference = (f64::powi(x, 2) - (x * x)).abs();
+/// assert!(abs_difference <= f64::EPSILON);
+///
+/// assert_eq!(f64::powi(f64::NAN, 0), 1.0);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::powi`]: ../../std/primitive.f64.html#method.powi
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn powi(x: f64, n: i32) -> f64 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::powif64(x, n) }
+}
+
+/// Experimental version of `sqrt` in `core`. See [`f64::sqrt`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let positive = 4.0_f64;
+/// let negative = -4.0_f64;
+/// let negative_zero = -0.0_f64;
+///
+/// assert_eq!(f64::sqrt(positive), 2.0);
+/// assert!(f64::sqrt(negative).is_nan());
+/// assert_eq!(f64::sqrt(negative_zero), negative_zero);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::sqrt`]: ../../std/primitive.f64.html#method.sqrt
+#[inline]
+#[doc(alias = "squareRoot")]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn sqrt(x: f64) -> f64 {
+    // SAFETY: intrinsic with no preconditions
+    unsafe { intrinsics::sqrtf64(x) }
+}
+
+/// Experimental version of `abs_sub` in `core`. See [`f64::abs_sub`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let x = 3.0_f64;
+/// let y = -3.0_f64;
+///
+/// let abs_difference_x = (f64::abs_sub(x, 1.0) - 2.0).abs();
+/// let abs_difference_y = (f64::abs_sub(y, 1.0) - 0.0).abs();
+///
+/// assert!(abs_difference_x < 1e-10);
+/// assert!(abs_difference_y < 1e-10);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::abs_sub`]: ../../std/primitive.f64.html#method.abs_sub
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[deprecated(
+    since = "1.10.0",
+    note = "you probably meant `(self - other).abs()`: \
+                this operation is `(self - other).max(0.0)` \
+                except that `abs_sub` also propagates NaNs (also \
+                known as `fdim` in C). If you truly need the positive \
+                difference, consider using that expression or the C function \
+                `fdim`, depending on how you wish to handle NaN (please consider \
+                filing an issue describing your use-case too)."
+)]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn abs_sub(x: f64, other: f64) -> f64 {
+    libm::fdim(x, other)
+}
+
+/// Experimental version of `cbrt` in `core`. See [`f64::cbrt`] for details.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_float_math)]
+///
+/// use core::f64;
+///
+/// let x = 8.0_f64;
+///
+/// // x^(1/3) - 2 == 0
+/// let abs_difference = (f64::cbrt(x) - 2.0).abs();
+///
+/// assert!(abs_difference < 1e-10);
+/// ```
+///
+/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+///
+/// [`f64::cbrt`]: ../../std/primitive.f64.html#method.cbrt
+#[inline]
+#[unstable(feature = "core_float_math", issue = "137578")]
+#[must_use = "method returns a new number and does not mutate the original value"]
+pub fn cbrt(x: f64) -> f64 {
+    libm::cbrt(x)
+}
diff --git a/library/core/src/num/flt2dec/decoder.rs b/library/core/src/num/flt2dec/decoder.rs
index 40b3aae24a5..bd6e2cdbafe 100644
--- a/library/core/src/num/flt2dec/decoder.rs
+++ b/library/core/src/num/flt2dec/decoder.rs
@@ -45,6 +45,13 @@ pub trait DecodableFloat: RawFloat + Copy {
     fn min_pos_norm_value() -> Self;
 }
 
+#[cfg(target_has_reliable_f16)]
+impl DecodableFloat for f16 {
+    fn min_pos_norm_value() -> Self {
+        f16::MIN_POSITIVE
+    }
+}
+
 impl DecodableFloat for f32 {
     fn min_pos_norm_value() -> Self {
         f32::MIN_POSITIVE
diff --git a/library/core/src/num/libm.rs b/library/core/src/num/libm.rs
new file mode 100644
index 00000000000..aeabb087230
--- /dev/null
+++ b/library/core/src/num/libm.rs
@@ -0,0 +1,11 @@
+//! Bindings to math functions provided by the system `libm` or by the `libm` crate, exposed
+//! via `compiler-builtins`.
+
+// SAFETY: These symbols have standard interfaces in C and are defined by `libm`, or are
+// provided by `compiler-builtins` on unsupported platforms.
+unsafe extern "C" {
+    pub(crate) safe fn cbrt(n: f64) -> f64;
+    pub(crate) safe fn cbrtf(n: f32) -> f32;
+    pub(crate) safe fn fdim(a: f64, b: f64) -> f64;
+    pub(crate) safe fn fdimf(a: f32, b: f32) -> f32;
+}
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index ecc1c7bf902..5c73bddbef2 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -46,6 +46,7 @@ mod uint_macros; // import uint_impl!
 mod error;
 mod int_log10;
 mod int_sqrt;
+pub(crate) mod libm;
 mod nonzero;
 mod overflow_panic;
 mod saturating;
@@ -492,6 +493,26 @@ impl u8 {
         ascii::Char::from_u8(*self)
     }
 
+    /// Converts this byte to an [ASCII character](ascii::Char), without
+    /// checking whether or not it's valid.
+    ///
+    /// # Safety
+    ///
+    /// This byte must be valid ASCII, or else this is UB.
+    #[must_use]
+    #[unstable(feature = "ascii_char", issue = "110998")]
+    #[inline]
+    pub const unsafe fn as_ascii_unchecked(&self) -> ascii::Char {
+        assert_unsafe_precondition!(
+            check_library_ub,
+            "as_ascii_unchecked requires that the byte is valid ASCII",
+            (it: &u8 = self) => it.is_ascii()
+        );
+
+        // SAFETY: the caller promised that this byte is ASCII.
+        unsafe { ascii::Char::from_u8_unchecked(*self) }
+    }
+
     /// Makes a copy of the value in its ASCII upper case equivalent.
     ///
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index ecfa723722d..257424b355f 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -12,11 +12,11 @@
 //! "pinned," in that it has been permanently (until the end of its lifespan) attached to its
 //! location in memory, as though pinned to a pinboard. Pinning a value is an incredibly useful
 //! building block for [`unsafe`] code to be able to reason about whether a raw pointer to the
-//! pinned value is still valid. [As we'll see later][drop-guarantee], this is necessarily from the
-//! time the value is first pinned until the end of its lifespan. This concept of "pinning" is
-//! necessary to implement safe interfaces on top of things like self-referential types and
-//! intrusive data structures which cannot currently be modeled in fully safe Rust using only
-//! borrow-checked [references][reference].
+//! pinned value is still valid. [As we'll see later][drop-guarantee], once a value is pinned,
+//! it is necessarily valid at its memory location until the end of its lifespan. This concept
+//! of "pinning" is necessary to implement safe interfaces on top of things like self-referential
+//! types and intrusive data structures which cannot currently be modeled in fully safe Rust using
+//! only borrow-checked [references][reference].
 //!
 //! "Pinning" allows us to put a *value* which exists at some location in memory into a state where
 //! safe code cannot *move* that value to a different location in memory or otherwise invalidate it
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index d05fb6a6d31..8b31328de04 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -262,7 +262,8 @@ impl<T: ?Sized> NonNull<T> {
     }
 
     /// Converts a reference to a `NonNull` pointer.
-    #[unstable(feature = "non_null_from_ref", issue = "130823")]
+    #[stable(feature = "non_null_from_ref", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "non_null_from_ref", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn from_ref(r: &T) -> Self {
         // SAFETY: A reference cannot be null.
@@ -270,7 +271,8 @@ impl<T: ?Sized> NonNull<T> {
     }
 
     /// Converts a mutable reference to a `NonNull` pointer.
-    #[unstable(feature = "non_null_from_ref", issue = "130823")]
+    #[stable(feature = "non_null_from_ref", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "non_null_from_ref", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn from_mut(r: &mut T) -> Self {
         // SAFETY: A mutable reference cannot be null.
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 9e7e949b722..e505e228095 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -17,6 +17,7 @@ use self::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};
 use crate::char::{self, EscapeDebugExtArgs};
 use crate::ops::Range;
 use crate::slice::{self, SliceIndex};
+use crate::ub_checks::assert_unsafe_precondition;
 use crate::{ascii, mem};
 
 pub mod pattern;
@@ -2634,6 +2635,27 @@ impl str {
         self.as_bytes().as_ascii()
     }
 
+    /// Converts this string slice into a slice of [ASCII characters](ascii::Char),
+    /// without checking whether they are valid.
+    ///
+    /// # Safety
+    ///
+    /// Every character in this string must be ASCII, or else this is UB.
+    #[unstable(feature = "ascii_char", issue = "110998")]
+    #[must_use]
+    #[inline]
+    pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char] {
+        assert_unsafe_precondition!(
+            check_library_ub,
+            "as_ascii_unchecked requires that the string is valid ASCII",
+            (it: &str = self) => it.is_ascii()
+        );
+
+        // SAFETY: the caller promised that every byte of this string slice
+        // is ASCII.
+        unsafe { self.as_bytes().as_ascii_unchecked() }
+    }
+
     /// Checks that two strings are an ASCII case-insensitive match.
     ///
     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
diff --git a/library/coretests/Cargo.toml b/library/coretests/Cargo.toml
index 7656388d24b..e0ddcd466ae 100644
--- a/library/coretests/Cargo.toml
+++ b/library/coretests/Cargo.toml
@@ -26,3 +26,14 @@ test = true
 [dev-dependencies]
 rand = { version = "0.9.0", default-features = false }
 rand_xorshift = { version = "0.4.0", default-features = false }
+
+[lints.rust.unexpected_cfgs]
+level = "warn"
+check-cfg = [
+    # Internal features aren't marked known config by default, we use these to
+    # gate tests.
+    'cfg(target_has_reliable_f16)',
+    'cfg(target_has_reliable_f16_math)',
+    'cfg(target_has_reliable_f128)',
+    'cfg(target_has_reliable_f128_math)',
+]
diff --git a/library/coretests/tests/array.rs b/library/coretests/tests/array.rs
index b6d18f1ec38..30ccbbc3203 100644
--- a/library/coretests/tests/array.rs
+++ b/library/coretests/tests/array.rs
@@ -325,7 +325,7 @@ fn array_map_drop_safety() {
     let success = std::panic::catch_unwind(|| {
         let items = [0; 10];
         let mut nth = 0;
-        items.map(|_| {
+        let _ = items.map(|_| {
             assert!(nth < num_to_create);
             nth += 1;
             DropCounter
diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs
new file mode 100644
index 00000000000..12cf651f03f
--- /dev/null
+++ b/library/coretests/tests/floats/f128.rs
@@ -0,0 +1,790 @@
+// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
+#![cfg(target_has_reliable_f128)]
+
+use std::f128::consts;
+use std::num::FpCategory as Fp;
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+use std::ops::Rem;
+use std::ops::{Add, Div, Mul, Sub};
+
+// Note these tolerances make sense around zero, but not for more extreme exponents.
+
+/// Default tolerances. Works for values that should be near precise but not exact. Roughly
+/// the precision carried by `100 * 100`.
+const TOL: f128 = 1e-12;
+
+/// For operations that are near exact, usually not involving math of different
+/// signs.
+const TOL_PRECISE: f128 = 1e-28;
+
+/// Smallest number
+const TINY_BITS: u128 = 0x1;
+
+/// Next smallest number
+const TINY_UP_BITS: u128 = 0x2;
+
+/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
+const MAX_DOWN_BITS: u128 = 0x7ffefffffffffffffffffffffffffffe;
+
+/// Zeroed exponent, full significant
+const LARGEST_SUBNORMAL_BITS: u128 = 0x0000ffffffffffffffffffffffffffff;
+
+/// Exponent = 0b1, zeroed significand
+const SMALLEST_NORMAL_BITS: u128 = 0x00010000000000000000000000000000;
+
+/// First pattern over the mantissa
+const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
+
+/// Second pattern over the mantissa
+const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
+
+/// Compare by representation
+#[allow(unused_macros)]
+macro_rules! assert_f128_biteq {
+    ($a:expr, $b:expr) => {
+        let (l, r): (&f128, &f128) = (&$a, &$b);
+        let lb = l.to_bits();
+        let rb = r.to_bits();
+        assert_eq!(lb, rb, "float {l:?} is not bitequal to {r:?}.\na: {lb:#034x}\nb: {rb:#034x}");
+    };
+}
+
+#[test]
+fn test_num_f128() {
+    // FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128`
+    // function is available on all platforms.
+    let ten = 10f128;
+    let two = 2f128;
+    assert_eq!(ten.add(two), ten + two);
+    assert_eq!(ten.sub(two), ten - two);
+    assert_eq!(ten.mul(two), ten * two);
+    assert_eq!(ten.div(two), ten / two);
+}
+
+// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
+// the intrinsics.
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_num_f128_rem() {
+    let ten = 10f128;
+    let two = 2f128;
+    assert_eq!(ten.rem(two), ten % two);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_min_nan() {
+    assert_eq!(f128::NAN.min(2.0), 2.0);
+    assert_eq!(2.0f128.min(f128::NAN), 2.0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_max_nan() {
+    assert_eq!(f128::NAN.max(2.0), 2.0);
+    assert_eq!(2.0f128.max(f128::NAN), 2.0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_minimum() {
+    assert!(f128::NAN.minimum(2.0).is_nan());
+    assert!(2.0f128.minimum(f128::NAN).is_nan());
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_maximum() {
+    assert!(f128::NAN.maximum(2.0).is_nan());
+    assert!(2.0f128.maximum(f128::NAN).is_nan());
+}
+
+#[test]
+fn test_nan() {
+    let nan: f128 = f128::NAN;
+    assert!(nan.is_nan());
+    assert!(!nan.is_infinite());
+    assert!(!nan.is_finite());
+    assert!(nan.is_sign_positive());
+    assert!(!nan.is_sign_negative());
+    assert!(!nan.is_normal());
+    assert_eq!(Fp::Nan, nan.classify());
+    // Ensure the quiet bit is set.
+    assert!(nan.to_bits() & (1 << (f128::MANTISSA_DIGITS - 2)) != 0);
+}
+
+#[test]
+fn test_infinity() {
+    let inf: f128 = f128::INFINITY;
+    assert!(inf.is_infinite());
+    assert!(!inf.is_finite());
+    assert!(inf.is_sign_positive());
+    assert!(!inf.is_sign_negative());
+    assert!(!inf.is_nan());
+    assert!(!inf.is_normal());
+    assert_eq!(Fp::Infinite, inf.classify());
+}
+
+#[test]
+fn test_neg_infinity() {
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert!(neg_inf.is_infinite());
+    assert!(!neg_inf.is_finite());
+    assert!(!neg_inf.is_sign_positive());
+    assert!(neg_inf.is_sign_negative());
+    assert!(!neg_inf.is_nan());
+    assert!(!neg_inf.is_normal());
+    assert_eq!(Fp::Infinite, neg_inf.classify());
+}
+
+#[test]
+fn test_zero() {
+    let zero: f128 = 0.0f128;
+    assert_eq!(0.0, zero);
+    assert!(!zero.is_infinite());
+    assert!(zero.is_finite());
+    assert!(zero.is_sign_positive());
+    assert!(!zero.is_sign_negative());
+    assert!(!zero.is_nan());
+    assert!(!zero.is_normal());
+    assert_eq!(Fp::Zero, zero.classify());
+}
+
+#[test]
+fn test_neg_zero() {
+    let neg_zero: f128 = -0.0;
+    assert_eq!(0.0, neg_zero);
+    assert!(!neg_zero.is_infinite());
+    assert!(neg_zero.is_finite());
+    assert!(!neg_zero.is_sign_positive());
+    assert!(neg_zero.is_sign_negative());
+    assert!(!neg_zero.is_nan());
+    assert!(!neg_zero.is_normal());
+    assert_eq!(Fp::Zero, neg_zero.classify());
+}
+
+#[test]
+fn test_one() {
+    let one: f128 = 1.0f128;
+    assert_eq!(1.0, one);
+    assert!(!one.is_infinite());
+    assert!(one.is_finite());
+    assert!(one.is_sign_positive());
+    assert!(!one.is_sign_negative());
+    assert!(!one.is_nan());
+    assert!(one.is_normal());
+    assert_eq!(Fp::Normal, one.classify());
+}
+
+#[test]
+fn test_is_nan() {
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert!(nan.is_nan());
+    assert!(!0.0f128.is_nan());
+    assert!(!5.3f128.is_nan());
+    assert!(!(-10.732f128).is_nan());
+    assert!(!inf.is_nan());
+    assert!(!neg_inf.is_nan());
+}
+
+#[test]
+fn test_is_infinite() {
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert!(!nan.is_infinite());
+    assert!(inf.is_infinite());
+    assert!(neg_inf.is_infinite());
+    assert!(!0.0f128.is_infinite());
+    assert!(!42.8f128.is_infinite());
+    assert!(!(-109.2f128).is_infinite());
+}
+
+#[test]
+fn test_is_finite() {
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert!(!nan.is_finite());
+    assert!(!inf.is_finite());
+    assert!(!neg_inf.is_finite());
+    assert!(0.0f128.is_finite());
+    assert!(42.8f128.is_finite());
+    assert!((-109.2f128).is_finite());
+}
+
+#[test]
+fn test_is_normal() {
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    let zero: f128 = 0.0f128;
+    let neg_zero: f128 = -0.0;
+    assert!(!nan.is_normal());
+    assert!(!inf.is_normal());
+    assert!(!neg_inf.is_normal());
+    assert!(!zero.is_normal());
+    assert!(!neg_zero.is_normal());
+    assert!(1f128.is_normal());
+    assert!(1e-4931f128.is_normal());
+    assert!(!1e-4932f128.is_normal());
+}
+
+#[test]
+fn test_classify() {
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    let zero: f128 = 0.0f128;
+    let neg_zero: f128 = -0.0;
+    assert_eq!(nan.classify(), Fp::Nan);
+    assert_eq!(inf.classify(), Fp::Infinite);
+    assert_eq!(neg_inf.classify(), Fp::Infinite);
+    assert_eq!(zero.classify(), Fp::Zero);
+    assert_eq!(neg_zero.classify(), Fp::Zero);
+    assert_eq!(1f128.classify(), Fp::Normal);
+    assert_eq!(1e-4931f128.classify(), Fp::Normal);
+    assert_eq!(1e-4932f128.classify(), Fp::Subnormal);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_floor() {
+    assert_approx_eq!(1.0f128.floor(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.3f128.floor(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.5f128.floor(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.7f128.floor(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(0.0f128.floor(), 0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-0.0f128).floor(), -0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.0f128).floor(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.3f128).floor(), -2.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.5f128).floor(), -2.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.7f128).floor(), -2.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_ceil() {
+    assert_approx_eq!(1.0f128.ceil(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.3f128.ceil(), 2.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.5f128.ceil(), 2.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.7f128.ceil(), 2.0f128, TOL_PRECISE);
+    assert_approx_eq!(0.0f128.ceil(), 0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-0.0f128).ceil(), -0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.0f128).ceil(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.3f128).ceil(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.5f128).ceil(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.7f128).ceil(), -1.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_round() {
+    assert_approx_eq!(2.5f128.round(), 3.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.0f128.round(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.3f128.round(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.5f128.round(), 2.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.7f128.round(), 2.0f128, TOL_PRECISE);
+    assert_approx_eq!(0.0f128.round(), 0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-0.0f128).round(), -0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.0f128).round(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.3f128).round(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.5f128).round(), -2.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.7f128).round(), -2.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_round_ties_even() {
+    assert_approx_eq!(2.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.0f128.round_ties_even(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.3f128.round_ties_even(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.7f128.round_ties_even(), 2.0f128, TOL_PRECISE);
+    assert_approx_eq!(0.0f128.round_ties_even(), 0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-0.0f128).round_ties_even(), -0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.0f128).round_ties_even(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.3f128).round_ties_even(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.5f128).round_ties_even(), -2.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.7f128).round_ties_even(), -2.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_trunc() {
+    assert_approx_eq!(1.0f128.trunc(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.3f128.trunc(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.5f128.trunc(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.7f128.trunc(), 1.0f128, TOL_PRECISE);
+    assert_approx_eq!(0.0f128.trunc(), 0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-0.0f128).trunc(), -0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.0f128).trunc(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.3f128).trunc(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.5f128).trunc(), -1.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.7f128).trunc(), -1.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_fract() {
+    assert_approx_eq!(1.0f128.fract(), 0.0f128, TOL_PRECISE);
+    assert_approx_eq!(1.3f128.fract(), 0.3f128, TOL_PRECISE);
+    assert_approx_eq!(1.5f128.fract(), 0.5f128, TOL_PRECISE);
+    assert_approx_eq!(1.7f128.fract(), 0.7f128, TOL_PRECISE);
+    assert_approx_eq!(0.0f128.fract(), 0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-0.0f128).fract(), -0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.0f128).fract(), -0.0f128, TOL_PRECISE);
+    assert_approx_eq!((-1.3f128).fract(), -0.3f128, TOL_PRECISE);
+    assert_approx_eq!((-1.5f128).fract(), -0.5f128, TOL_PRECISE);
+    assert_approx_eq!((-1.7f128).fract(), -0.7f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_abs() {
+    assert_eq!(f128::INFINITY.abs(), f128::INFINITY);
+    assert_eq!(1f128.abs(), 1f128);
+    assert_eq!(0f128.abs(), 0f128);
+    assert_eq!((-0f128).abs(), 0f128);
+    assert_eq!((-1f128).abs(), 1f128);
+    assert_eq!(f128::NEG_INFINITY.abs(), f128::INFINITY);
+    assert_eq!((1f128 / f128::NEG_INFINITY).abs(), 0f128);
+    assert!(f128::NAN.abs().is_nan());
+}
+
+#[test]
+fn test_is_sign_positive() {
+    assert!(f128::INFINITY.is_sign_positive());
+    assert!(1f128.is_sign_positive());
+    assert!(0f128.is_sign_positive());
+    assert!(!(-0f128).is_sign_positive());
+    assert!(!(-1f128).is_sign_positive());
+    assert!(!f128::NEG_INFINITY.is_sign_positive());
+    assert!(!(1f128 / f128::NEG_INFINITY).is_sign_positive());
+    assert!(f128::NAN.is_sign_positive());
+    assert!(!(-f128::NAN).is_sign_positive());
+}
+
+#[test]
+fn test_is_sign_negative() {
+    assert!(!f128::INFINITY.is_sign_negative());
+    assert!(!1f128.is_sign_negative());
+    assert!(!0f128.is_sign_negative());
+    assert!((-0f128).is_sign_negative());
+    assert!((-1f128).is_sign_negative());
+    assert!(f128::NEG_INFINITY.is_sign_negative());
+    assert!((1f128 / f128::NEG_INFINITY).is_sign_negative());
+    assert!(!f128::NAN.is_sign_negative());
+    assert!((-f128::NAN).is_sign_negative());
+}
+
+#[test]
+fn test_next_up() {
+    let tiny = f128::from_bits(TINY_BITS);
+    let tiny_up = f128::from_bits(TINY_UP_BITS);
+    let max_down = f128::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
+    assert_f128_biteq!(f128::NEG_INFINITY.next_up(), f128::MIN);
+    assert_f128_biteq!(f128::MIN.next_up(), -max_down);
+    assert_f128_biteq!((-1.0 - f128::EPSILON).next_up(), -1.0);
+    assert_f128_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_f128_biteq!((-tiny_up).next_up(), -tiny);
+    assert_f128_biteq!((-tiny).next_up(), -0.0f128);
+    assert_f128_biteq!((-0.0f128).next_up(), tiny);
+    assert_f128_biteq!(0.0f128.next_up(), tiny);
+    assert_f128_biteq!(tiny.next_up(), tiny_up);
+    assert_f128_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_f128_biteq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
+    assert_f128_biteq!(f128::MAX.next_up(), f128::INFINITY);
+    assert_f128_biteq!(f128::INFINITY.next_up(), f128::INFINITY);
+
+    // Check that NaNs roundtrip.
+    let nan0 = f128::NAN;
+    let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
+    let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
+    assert_f128_biteq!(nan0.next_up(), nan0);
+    assert_f128_biteq!(nan1.next_up(), nan1);
+    assert_f128_biteq!(nan2.next_up(), nan2);
+}
+
+#[test]
+fn test_next_down() {
+    let tiny = f128::from_bits(TINY_BITS);
+    let tiny_up = f128::from_bits(TINY_UP_BITS);
+    let max_down = f128::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
+    assert_f128_biteq!(f128::NEG_INFINITY.next_down(), f128::NEG_INFINITY);
+    assert_f128_biteq!(f128::MIN.next_down(), f128::NEG_INFINITY);
+    assert_f128_biteq!((-max_down).next_down(), f128::MIN);
+    assert_f128_biteq!((-1.0f128).next_down(), -1.0 - f128::EPSILON);
+    assert_f128_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_f128_biteq!((-tiny).next_down(), -tiny_up);
+    assert_f128_biteq!((-0.0f128).next_down(), -tiny);
+    assert_f128_biteq!((0.0f128).next_down(), -tiny);
+    assert_f128_biteq!(tiny.next_down(), 0.0f128);
+    assert_f128_biteq!(tiny_up.next_down(), tiny);
+    assert_f128_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_f128_biteq!((1.0 + f128::EPSILON).next_down(), 1.0f128);
+    assert_f128_biteq!(f128::MAX.next_down(), max_down);
+    assert_f128_biteq!(f128::INFINITY.next_down(), f128::MAX);
+
+    // Check that NaNs roundtrip.
+    let nan0 = f128::NAN;
+    let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
+    let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
+    assert_f128_biteq!(nan0.next_down(), nan0);
+    assert_f128_biteq!(nan1.next_down(), nan1);
+    assert_f128_biteq!(nan2.next_down(), nan2);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_mul_add() {
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert_approx_eq!(12.3f128.mul_add(4.5, 6.7), 62.05, TOL_PRECISE);
+    assert_approx_eq!((-12.3f128).mul_add(-4.5, -6.7), 48.65, TOL_PRECISE);
+    assert_approx_eq!(0.0f128.mul_add(8.9, 1.2), 1.2, TOL_PRECISE);
+    assert_approx_eq!(3.4f128.mul_add(-0.0, 5.6), 5.6, TOL_PRECISE);
+    assert!(nan.mul_add(7.8, 9.0).is_nan());
+    assert_eq!(inf.mul_add(7.8, 9.0), inf);
+    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_eq!(8.9f128.mul_add(inf, 3.2), inf);
+    assert_eq!((-3.2f128).mul_add(2.4, neg_inf), neg_inf);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_recip() {
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert_eq!(1.0f128.recip(), 1.0);
+    assert_eq!(2.0f128.recip(), 0.5);
+    assert_eq!((-0.4f128).recip(), -2.5);
+    assert_eq!(0.0f128.recip(), inf);
+    assert_approx_eq!(
+        f128::MAX.recip(),
+        8.40525785778023376565669454330438228902076605e-4933,
+        1e-4900
+    );
+    assert!(nan.recip().is_nan());
+    assert_eq!(inf.recip(), 0.0);
+    assert_eq!(neg_inf.recip(), 0.0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_powi() {
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert_eq!(1.0f128.powi(1), 1.0);
+    assert_approx_eq!((-3.1f128).powi(2), 9.6100000000000005506706202140776519387, TOL);
+    assert_approx_eq!(5.9f128.powi(-2), 0.028727377190462507313100483690639638451, TOL);
+    assert_eq!(8.3f128.powi(0), 1.0);
+    assert!(nan.powi(2).is_nan());
+    assert_eq!(inf.powi(3), inf);
+    assert_eq!(neg_inf.powi(2), inf);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
+fn test_sqrt_domain() {
+    assert!(f128::NAN.sqrt().is_nan());
+    assert!(f128::NEG_INFINITY.sqrt().is_nan());
+    assert!((-1.0f128).sqrt().is_nan());
+    assert_eq!((-0.0f128).sqrt(), -0.0);
+    assert_eq!(0.0f128.sqrt(), 0.0);
+    assert_eq!(1.0f128.sqrt(), 1.0);
+    assert_eq!(f128::INFINITY.sqrt(), f128::INFINITY);
+}
+
+#[test]
+fn test_to_degrees() {
+    let pi: f128 = consts::PI;
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert_eq!(0.0f128.to_degrees(), 0.0);
+    assert_approx_eq!((-5.8f128).to_degrees(), -332.31552117587745090765431723855668471, TOL);
+    assert_approx_eq!(pi.to_degrees(), 180.0, TOL);
+    assert!(nan.to_degrees().is_nan());
+    assert_eq!(inf.to_degrees(), inf);
+    assert_eq!(neg_inf.to_degrees(), neg_inf);
+    assert_eq!(1_f128.to_degrees(), 57.2957795130823208767981548141051703);
+}
+
+#[test]
+fn test_to_radians() {
+    let pi: f128 = consts::PI;
+    let nan: f128 = f128::NAN;
+    let inf: f128 = f128::INFINITY;
+    let neg_inf: f128 = f128::NEG_INFINITY;
+    assert_eq!(0.0f128.to_radians(), 0.0);
+    assert_approx_eq!(154.6f128.to_radians(), 2.6982790235832334267135442069489767804, TOL);
+    assert_approx_eq!((-332.31f128).to_radians(), -5.7999036373023566567593094812182763013, TOL);
+    // check approx rather than exact because round trip for pi doesn't fall on an exactly
+    // representable value (unlike `f32` and `f64`).
+    assert_approx_eq!(180.0f128.to_radians(), pi, TOL_PRECISE);
+    assert!(nan.to_radians().is_nan());
+    assert_eq!(inf.to_radians(), inf);
+    assert_eq!(neg_inf.to_radians(), neg_inf);
+}
+
+#[test]
+fn test_float_bits_conv() {
+    assert_eq!((1f128).to_bits(), 0x3fff0000000000000000000000000000);
+    assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
+    assert_eq!((1337f128).to_bits(), 0x40094e40000000000000000000000000);
+    assert_eq!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000);
+    assert_approx_eq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0, TOL_PRECISE);
+    assert_approx_eq!(f128::from_bits(0x40029000000000000000000000000000), 12.5, TOL_PRECISE);
+    assert_approx_eq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0, TOL_PRECISE);
+    assert_approx_eq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25, TOL_PRECISE);
+
+    // Check that NaNs roundtrip their bits regardless of signaling-ness
+    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+    let masked_nan1 = f128::NAN.to_bits() ^ NAN_MASK1;
+    let masked_nan2 = f128::NAN.to_bits() ^ NAN_MASK2;
+    assert!(f128::from_bits(masked_nan1).is_nan());
+    assert!(f128::from_bits(masked_nan2).is_nan());
+
+    assert_eq!(f128::from_bits(masked_nan1).to_bits(), masked_nan1);
+    assert_eq!(f128::from_bits(masked_nan2).to_bits(), masked_nan2);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_min_greater_than_max() {
+    let _ = 1.0f128.clamp(3.0, 1.0);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_min_is_nan() {
+    let _ = 1.0f128.clamp(f128::NAN, 1.0);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_max_is_nan() {
+    let _ = 1.0f128.clamp(3.0, f128::NAN);
+}
+
+#[test]
+fn test_total_cmp() {
+    use core::cmp::Ordering;
+
+    fn quiet_bit_mask() -> u128 {
+        1 << (f128::MANTISSA_DIGITS - 2)
+    }
+
+    // FIXME(f16_f128): test subnormals when powf is available
+    // fn min_subnorm() -> f128 {
+    //     f128::MIN_POSITIVE / f128::powf(2.0, f128::MANTISSA_DIGITS as f128 - 1.0)
+    // }
+
+    // fn max_subnorm() -> f128 {
+    //     f128::MIN_POSITIVE - min_subnorm()
+    // }
+
+    fn q_nan() -> f128 {
+        f128::from_bits(f128::NAN.to_bits() | quiet_bit_mask())
+    }
+
+    fn s_nan() -> f128 {
+        f128::from_bits((f128::NAN.to_bits() & !quiet_bit_mask()) + 42)
+    }
+
+    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
+    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Equal, (-f128::INFINITY).total_cmp(&-f128::INFINITY));
+    assert_eq!(Ordering::Equal, (-f128::MAX).total_cmp(&-f128::MAX));
+    assert_eq!(Ordering::Equal, (-2.5_f128).total_cmp(&-2.5));
+    assert_eq!(Ordering::Equal, (-1.0_f128).total_cmp(&-1.0));
+    assert_eq!(Ordering::Equal, (-1.5_f128).total_cmp(&-1.5));
+    assert_eq!(Ordering::Equal, (-0.5_f128).total_cmp(&-0.5));
+    assert_eq!(Ordering::Equal, (-f128::MIN_POSITIVE).total_cmp(&-f128::MIN_POSITIVE));
+    // assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
+    // assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Equal, (-0.0_f128).total_cmp(&-0.0));
+    assert_eq!(Ordering::Equal, 0.0_f128.total_cmp(&0.0));
+    // assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
+    // assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Equal, f128::MIN_POSITIVE.total_cmp(&f128::MIN_POSITIVE));
+    assert_eq!(Ordering::Equal, 0.5_f128.total_cmp(&0.5));
+    assert_eq!(Ordering::Equal, 1.0_f128.total_cmp(&1.0));
+    assert_eq!(Ordering::Equal, 1.5_f128.total_cmp(&1.5));
+    assert_eq!(Ordering::Equal, 2.5_f128.total_cmp(&2.5));
+    assert_eq!(Ordering::Equal, f128::MAX.total_cmp(&f128::MAX));
+    assert_eq!(Ordering::Equal, f128::INFINITY.total_cmp(&f128::INFINITY));
+    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
+    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
+
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::INFINITY));
+    assert_eq!(Ordering::Less, (-f128::INFINITY).total_cmp(&-f128::MAX));
+    assert_eq!(Ordering::Less, (-f128::MAX).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-2.5_f128).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-1.5_f128).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-1.0_f128).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-0.5_f128).total_cmp(&-f128::MIN_POSITIVE));
+    // assert_eq!(Ordering::Less, (-f128::MIN_POSITIVE).total_cmp(&-max_subnorm()));
+    // assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
+    // assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-0.0_f128).total_cmp(&0.0));
+    // assert_eq!(Ordering::Less, 0.0_f128.total_cmp(&min_subnorm()));
+    // assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
+    // assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f128::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, f128::MIN_POSITIVE.total_cmp(&0.5));
+    assert_eq!(Ordering::Less, 0.5_f128.total_cmp(&1.0));
+    assert_eq!(Ordering::Less, 1.0_f128.total_cmp(&1.5));
+    assert_eq!(Ordering::Less, 1.5_f128.total_cmp(&2.5));
+    assert_eq!(Ordering::Less, 2.5_f128.total_cmp(&f128::MAX));
+    assert_eq!(Ordering::Less, f128::MAX.total_cmp(&f128::INFINITY));
+    assert_eq!(Ordering::Less, f128::INFINITY.total_cmp(&s_nan()));
+    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
+
+    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
+    assert_eq!(Ordering::Greater, (-f128::INFINITY).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Greater, (-f128::MAX).total_cmp(&-f128::INFINITY));
+    assert_eq!(Ordering::Greater, (-2.5_f128).total_cmp(&-f128::MAX));
+    assert_eq!(Ordering::Greater, (-1.5_f128).total_cmp(&-2.5));
+    assert_eq!(Ordering::Greater, (-1.0_f128).total_cmp(&-1.5));
+    assert_eq!(Ordering::Greater, (-0.5_f128).total_cmp(&-1.0));
+    assert_eq!(Ordering::Greater, (-f128::MIN_POSITIVE).total_cmp(&-0.5));
+    // assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f128::MIN_POSITIVE));
+    // assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
+    // assert_eq!(Ordering::Greater, (-0.0_f128).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Greater, 0.0_f128.total_cmp(&-0.0));
+    // assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
+    // assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
+    // assert_eq!(Ordering::Greater, f128::MIN_POSITIVE.total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Greater, 0.5_f128.total_cmp(&f128::MIN_POSITIVE));
+    assert_eq!(Ordering::Greater, 1.0_f128.total_cmp(&0.5));
+    assert_eq!(Ordering::Greater, 1.5_f128.total_cmp(&1.0));
+    assert_eq!(Ordering::Greater, 2.5_f128.total_cmp(&1.5));
+    assert_eq!(Ordering::Greater, f128::MAX.total_cmp(&2.5));
+    assert_eq!(Ordering::Greater, f128::INFINITY.total_cmp(&f128::MAX));
+    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f128::INFINITY));
+    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
+
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::INFINITY));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::MAX));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::MIN_POSITIVE));
+    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
+    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
+    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
+    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::MAX));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::INFINITY));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
+
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::INFINITY));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::MAX));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::MIN_POSITIVE));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
+    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::MAX));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::INFINITY));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
+}
+
+#[test]
+fn test_algebraic() {
+    let a: f128 = 123.0;
+    let b: f128 = 456.0;
+
+    // Check that individual operations match their primitive counterparts.
+    //
+    // This is a check of current implementations and does NOT imply any form of
+    // guarantee about future behavior. The compiler reserves the right to make
+    // these operations inexact matches in the future.
+    let eps = if cfg!(miri) { 1e-6 } else { 0.0 };
+
+    assert_approx_eq!(a.algebraic_add(b), a + b, eps);
+    assert_approx_eq!(a.algebraic_sub(b), a - b, eps);
+    assert_approx_eq!(a.algebraic_mul(b), a * b, eps);
+    assert_approx_eq!(a.algebraic_div(b), a / b, eps);
+    assert_approx_eq!(a.algebraic_rem(b), a % b, eps);
+}
+
+#[test]
+fn test_from() {
+    assert_eq!(f128::from(false), 0.0);
+    assert_eq!(f128::from(true), 1.0);
+    assert_eq!(f128::from(u8::MIN), 0.0);
+    assert_eq!(f128::from(42_u8), 42.0);
+    assert_eq!(f128::from(u8::MAX), 255.0);
+    assert_eq!(f128::from(i8::MIN), -128.0);
+    assert_eq!(f128::from(42_i8), 42.0);
+    assert_eq!(f128::from(i8::MAX), 127.0);
+    assert_eq!(f128::from(u16::MIN), 0.0);
+    assert_eq!(f128::from(42_u16), 42.0);
+    assert_eq!(f128::from(u16::MAX), 65535.0);
+    assert_eq!(f128::from(i16::MIN), -32768.0);
+    assert_eq!(f128::from(42_i16), 42.0);
+    assert_eq!(f128::from(i16::MAX), 32767.0);
+    assert_eq!(f128::from(u32::MIN), 0.0);
+    assert_eq!(f128::from(42_u32), 42.0);
+    assert_eq!(f128::from(u32::MAX), 4294967295.0);
+    assert_eq!(f128::from(i32::MIN), -2147483648.0);
+    assert_eq!(f128::from(42_i32), 42.0);
+    assert_eq!(f128::from(i32::MAX), 2147483647.0);
+    // FIXME(f16_f128): Uncomment these tests once the From<{u64,i64}> impls are added.
+    // assert_eq!(f128::from(u64::MIN), 0.0);
+    // assert_eq!(f128::from(42_u64), 42.0);
+    // assert_eq!(f128::from(u64::MAX), 18446744073709551615.0);
+    // assert_eq!(f128::from(i64::MIN), -9223372036854775808.0);
+    // assert_eq!(f128::from(42_i64), 42.0);
+    // assert_eq!(f128::from(i64::MAX), 9223372036854775807.0);
+}
diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs
new file mode 100644
index 00000000000..db98181226c
--- /dev/null
+++ b/library/coretests/tests/floats/f16.rs
@@ -0,0 +1,753 @@
+// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
+#![cfg(target_has_reliable_f16)]
+
+use std::f16::consts;
+use std::num::FpCategory as Fp;
+
+/// Tolerance for results on the order of 10.0e-2
+#[allow(unused)]
+const TOL_N2: f16 = 0.0001;
+
+/// Tolerance for results on the order of 10.0e+0
+#[allow(unused)]
+const TOL_0: f16 = 0.01;
+
+/// Tolerance for results on the order of 10.0e+2
+#[allow(unused)]
+const TOL_P2: f16 = 0.5;
+
+/// Tolerance for results on the order of 10.0e+4
+#[allow(unused)]
+const TOL_P4: f16 = 10.0;
+
+/// Smallest number
+const TINY_BITS: u16 = 0x1;
+
+/// Next smallest number
+const TINY_UP_BITS: u16 = 0x2;
+
+/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
+const MAX_DOWN_BITS: u16 = 0x7bfe;
+
+/// Zeroed exponent, full significant
+const LARGEST_SUBNORMAL_BITS: u16 = 0x03ff;
+
+/// Exponent = 0b1, zeroed significand
+const SMALLEST_NORMAL_BITS: u16 = 0x0400;
+
+/// First pattern over the mantissa
+const NAN_MASK1: u16 = 0x02aa;
+
+/// Second pattern over the mantissa
+const NAN_MASK2: u16 = 0x0155;
+
+/// Compare by representation
+#[allow(unused_macros)]
+macro_rules! assert_f16_biteq {
+    ($a:expr, $b:expr) => {
+        let (l, r): (&f16, &f16) = (&$a, &$b);
+        let lb = l.to_bits();
+        let rb = r.to_bits();
+        assert_eq!(lb, rb, "float {l:?} ({lb:#04x}) is not bitequal to {r:?} ({rb:#04x})");
+    };
+}
+
+#[test]
+fn test_num_f16() {
+    super::test_num(10f16, 2f16);
+}
+
+// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
+// the intrinsics.
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_min_nan() {
+    assert_eq!(f16::NAN.min(2.0), 2.0);
+    assert_eq!(2.0f16.min(f16::NAN), 2.0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_max_nan() {
+    assert_eq!(f16::NAN.max(2.0), 2.0);
+    assert_eq!(2.0f16.max(f16::NAN), 2.0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_minimum() {
+    assert!(f16::NAN.minimum(2.0).is_nan());
+    assert!(2.0f16.minimum(f16::NAN).is_nan());
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_maximum() {
+    assert!(f16::NAN.maximum(2.0).is_nan());
+    assert!(2.0f16.maximum(f16::NAN).is_nan());
+}
+
+#[test]
+fn test_nan() {
+    let nan: f16 = f16::NAN;
+    assert!(nan.is_nan());
+    assert!(!nan.is_infinite());
+    assert!(!nan.is_finite());
+    assert!(nan.is_sign_positive());
+    assert!(!nan.is_sign_negative());
+    assert!(!nan.is_normal());
+    assert_eq!(Fp::Nan, nan.classify());
+    // Ensure the quiet bit is set.
+    assert!(nan.to_bits() & (1 << (f16::MANTISSA_DIGITS - 2)) != 0);
+}
+
+#[test]
+fn test_infinity() {
+    let inf: f16 = f16::INFINITY;
+    assert!(inf.is_infinite());
+    assert!(!inf.is_finite());
+    assert!(inf.is_sign_positive());
+    assert!(!inf.is_sign_negative());
+    assert!(!inf.is_nan());
+    assert!(!inf.is_normal());
+    assert_eq!(Fp::Infinite, inf.classify());
+}
+
+#[test]
+fn test_neg_infinity() {
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert!(neg_inf.is_infinite());
+    assert!(!neg_inf.is_finite());
+    assert!(!neg_inf.is_sign_positive());
+    assert!(neg_inf.is_sign_negative());
+    assert!(!neg_inf.is_nan());
+    assert!(!neg_inf.is_normal());
+    assert_eq!(Fp::Infinite, neg_inf.classify());
+}
+
+#[test]
+fn test_zero() {
+    let zero: f16 = 0.0f16;
+    assert_eq!(0.0, zero);
+    assert!(!zero.is_infinite());
+    assert!(zero.is_finite());
+    assert!(zero.is_sign_positive());
+    assert!(!zero.is_sign_negative());
+    assert!(!zero.is_nan());
+    assert!(!zero.is_normal());
+    assert_eq!(Fp::Zero, zero.classify());
+}
+
+#[test]
+fn test_neg_zero() {
+    let neg_zero: f16 = -0.0;
+    assert_eq!(0.0, neg_zero);
+    assert!(!neg_zero.is_infinite());
+    assert!(neg_zero.is_finite());
+    assert!(!neg_zero.is_sign_positive());
+    assert!(neg_zero.is_sign_negative());
+    assert!(!neg_zero.is_nan());
+    assert!(!neg_zero.is_normal());
+    assert_eq!(Fp::Zero, neg_zero.classify());
+}
+
+#[test]
+fn test_one() {
+    let one: f16 = 1.0f16;
+    assert_eq!(1.0, one);
+    assert!(!one.is_infinite());
+    assert!(one.is_finite());
+    assert!(one.is_sign_positive());
+    assert!(!one.is_sign_negative());
+    assert!(!one.is_nan());
+    assert!(one.is_normal());
+    assert_eq!(Fp::Normal, one.classify());
+}
+
+#[test]
+fn test_is_nan() {
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert!(nan.is_nan());
+    assert!(!0.0f16.is_nan());
+    assert!(!5.3f16.is_nan());
+    assert!(!(-10.732f16).is_nan());
+    assert!(!inf.is_nan());
+    assert!(!neg_inf.is_nan());
+}
+
+#[test]
+fn test_is_infinite() {
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert!(!nan.is_infinite());
+    assert!(inf.is_infinite());
+    assert!(neg_inf.is_infinite());
+    assert!(!0.0f16.is_infinite());
+    assert!(!42.8f16.is_infinite());
+    assert!(!(-109.2f16).is_infinite());
+}
+
+#[test]
+fn test_is_finite() {
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert!(!nan.is_finite());
+    assert!(!inf.is_finite());
+    assert!(!neg_inf.is_finite());
+    assert!(0.0f16.is_finite());
+    assert!(42.8f16.is_finite());
+    assert!((-109.2f16).is_finite());
+}
+
+#[test]
+fn test_is_normal() {
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    let zero: f16 = 0.0f16;
+    let neg_zero: f16 = -0.0;
+    assert!(!nan.is_normal());
+    assert!(!inf.is_normal());
+    assert!(!neg_inf.is_normal());
+    assert!(!zero.is_normal());
+    assert!(!neg_zero.is_normal());
+    assert!(1f16.is_normal());
+    assert!(1e-4f16.is_normal());
+    assert!(!1e-5f16.is_normal());
+}
+
+#[test]
+fn test_classify() {
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    let zero: f16 = 0.0f16;
+    let neg_zero: f16 = -0.0;
+    assert_eq!(nan.classify(), Fp::Nan);
+    assert_eq!(inf.classify(), Fp::Infinite);
+    assert_eq!(neg_inf.classify(), Fp::Infinite);
+    assert_eq!(zero.classify(), Fp::Zero);
+    assert_eq!(neg_zero.classify(), Fp::Zero);
+    assert_eq!(1f16.classify(), Fp::Normal);
+    assert_eq!(1e-4f16.classify(), Fp::Normal);
+    assert_eq!(1e-5f16.classify(), Fp::Subnormal);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_floor() {
+    assert_approx_eq!(1.0f16.floor(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.3f16.floor(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.5f16.floor(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.7f16.floor(), 1.0f16, TOL_0);
+    assert_approx_eq!(0.0f16.floor(), 0.0f16, TOL_0);
+    assert_approx_eq!((-0.0f16).floor(), -0.0f16, TOL_0);
+    assert_approx_eq!((-1.0f16).floor(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.3f16).floor(), -2.0f16, TOL_0);
+    assert_approx_eq!((-1.5f16).floor(), -2.0f16, TOL_0);
+    assert_approx_eq!((-1.7f16).floor(), -2.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_ceil() {
+    assert_approx_eq!(1.0f16.ceil(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.3f16.ceil(), 2.0f16, TOL_0);
+    assert_approx_eq!(1.5f16.ceil(), 2.0f16, TOL_0);
+    assert_approx_eq!(1.7f16.ceil(), 2.0f16, TOL_0);
+    assert_approx_eq!(0.0f16.ceil(), 0.0f16, TOL_0);
+    assert_approx_eq!((-0.0f16).ceil(), -0.0f16, TOL_0);
+    assert_approx_eq!((-1.0f16).ceil(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.3f16).ceil(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.5f16).ceil(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.7f16).ceil(), -1.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_round() {
+    assert_approx_eq!(2.5f16.round(), 3.0f16, TOL_0);
+    assert_approx_eq!(1.0f16.round(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.3f16.round(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.5f16.round(), 2.0f16, TOL_0);
+    assert_approx_eq!(1.7f16.round(), 2.0f16, TOL_0);
+    assert_approx_eq!(0.0f16.round(), 0.0f16, TOL_0);
+    assert_approx_eq!((-0.0f16).round(), -0.0f16, TOL_0);
+    assert_approx_eq!((-1.0f16).round(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.3f16).round(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.5f16).round(), -2.0f16, TOL_0);
+    assert_approx_eq!((-1.7f16).round(), -2.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_round_ties_even() {
+    assert_approx_eq!(2.5f16.round_ties_even(), 2.0f16, TOL_0);
+    assert_approx_eq!(1.0f16.round_ties_even(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.3f16.round_ties_even(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.5f16.round_ties_even(), 2.0f16, TOL_0);
+    assert_approx_eq!(1.7f16.round_ties_even(), 2.0f16, TOL_0);
+    assert_approx_eq!(0.0f16.round_ties_even(), 0.0f16, TOL_0);
+    assert_approx_eq!((-0.0f16).round_ties_even(), -0.0f16, TOL_0);
+    assert_approx_eq!((-1.0f16).round_ties_even(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.3f16).round_ties_even(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.5f16).round_ties_even(), -2.0f16, TOL_0);
+    assert_approx_eq!((-1.7f16).round_ties_even(), -2.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_trunc() {
+    assert_approx_eq!(1.0f16.trunc(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.3f16.trunc(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.5f16.trunc(), 1.0f16, TOL_0);
+    assert_approx_eq!(1.7f16.trunc(), 1.0f16, TOL_0);
+    assert_approx_eq!(0.0f16.trunc(), 0.0f16, TOL_0);
+    assert_approx_eq!((-0.0f16).trunc(), -0.0f16, TOL_0);
+    assert_approx_eq!((-1.0f16).trunc(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.3f16).trunc(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.5f16).trunc(), -1.0f16, TOL_0);
+    assert_approx_eq!((-1.7f16).trunc(), -1.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_fract() {
+    assert_approx_eq!(1.0f16.fract(), 0.0f16, TOL_0);
+    assert_approx_eq!(1.3f16.fract(), 0.3f16, TOL_0);
+    assert_approx_eq!(1.5f16.fract(), 0.5f16, TOL_0);
+    assert_approx_eq!(1.7f16.fract(), 0.7f16, TOL_0);
+    assert_approx_eq!(0.0f16.fract(), 0.0f16, TOL_0);
+    assert_approx_eq!((-0.0f16).fract(), -0.0f16, TOL_0);
+    assert_approx_eq!((-1.0f16).fract(), -0.0f16, TOL_0);
+    assert_approx_eq!((-1.3f16).fract(), -0.3f16, TOL_0);
+    assert_approx_eq!((-1.5f16).fract(), -0.5f16, TOL_0);
+    assert_approx_eq!((-1.7f16).fract(), -0.7f16, TOL_0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_abs() {
+    assert_eq!(f16::INFINITY.abs(), f16::INFINITY);
+    assert_eq!(1f16.abs(), 1f16);
+    assert_eq!(0f16.abs(), 0f16);
+    assert_eq!((-0f16).abs(), 0f16);
+    assert_eq!((-1f16).abs(), 1f16);
+    assert_eq!(f16::NEG_INFINITY.abs(), f16::INFINITY);
+    assert_eq!((1f16 / f16::NEG_INFINITY).abs(), 0f16);
+    assert!(f16::NAN.abs().is_nan());
+}
+
+#[test]
+fn test_is_sign_positive() {
+    assert!(f16::INFINITY.is_sign_positive());
+    assert!(1f16.is_sign_positive());
+    assert!(0f16.is_sign_positive());
+    assert!(!(-0f16).is_sign_positive());
+    assert!(!(-1f16).is_sign_positive());
+    assert!(!f16::NEG_INFINITY.is_sign_positive());
+    assert!(!(1f16 / f16::NEG_INFINITY).is_sign_positive());
+    assert!(f16::NAN.is_sign_positive());
+    assert!(!(-f16::NAN).is_sign_positive());
+}
+
+#[test]
+fn test_is_sign_negative() {
+    assert!(!f16::INFINITY.is_sign_negative());
+    assert!(!1f16.is_sign_negative());
+    assert!(!0f16.is_sign_negative());
+    assert!((-0f16).is_sign_negative());
+    assert!((-1f16).is_sign_negative());
+    assert!(f16::NEG_INFINITY.is_sign_negative());
+    assert!((1f16 / f16::NEG_INFINITY).is_sign_negative());
+    assert!(!f16::NAN.is_sign_negative());
+    assert!((-f16::NAN).is_sign_negative());
+}
+
+#[test]
+fn test_next_up() {
+    let tiny = f16::from_bits(TINY_BITS);
+    let tiny_up = f16::from_bits(TINY_UP_BITS);
+    let max_down = f16::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
+    assert_f16_biteq!(f16::NEG_INFINITY.next_up(), f16::MIN);
+    assert_f16_biteq!(f16::MIN.next_up(), -max_down);
+    assert_f16_biteq!((-1.0 - f16::EPSILON).next_up(), -1.0);
+    assert_f16_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_f16_biteq!((-tiny_up).next_up(), -tiny);
+    assert_f16_biteq!((-tiny).next_up(), -0.0f16);
+    assert_f16_biteq!((-0.0f16).next_up(), tiny);
+    assert_f16_biteq!(0.0f16.next_up(), tiny);
+    assert_f16_biteq!(tiny.next_up(), tiny_up);
+    assert_f16_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_f16_biteq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
+    assert_f16_biteq!(f16::MAX.next_up(), f16::INFINITY);
+    assert_f16_biteq!(f16::INFINITY.next_up(), f16::INFINITY);
+
+    // Check that NaNs roundtrip.
+    let nan0 = f16::NAN;
+    let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
+    assert_f16_biteq!(nan0.next_up(), nan0);
+    assert_f16_biteq!(nan1.next_up(), nan1);
+    assert_f16_biteq!(nan2.next_up(), nan2);
+}
+
+#[test]
+fn test_next_down() {
+    let tiny = f16::from_bits(TINY_BITS);
+    let tiny_up = f16::from_bits(TINY_UP_BITS);
+    let max_down = f16::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
+    assert_f16_biteq!(f16::NEG_INFINITY.next_down(), f16::NEG_INFINITY);
+    assert_f16_biteq!(f16::MIN.next_down(), f16::NEG_INFINITY);
+    assert_f16_biteq!((-max_down).next_down(), f16::MIN);
+    assert_f16_biteq!((-1.0f16).next_down(), -1.0 - f16::EPSILON);
+    assert_f16_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_f16_biteq!((-tiny).next_down(), -tiny_up);
+    assert_f16_biteq!((-0.0f16).next_down(), -tiny);
+    assert_f16_biteq!((0.0f16).next_down(), -tiny);
+    assert_f16_biteq!(tiny.next_down(), 0.0f16);
+    assert_f16_biteq!(tiny_up.next_down(), tiny);
+    assert_f16_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_f16_biteq!((1.0 + f16::EPSILON).next_down(), 1.0f16);
+    assert_f16_biteq!(f16::MAX.next_down(), max_down);
+    assert_f16_biteq!(f16::INFINITY.next_down(), f16::MAX);
+
+    // Check that NaNs roundtrip.
+    let nan0 = f16::NAN;
+    let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
+    assert_f16_biteq!(nan0.next_down(), nan0);
+    assert_f16_biteq!(nan1.next_down(), nan1);
+    assert_f16_biteq!(nan2.next_down(), nan2);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_mul_add() {
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert_approx_eq!(12.3f16.mul_add(4.5, 6.7), 62.05, TOL_P2);
+    assert_approx_eq!((-12.3f16).mul_add(-4.5, -6.7), 48.65, TOL_P2);
+    assert_approx_eq!(0.0f16.mul_add(8.9, 1.2), 1.2, TOL_0);
+    assert_approx_eq!(3.4f16.mul_add(-0.0, 5.6), 5.6, TOL_0);
+    assert!(nan.mul_add(7.8, 9.0).is_nan());
+    assert_eq!(inf.mul_add(7.8, 9.0), inf);
+    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_eq!(8.9f16.mul_add(inf, 3.2), inf);
+    assert_eq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_recip() {
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert_eq!(1.0f16.recip(), 1.0);
+    assert_eq!(2.0f16.recip(), 0.5);
+    assert_eq!((-0.4f16).recip(), -2.5);
+    assert_eq!(0.0f16.recip(), inf);
+    assert_approx_eq!(f16::MAX.recip(), 1.526624e-5f16, 1e-4);
+    assert!(nan.recip().is_nan());
+    assert_eq!(inf.recip(), 0.0);
+    assert_eq!(neg_inf.recip(), 0.0);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_powi() {
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert_eq!(1.0f16.powi(1), 1.0);
+    assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0);
+    assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2);
+    assert_eq!(8.3f16.powi(0), 1.0);
+    assert!(nan.powi(2).is_nan());
+    assert_eq!(inf.powi(3), inf);
+    assert_eq!(neg_inf.powi(2), inf);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_sqrt_domain() {
+    assert!(f16::NAN.sqrt().is_nan());
+    assert!(f16::NEG_INFINITY.sqrt().is_nan());
+    assert!((-1.0f16).sqrt().is_nan());
+    assert_eq!((-0.0f16).sqrt(), -0.0);
+    assert_eq!(0.0f16.sqrt(), 0.0);
+    assert_eq!(1.0f16.sqrt(), 1.0);
+    assert_eq!(f16::INFINITY.sqrt(), f16::INFINITY);
+}
+
+#[test]
+fn test_to_degrees() {
+    let pi: f16 = consts::PI;
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert_eq!(0.0f16.to_degrees(), 0.0);
+    assert_approx_eq!((-5.8f16).to_degrees(), -332.315521, TOL_P2);
+    assert_approx_eq!(pi.to_degrees(), 180.0, TOL_P2);
+    assert!(nan.to_degrees().is_nan());
+    assert_eq!(inf.to_degrees(), inf);
+    assert_eq!(neg_inf.to_degrees(), neg_inf);
+    assert_eq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703);
+}
+
+#[test]
+fn test_to_radians() {
+    let pi: f16 = consts::PI;
+    let nan: f16 = f16::NAN;
+    let inf: f16 = f16::INFINITY;
+    let neg_inf: f16 = f16::NEG_INFINITY;
+    assert_eq!(0.0f16.to_radians(), 0.0);
+    assert_approx_eq!(154.6f16.to_radians(), 2.698279, TOL_0);
+    assert_approx_eq!((-332.31f16).to_radians(), -5.799903, TOL_0);
+    assert_approx_eq!(180.0f16.to_radians(), pi, TOL_0);
+    assert!(nan.to_radians().is_nan());
+    assert_eq!(inf.to_radians(), inf);
+    assert_eq!(neg_inf.to_radians(), neg_inf);
+}
+
+#[test]
+fn test_float_bits_conv() {
+    assert_eq!((1f16).to_bits(), 0x3c00);
+    assert_eq!((12.5f16).to_bits(), 0x4a40);
+    assert_eq!((1337f16).to_bits(), 0x6539);
+    assert_eq!((-14.25f16).to_bits(), 0xcb20);
+    assert_approx_eq!(f16::from_bits(0x3c00), 1.0, TOL_0);
+    assert_approx_eq!(f16::from_bits(0x4a40), 12.5, TOL_0);
+    assert_approx_eq!(f16::from_bits(0x6539), 1337.0, TOL_P4);
+    assert_approx_eq!(f16::from_bits(0xcb20), -14.25, TOL_0);
+
+    // Check that NaNs roundtrip their bits regardless of signaling-ness
+    let masked_nan1 = f16::NAN.to_bits() ^ NAN_MASK1;
+    let masked_nan2 = f16::NAN.to_bits() ^ NAN_MASK2;
+    assert!(f16::from_bits(masked_nan1).is_nan());
+    assert!(f16::from_bits(masked_nan2).is_nan());
+
+    assert_eq!(f16::from_bits(masked_nan1).to_bits(), masked_nan1);
+    assert_eq!(f16::from_bits(masked_nan2).to_bits(), masked_nan2);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_min_greater_than_max() {
+    let _ = 1.0f16.clamp(3.0, 1.0);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_min_is_nan() {
+    let _ = 1.0f16.clamp(f16::NAN, 1.0);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_max_is_nan() {
+    let _ = 1.0f16.clamp(3.0, f16::NAN);
+}
+
+#[test]
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f16_math)]
+fn test_total_cmp() {
+    use core::cmp::Ordering;
+
+    fn quiet_bit_mask() -> u16 {
+        1 << (f16::MANTISSA_DIGITS - 2)
+    }
+
+    fn min_subnorm() -> f16 {
+        f16::MIN_POSITIVE / f16::powf(2.0, f16::MANTISSA_DIGITS as f16 - 1.0)
+    }
+
+    fn max_subnorm() -> f16 {
+        f16::MIN_POSITIVE - min_subnorm()
+    }
+
+    fn q_nan() -> f16 {
+        f16::from_bits(f16::NAN.to_bits() | quiet_bit_mask())
+    }
+
+    fn s_nan() -> f16 {
+        f16::from_bits((f16::NAN.to_bits() & !quiet_bit_mask()) + 42)
+    }
+
+    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
+    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Equal, (-f16::INFINITY).total_cmp(&-f16::INFINITY));
+    assert_eq!(Ordering::Equal, (-f16::MAX).total_cmp(&-f16::MAX));
+    assert_eq!(Ordering::Equal, (-2.5_f16).total_cmp(&-2.5));
+    assert_eq!(Ordering::Equal, (-1.0_f16).total_cmp(&-1.0));
+    assert_eq!(Ordering::Equal, (-1.5_f16).total_cmp(&-1.5));
+    assert_eq!(Ordering::Equal, (-0.5_f16).total_cmp(&-0.5));
+    assert_eq!(Ordering::Equal, (-f16::MIN_POSITIVE).total_cmp(&-f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Equal, (-0.0_f16).total_cmp(&-0.0));
+    assert_eq!(Ordering::Equal, 0.0_f16.total_cmp(&0.0));
+    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Equal, f16::MIN_POSITIVE.total_cmp(&f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Equal, 0.5_f16.total_cmp(&0.5));
+    assert_eq!(Ordering::Equal, 1.0_f16.total_cmp(&1.0));
+    assert_eq!(Ordering::Equal, 1.5_f16.total_cmp(&1.5));
+    assert_eq!(Ordering::Equal, 2.5_f16.total_cmp(&2.5));
+    assert_eq!(Ordering::Equal, f16::MAX.total_cmp(&f16::MAX));
+    assert_eq!(Ordering::Equal, f16::INFINITY.total_cmp(&f16::INFINITY));
+    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
+    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
+
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
+    assert_eq!(Ordering::Less, (-f16::INFINITY).total_cmp(&-f16::MAX));
+    assert_eq!(Ordering::Less, (-f16::MAX).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-2.5_f16).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-1.5_f16).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-1.0_f16).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-0.5_f16).total_cmp(&-f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-f16::MIN_POSITIVE).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-0.0_f16).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, 0.0_f16.total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, f16::MIN_POSITIVE.total_cmp(&0.5));
+    assert_eq!(Ordering::Less, 0.5_f16.total_cmp(&1.0));
+    assert_eq!(Ordering::Less, 1.0_f16.total_cmp(&1.5));
+    assert_eq!(Ordering::Less, 1.5_f16.total_cmp(&2.5));
+    assert_eq!(Ordering::Less, 2.5_f16.total_cmp(&f16::MAX));
+    assert_eq!(Ordering::Less, f16::MAX.total_cmp(&f16::INFINITY));
+    assert_eq!(Ordering::Less, f16::INFINITY.total_cmp(&s_nan()));
+    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
+
+    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
+    assert_eq!(Ordering::Greater, (-f16::INFINITY).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Greater, (-f16::MAX).total_cmp(&-f16::INFINITY));
+    assert_eq!(Ordering::Greater, (-2.5_f16).total_cmp(&-f16::MAX));
+    assert_eq!(Ordering::Greater, (-1.5_f16).total_cmp(&-2.5));
+    assert_eq!(Ordering::Greater, (-1.0_f16).total_cmp(&-1.5));
+    assert_eq!(Ordering::Greater, (-0.5_f16).total_cmp(&-1.0));
+    assert_eq!(Ordering::Greater, (-f16::MIN_POSITIVE).total_cmp(&-0.5));
+    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Greater, (-0.0_f16).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Greater, 0.0_f16.total_cmp(&-0.0));
+    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
+    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Greater, f16::MIN_POSITIVE.total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Greater, 0.5_f16.total_cmp(&f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Greater, 1.0_f16.total_cmp(&0.5));
+    assert_eq!(Ordering::Greater, 1.5_f16.total_cmp(&1.0));
+    assert_eq!(Ordering::Greater, 2.5_f16.total_cmp(&1.5));
+    assert_eq!(Ordering::Greater, f16::MAX.total_cmp(&2.5));
+    assert_eq!(Ordering::Greater, f16::INFINITY.total_cmp(&f16::MAX));
+    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f16::INFINITY));
+    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
+
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::INFINITY));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MAX));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MAX));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::INFINITY));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
+
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MAX));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MAX));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::INFINITY));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
+}
+
+#[test]
+fn test_algebraic() {
+    let a: f16 = 123.0;
+    let b: f16 = 456.0;
+
+    // Check that individual operations match their primitive counterparts.
+    //
+    // This is a check of current implementations and does NOT imply any form of
+    // guarantee about future behavior. The compiler reserves the right to make
+    // these operations inexact matches in the future.
+    let eps_add = if cfg!(miri) { 1e1 } else { 0.0 };
+    let eps_mul = if cfg!(miri) { 1e3 } else { 0.0 };
+    let eps_div = if cfg!(miri) { 1e0 } else { 0.0 };
+
+    assert_approx_eq!(a.algebraic_add(b), a + b, eps_add);
+    assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add);
+    assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul);
+    assert_approx_eq!(a.algebraic_div(b), a / b, eps_div);
+    assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div);
+}
+
+#[test]
+fn test_from() {
+    assert_eq!(f16::from(false), 0.0);
+    assert_eq!(f16::from(true), 1.0);
+    assert_eq!(f16::from(u8::MIN), 0.0);
+    assert_eq!(f16::from(42_u8), 42.0);
+    assert_eq!(f16::from(u8::MAX), 255.0);
+    assert_eq!(f16::from(i8::MIN), -128.0);
+    assert_eq!(f16::from(42_i8), 42.0);
+    assert_eq!(f16::from(i8::MAX), 127.0);
+}
diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs
new file mode 100644
index 00000000000..9b551643bae
--- /dev/null
+++ b/library/coretests/tests/floats/f32.rs
@@ -0,0 +1,702 @@
+use core::f32;
+use core::f32::consts;
+use core::num::FpCategory as Fp;
+
+/// Smallest number
+const TINY_BITS: u32 = 0x1;
+
+/// Next smallest number
+const TINY_UP_BITS: u32 = 0x2;
+
+/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
+const MAX_DOWN_BITS: u32 = 0x7f7f_fffe;
+
+/// Zeroed exponent, full significant
+const LARGEST_SUBNORMAL_BITS: u32 = 0x007f_ffff;
+
+/// Exponent = 0b1, zeroed significand
+const SMALLEST_NORMAL_BITS: u32 = 0x0080_0000;
+
+/// First pattern over the mantissa
+const NAN_MASK1: u32 = 0x002a_aaaa;
+
+/// Second pattern over the mantissa
+const NAN_MASK2: u32 = 0x0055_5555;
+
+#[allow(unused_macros)]
+macro_rules! assert_f32_biteq {
+    ($left : expr, $right : expr) => {
+        let l: &f32 = &$left;
+        let r: &f32 = &$right;
+        let lb = l.to_bits();
+        let rb = r.to_bits();
+        assert_eq!(lb, rb, "float {l} ({lb:#010x}) is not bitequal to {r} ({rb:#010x})");
+    };
+}
+
+#[test]
+fn test_num_f32() {
+    super::test_num(10f32, 2f32);
+}
+
+#[test]
+fn test_min_nan() {
+    assert_eq!(f32::NAN.min(2.0), 2.0);
+    assert_eq!(2.0f32.min(f32::NAN), 2.0);
+}
+
+#[test]
+fn test_max_nan() {
+    assert_eq!(f32::NAN.max(2.0), 2.0);
+    assert_eq!(2.0f32.max(f32::NAN), 2.0);
+}
+
+#[test]
+fn test_minimum() {
+    assert!(f32::NAN.minimum(2.0).is_nan());
+    assert!(2.0f32.minimum(f32::NAN).is_nan());
+}
+
+#[test]
+fn test_maximum() {
+    assert!(f32::NAN.maximum(2.0).is_nan());
+    assert!(2.0f32.maximum(f32::NAN).is_nan());
+}
+
+#[test]
+fn test_nan() {
+    let nan: f32 = f32::NAN;
+    assert!(nan.is_nan());
+    assert!(!nan.is_infinite());
+    assert!(!nan.is_finite());
+    assert!(!nan.is_normal());
+    assert!(nan.is_sign_positive());
+    assert!(!nan.is_sign_negative());
+    assert_eq!(Fp::Nan, nan.classify());
+    // Ensure the quiet bit is set.
+    assert!(nan.to_bits() & (1 << (f32::MANTISSA_DIGITS - 2)) != 0);
+}
+
+#[test]
+fn test_infinity() {
+    let inf: f32 = f32::INFINITY;
+    assert!(inf.is_infinite());
+    assert!(!inf.is_finite());
+    assert!(inf.is_sign_positive());
+    assert!(!inf.is_sign_negative());
+    assert!(!inf.is_nan());
+    assert!(!inf.is_normal());
+    assert_eq!(Fp::Infinite, inf.classify());
+}
+
+#[test]
+fn test_neg_infinity() {
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert!(neg_inf.is_infinite());
+    assert!(!neg_inf.is_finite());
+    assert!(!neg_inf.is_sign_positive());
+    assert!(neg_inf.is_sign_negative());
+    assert!(!neg_inf.is_nan());
+    assert!(!neg_inf.is_normal());
+    assert_eq!(Fp::Infinite, neg_inf.classify());
+}
+
+#[test]
+fn test_zero() {
+    let zero: f32 = 0.0f32;
+    assert_eq!(0.0, zero);
+    assert!(!zero.is_infinite());
+    assert!(zero.is_finite());
+    assert!(zero.is_sign_positive());
+    assert!(!zero.is_sign_negative());
+    assert!(!zero.is_nan());
+    assert!(!zero.is_normal());
+    assert_eq!(Fp::Zero, zero.classify());
+}
+
+#[test]
+fn test_neg_zero() {
+    let neg_zero: f32 = -0.0;
+    assert_eq!(0.0, neg_zero);
+    assert!(!neg_zero.is_infinite());
+    assert!(neg_zero.is_finite());
+    assert!(!neg_zero.is_sign_positive());
+    assert!(neg_zero.is_sign_negative());
+    assert!(!neg_zero.is_nan());
+    assert!(!neg_zero.is_normal());
+    assert_eq!(Fp::Zero, neg_zero.classify());
+}
+
+#[test]
+fn test_one() {
+    let one: f32 = 1.0f32;
+    assert_eq!(1.0, one);
+    assert!(!one.is_infinite());
+    assert!(one.is_finite());
+    assert!(one.is_sign_positive());
+    assert!(!one.is_sign_negative());
+    assert!(!one.is_nan());
+    assert!(one.is_normal());
+    assert_eq!(Fp::Normal, one.classify());
+}
+
+#[test]
+fn test_is_nan() {
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert!(nan.is_nan());
+    assert!(!0.0f32.is_nan());
+    assert!(!5.3f32.is_nan());
+    assert!(!(-10.732f32).is_nan());
+    assert!(!inf.is_nan());
+    assert!(!neg_inf.is_nan());
+}
+
+#[test]
+fn test_is_infinite() {
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert!(!nan.is_infinite());
+    assert!(inf.is_infinite());
+    assert!(neg_inf.is_infinite());
+    assert!(!0.0f32.is_infinite());
+    assert!(!42.8f32.is_infinite());
+    assert!(!(-109.2f32).is_infinite());
+}
+
+#[test]
+fn test_is_finite() {
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert!(!nan.is_finite());
+    assert!(!inf.is_finite());
+    assert!(!neg_inf.is_finite());
+    assert!(0.0f32.is_finite());
+    assert!(42.8f32.is_finite());
+    assert!((-109.2f32).is_finite());
+}
+
+#[test]
+fn test_is_normal() {
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    let zero: f32 = 0.0f32;
+    let neg_zero: f32 = -0.0;
+    assert!(!nan.is_normal());
+    assert!(!inf.is_normal());
+    assert!(!neg_inf.is_normal());
+    assert!(!zero.is_normal());
+    assert!(!neg_zero.is_normal());
+    assert!(1f32.is_normal());
+    assert!(1e-37f32.is_normal());
+    assert!(!1e-38f32.is_normal());
+}
+
+#[test]
+fn test_classify() {
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    let zero: f32 = 0.0f32;
+    let neg_zero: f32 = -0.0;
+    assert_eq!(nan.classify(), Fp::Nan);
+    assert_eq!(inf.classify(), Fp::Infinite);
+    assert_eq!(neg_inf.classify(), Fp::Infinite);
+    assert_eq!(zero.classify(), Fp::Zero);
+    assert_eq!(neg_zero.classify(), Fp::Zero);
+    assert_eq!(1f32.classify(), Fp::Normal);
+    assert_eq!(1e-37f32.classify(), Fp::Normal);
+    assert_eq!(1e-38f32.classify(), Fp::Subnormal);
+}
+
+#[test]
+fn test_floor() {
+    assert_approx_eq!(f32::floor(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::floor(1.3f32), 1.0f32);
+    assert_approx_eq!(f32::floor(1.5f32), 1.0f32);
+    assert_approx_eq!(f32::floor(1.7f32), 1.0f32);
+    assert_approx_eq!(f32::floor(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::floor(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::floor(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::floor(-1.3f32), -2.0f32);
+    assert_approx_eq!(f32::floor(-1.5f32), -2.0f32);
+    assert_approx_eq!(f32::floor(-1.7f32), -2.0f32);
+}
+
+#[test]
+fn test_ceil() {
+    assert_approx_eq!(f32::ceil(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::ceil(1.3f32), 2.0f32);
+    assert_approx_eq!(f32::ceil(1.5f32), 2.0f32);
+    assert_approx_eq!(f32::ceil(1.7f32), 2.0f32);
+    assert_approx_eq!(f32::ceil(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::ceil(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::ceil(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::ceil(-1.3f32), -1.0f32);
+    assert_approx_eq!(f32::ceil(-1.5f32), -1.0f32);
+    assert_approx_eq!(f32::ceil(-1.7f32), -1.0f32);
+}
+
+#[test]
+fn test_round() {
+    assert_approx_eq!(f32::round(2.5f32), 3.0f32);
+    assert_approx_eq!(f32::round(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::round(1.3f32), 1.0f32);
+    assert_approx_eq!(f32::round(1.5f32), 2.0f32);
+    assert_approx_eq!(f32::round(1.7f32), 2.0f32);
+    assert_approx_eq!(f32::round(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::round(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::round(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::round(-1.3f32), -1.0f32);
+    assert_approx_eq!(f32::round(-1.5f32), -2.0f32);
+    assert_approx_eq!(f32::round(-1.7f32), -2.0f32);
+}
+
+#[test]
+fn test_round_ties_even() {
+    assert_approx_eq!(f32::round_ties_even(2.5f32), 2.0f32);
+    assert_approx_eq!(f32::round_ties_even(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::round_ties_even(1.3f32), 1.0f32);
+    assert_approx_eq!(f32::round_ties_even(1.5f32), 2.0f32);
+    assert_approx_eq!(f32::round_ties_even(1.7f32), 2.0f32);
+    assert_approx_eq!(f32::round_ties_even(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::round_ties_even(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::round_ties_even(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::round_ties_even(-1.3f32), -1.0f32);
+    assert_approx_eq!(f32::round_ties_even(-1.5f32), -2.0f32);
+    assert_approx_eq!(f32::round_ties_even(-1.7f32), -2.0f32);
+}
+
+#[test]
+fn test_trunc() {
+    assert_approx_eq!(f32::trunc(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::trunc(1.3f32), 1.0f32);
+    assert_approx_eq!(f32::trunc(1.5f32), 1.0f32);
+    assert_approx_eq!(f32::trunc(1.7f32), 1.0f32);
+    assert_approx_eq!(f32::trunc(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::trunc(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::trunc(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::trunc(-1.3f32), -1.0f32);
+    assert_approx_eq!(f32::trunc(-1.5f32), -1.0f32);
+    assert_approx_eq!(f32::trunc(-1.7f32), -1.0f32);
+}
+
+#[test]
+fn test_fract() {
+    assert_approx_eq!(f32::fract(1.0f32), 0.0f32);
+    assert_approx_eq!(f32::fract(1.3f32), 0.3f32);
+    assert_approx_eq!(f32::fract(1.5f32), 0.5f32);
+    assert_approx_eq!(f32::fract(1.7f32), 0.7f32);
+    assert_approx_eq!(f32::fract(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::fract(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::fract(-1.0f32), -0.0f32);
+    assert_approx_eq!(f32::fract(-1.3f32), -0.3f32);
+    assert_approx_eq!(f32::fract(-1.5f32), -0.5f32);
+    assert_approx_eq!(f32::fract(-1.7f32), -0.7f32);
+}
+
+#[test]
+fn test_abs() {
+    assert_eq!(f32::INFINITY.abs(), f32::INFINITY);
+    assert_eq!(1f32.abs(), 1f32);
+    assert_eq!(0f32.abs(), 0f32);
+    assert_eq!((-0f32).abs(), 0f32);
+    assert_eq!((-1f32).abs(), 1f32);
+    assert_eq!(f32::NEG_INFINITY.abs(), f32::INFINITY);
+    assert_eq!((1f32 / f32::NEG_INFINITY).abs(), 0f32);
+    assert!(f32::NAN.abs().is_nan());
+}
+
+#[test]
+fn test_signum() {
+    assert_eq!(f32::INFINITY.signum(), 1f32);
+    assert_eq!(1f32.signum(), 1f32);
+    assert_eq!(0f32.signum(), 1f32);
+    assert_eq!((-0f32).signum(), -1f32);
+    assert_eq!((-1f32).signum(), -1f32);
+    assert_eq!(f32::NEG_INFINITY.signum(), -1f32);
+    assert_eq!((1f32 / f32::NEG_INFINITY).signum(), -1f32);
+    assert!(f32::NAN.signum().is_nan());
+}
+
+#[test]
+fn test_is_sign_positive() {
+    assert!(f32::INFINITY.is_sign_positive());
+    assert!(1f32.is_sign_positive());
+    assert!(0f32.is_sign_positive());
+    assert!(!(-0f32).is_sign_positive());
+    assert!(!(-1f32).is_sign_positive());
+    assert!(!f32::NEG_INFINITY.is_sign_positive());
+    assert!(!(1f32 / f32::NEG_INFINITY).is_sign_positive());
+    assert!(f32::NAN.is_sign_positive());
+    assert!(!(-f32::NAN).is_sign_positive());
+}
+
+#[test]
+fn test_is_sign_negative() {
+    assert!(!f32::INFINITY.is_sign_negative());
+    assert!(!1f32.is_sign_negative());
+    assert!(!0f32.is_sign_negative());
+    assert!((-0f32).is_sign_negative());
+    assert!((-1f32).is_sign_negative());
+    assert!(f32::NEG_INFINITY.is_sign_negative());
+    assert!((1f32 / f32::NEG_INFINITY).is_sign_negative());
+    assert!(!f32::NAN.is_sign_negative());
+    assert!((-f32::NAN).is_sign_negative());
+}
+
+#[test]
+fn test_next_up() {
+    let tiny = f32::from_bits(TINY_BITS);
+    let tiny_up = f32::from_bits(TINY_UP_BITS);
+    let max_down = f32::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
+    assert_f32_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN);
+    assert_f32_biteq!(f32::MIN.next_up(), -max_down);
+    assert_f32_biteq!((-1.0 - f32::EPSILON).next_up(), -1.0);
+    assert_f32_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_f32_biteq!((-tiny_up).next_up(), -tiny);
+    assert_f32_biteq!((-tiny).next_up(), -0.0f32);
+    assert_f32_biteq!((-0.0f32).next_up(), tiny);
+    assert_f32_biteq!(0.0f32.next_up(), tiny);
+    assert_f32_biteq!(tiny.next_up(), tiny_up);
+    assert_f32_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_f32_biteq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
+    assert_f32_biteq!(f32::MAX.next_up(), f32::INFINITY);
+    assert_f32_biteq!(f32::INFINITY.next_up(), f32::INFINITY);
+
+    // Check that NaNs roundtrip.
+    let nan0 = f32::NAN;
+    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
+    assert_f32_biteq!(nan0.next_up(), nan0);
+    assert_f32_biteq!(nan1.next_up(), nan1);
+    assert_f32_biteq!(nan2.next_up(), nan2);
+}
+
+#[test]
+fn test_next_down() {
+    let tiny = f32::from_bits(TINY_BITS);
+    let tiny_up = f32::from_bits(TINY_UP_BITS);
+    let max_down = f32::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
+    assert_f32_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
+    assert_f32_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY);
+    assert_f32_biteq!((-max_down).next_down(), f32::MIN);
+    assert_f32_biteq!((-1.0f32).next_down(), -1.0 - f32::EPSILON);
+    assert_f32_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_f32_biteq!((-tiny).next_down(), -tiny_up);
+    assert_f32_biteq!((-0.0f32).next_down(), -tiny);
+    assert_f32_biteq!((0.0f32).next_down(), -tiny);
+    assert_f32_biteq!(tiny.next_down(), 0.0f32);
+    assert_f32_biteq!(tiny_up.next_down(), tiny);
+    assert_f32_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_f32_biteq!((1.0 + f32::EPSILON).next_down(), 1.0f32);
+    assert_f32_biteq!(f32::MAX.next_down(), max_down);
+    assert_f32_biteq!(f32::INFINITY.next_down(), f32::MAX);
+
+    // Check that NaNs roundtrip.
+    let nan0 = f32::NAN;
+    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
+    assert_f32_biteq!(nan0.next_down(), nan0);
+    assert_f32_biteq!(nan1.next_down(), nan1);
+    assert_f32_biteq!(nan2.next_down(), nan2);
+}
+
+// FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
+#[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)]
+#[test]
+fn test_mul_add() {
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert_approx_eq!(f32::mul_add(12.3f32, 4.5, 6.7), 62.05);
+    assert_approx_eq!(f32::mul_add(-12.3f32, -4.5, -6.7), 48.65);
+    assert_approx_eq!(f32::mul_add(0.0f32, 8.9, 1.2), 1.2);
+    assert_approx_eq!(f32::mul_add(3.4f32, -0.0, 5.6), 5.6);
+    assert!(f32::mul_add(nan, 7.8, 9.0).is_nan());
+    assert_eq!(f32::mul_add(inf, 7.8, 9.0), inf);
+    assert_eq!(f32::mul_add(neg_inf, 7.8, 9.0), neg_inf);
+    assert_eq!(f32::mul_add(8.9f32, inf, 3.2), inf);
+    assert_eq!(f32::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
+}
+
+#[test]
+fn test_recip() {
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert_eq!(1.0f32.recip(), 1.0);
+    assert_eq!(2.0f32.recip(), 0.5);
+    assert_eq!((-0.4f32).recip(), -2.5);
+    assert_eq!(0.0f32.recip(), inf);
+    assert!(nan.recip().is_nan());
+    assert_eq!(inf.recip(), 0.0);
+    assert_eq!(neg_inf.recip(), 0.0);
+}
+
+#[test]
+fn test_powi() {
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert_eq!(1.0f32.powi(1), 1.0);
+    assert_approx_eq!((-3.1f32).powi(2), 9.61);
+    assert_approx_eq!(5.9f32.powi(-2), 0.028727);
+    assert_eq!(8.3f32.powi(0), 1.0);
+    assert!(nan.powi(2).is_nan());
+    assert_eq!(inf.powi(3), inf);
+    assert_eq!(neg_inf.powi(2), inf);
+}
+
+#[test]
+fn test_sqrt_domain() {
+    assert!(f32::NAN.sqrt().is_nan());
+    assert!(f32::NEG_INFINITY.sqrt().is_nan());
+    assert!((-1.0f32).sqrt().is_nan());
+    assert_eq!((-0.0f32).sqrt(), -0.0);
+    assert_eq!(0.0f32.sqrt(), 0.0);
+    assert_eq!(1.0f32.sqrt(), 1.0);
+    assert_eq!(f32::INFINITY.sqrt(), f32::INFINITY);
+}
+
+#[test]
+fn test_to_degrees() {
+    let pi: f32 = consts::PI;
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert_eq!(0.0f32.to_degrees(), 0.0);
+    assert_approx_eq!((-5.8f32).to_degrees(), -332.315521);
+    assert_eq!(pi.to_degrees(), 180.0);
+    assert!(nan.to_degrees().is_nan());
+    assert_eq!(inf.to_degrees(), inf);
+    assert_eq!(neg_inf.to_degrees(), neg_inf);
+    assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
+}
+
+#[test]
+fn test_to_radians() {
+    let pi: f32 = consts::PI;
+    let nan: f32 = f32::NAN;
+    let inf: f32 = f32::INFINITY;
+    let neg_inf: f32 = f32::NEG_INFINITY;
+    assert_eq!(0.0f32.to_radians(), 0.0);
+    assert_approx_eq!(154.6f32.to_radians(), 2.698279);
+    assert_approx_eq!((-332.31f32).to_radians(), -5.799903);
+    assert_eq!(180.0f32.to_radians(), pi);
+    assert!(nan.to_radians().is_nan());
+    assert_eq!(inf.to_radians(), inf);
+    assert_eq!(neg_inf.to_radians(), neg_inf);
+}
+
+#[test]
+fn test_float_bits_conv() {
+    assert_eq!((1f32).to_bits(), 0x3f800000);
+    assert_eq!((12.5f32).to_bits(), 0x41480000);
+    assert_eq!((1337f32).to_bits(), 0x44a72000);
+    assert_eq!((-14.25f32).to_bits(), 0xc1640000);
+    assert_approx_eq!(f32::from_bits(0x3f800000), 1.0);
+    assert_approx_eq!(f32::from_bits(0x41480000), 12.5);
+    assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
+    assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
+
+    // Check that NaNs roundtrip their bits regardless of signaling-ness
+    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+    let masked_nan1 = f32::NAN.to_bits() ^ NAN_MASK1;
+    let masked_nan2 = f32::NAN.to_bits() ^ NAN_MASK2;
+    assert!(f32::from_bits(masked_nan1).is_nan());
+    assert!(f32::from_bits(masked_nan2).is_nan());
+
+    assert_eq!(f32::from_bits(masked_nan1).to_bits(), masked_nan1);
+    assert_eq!(f32::from_bits(masked_nan2).to_bits(), masked_nan2);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_min_greater_than_max() {
+    let _ = 1.0f32.clamp(3.0, 1.0);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_min_is_nan() {
+    let _ = 1.0f32.clamp(f32::NAN, 1.0);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_max_is_nan() {
+    let _ = 1.0f32.clamp(3.0, f32::NAN);
+}
+
+#[test]
+fn test_total_cmp() {
+    use core::cmp::Ordering;
+
+    fn quiet_bit_mask() -> u32 {
+        1 << (f32::MANTISSA_DIGITS - 2)
+    }
+
+    fn min_subnorm() -> f32 {
+        f32::MIN_POSITIVE / f32::powf(2.0, f32::MANTISSA_DIGITS as f32 - 1.0)
+    }
+
+    fn max_subnorm() -> f32 {
+        f32::MIN_POSITIVE - min_subnorm()
+    }
+
+    fn q_nan() -> f32 {
+        f32::from_bits(f32::NAN.to_bits() | quiet_bit_mask())
+    }
+
+    fn s_nan() -> f32 {
+        f32::from_bits((f32::NAN.to_bits() & !quiet_bit_mask()) + 42)
+    }
+
+    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
+    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Equal, (-f32::INFINITY).total_cmp(&-f32::INFINITY));
+    assert_eq!(Ordering::Equal, (-f32::MAX).total_cmp(&-f32::MAX));
+    assert_eq!(Ordering::Equal, (-2.5_f32).total_cmp(&-2.5));
+    assert_eq!(Ordering::Equal, (-1.0_f32).total_cmp(&-1.0));
+    assert_eq!(Ordering::Equal, (-1.5_f32).total_cmp(&-1.5));
+    assert_eq!(Ordering::Equal, (-0.5_f32).total_cmp(&-0.5));
+    assert_eq!(Ordering::Equal, (-f32::MIN_POSITIVE).total_cmp(&-f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Equal, (-0.0_f32).total_cmp(&-0.0));
+    assert_eq!(Ordering::Equal, 0.0_f32.total_cmp(&0.0));
+    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Equal, f32::MIN_POSITIVE.total_cmp(&f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Equal, 0.5_f32.total_cmp(&0.5));
+    assert_eq!(Ordering::Equal, 1.0_f32.total_cmp(&1.0));
+    assert_eq!(Ordering::Equal, 1.5_f32.total_cmp(&1.5));
+    assert_eq!(Ordering::Equal, 2.5_f32.total_cmp(&2.5));
+    assert_eq!(Ordering::Equal, f32::MAX.total_cmp(&f32::MAX));
+    assert_eq!(Ordering::Equal, f32::INFINITY.total_cmp(&f32::INFINITY));
+    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
+    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
+
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::INFINITY));
+    assert_eq!(Ordering::Less, (-f32::INFINITY).total_cmp(&-f32::MAX));
+    assert_eq!(Ordering::Less, (-f32::MAX).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-2.5_f32).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-1.5_f32).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-1.0_f32).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-0.5_f32).total_cmp(&-f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-f32::MIN_POSITIVE).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-0.0_f32).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, 0.0_f32.total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, f32::MIN_POSITIVE.total_cmp(&0.5));
+    assert_eq!(Ordering::Less, 0.5_f32.total_cmp(&1.0));
+    assert_eq!(Ordering::Less, 1.0_f32.total_cmp(&1.5));
+    assert_eq!(Ordering::Less, 1.5_f32.total_cmp(&2.5));
+    assert_eq!(Ordering::Less, 2.5_f32.total_cmp(&f32::MAX));
+    assert_eq!(Ordering::Less, f32::MAX.total_cmp(&f32::INFINITY));
+    assert_eq!(Ordering::Less, f32::INFINITY.total_cmp(&s_nan()));
+    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
+
+    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
+    assert_eq!(Ordering::Greater, (-f32::INFINITY).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Greater, (-f32::MAX).total_cmp(&-f32::INFINITY));
+    assert_eq!(Ordering::Greater, (-2.5_f32).total_cmp(&-f32::MAX));
+    assert_eq!(Ordering::Greater, (-1.5_f32).total_cmp(&-2.5));
+    assert_eq!(Ordering::Greater, (-1.0_f32).total_cmp(&-1.5));
+    assert_eq!(Ordering::Greater, (-0.5_f32).total_cmp(&-1.0));
+    assert_eq!(Ordering::Greater, (-f32::MIN_POSITIVE).total_cmp(&-0.5));
+    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Greater, (-0.0_f32).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Greater, 0.0_f32.total_cmp(&-0.0));
+    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
+    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Greater, f32::MIN_POSITIVE.total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Greater, 0.5_f32.total_cmp(&f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Greater, 1.0_f32.total_cmp(&0.5));
+    assert_eq!(Ordering::Greater, 1.5_f32.total_cmp(&1.0));
+    assert_eq!(Ordering::Greater, 2.5_f32.total_cmp(&1.5));
+    assert_eq!(Ordering::Greater, f32::MAX.total_cmp(&2.5));
+    assert_eq!(Ordering::Greater, f32::INFINITY.total_cmp(&f32::MAX));
+    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f32::INFINITY));
+    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
+
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::INFINITY));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::MAX));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::MAX));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::INFINITY));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
+
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::INFINITY));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::MAX));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::MAX));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
+}
+
+#[test]
+fn test_algebraic() {
+    let a: f32 = 123.0;
+    let b: f32 = 456.0;
+
+    // Check that individual operations match their primitive counterparts.
+    //
+    // This is a check of current implementations and does NOT imply any form of
+    // guarantee about future behavior. The compiler reserves the right to make
+    // these operations inexact matches in the future.
+    let eps_add = if cfg!(miri) { 1e-3 } else { 0.0 };
+    let eps_mul = if cfg!(miri) { 1e-1 } else { 0.0 };
+    let eps_div = if cfg!(miri) { 1e-4 } else { 0.0 };
+
+    assert_approx_eq!(a.algebraic_add(b), a + b, eps_add);
+    assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add);
+    assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul);
+    assert_approx_eq!(a.algebraic_div(b), a / b, eps_div);
+    assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div);
+}
diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs
new file mode 100644
index 00000000000..988108371d7
--- /dev/null
+++ b/library/coretests/tests/floats/f64.rs
@@ -0,0 +1,682 @@
+use std::f64::consts;
+use std::num::FpCategory as Fp;
+
+/// Smallest number
+const TINY_BITS: u64 = 0x1;
+
+/// Next smallest number
+const TINY_UP_BITS: u64 = 0x2;
+
+/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
+const MAX_DOWN_BITS: u64 = 0x7fef_ffff_ffff_fffe;
+
+/// Zeroed exponent, full significant
+const LARGEST_SUBNORMAL_BITS: u64 = 0x000f_ffff_ffff_ffff;
+
+/// Exponent = 0b1, zeroed significand
+const SMALLEST_NORMAL_BITS: u64 = 0x0010_0000_0000_0000;
+
+/// First pattern over the mantissa
+const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa;
+
+/// Second pattern over the mantissa
+const NAN_MASK2: u64 = 0x0005_5555_5555_5555;
+
+#[allow(unused_macros)]
+macro_rules! assert_f64_biteq {
+    ($left : expr, $right : expr) => {
+        let l: &f64 = &$left;
+        let r: &f64 = &$right;
+        let lb = l.to_bits();
+        let rb = r.to_bits();
+        assert_eq!(lb, rb, "float {l} ({lb:#018x}) is not bitequal to {r} ({rb:#018x})");
+    };
+}
+
+#[test]
+fn test_num_f64() {
+    super::test_num(10f64, 2f64);
+}
+
+#[test]
+fn test_min_nan() {
+    assert_eq!(f64::NAN.min(2.0), 2.0);
+    assert_eq!(2.0f64.min(f64::NAN), 2.0);
+}
+
+#[test]
+fn test_max_nan() {
+    assert_eq!(f64::NAN.max(2.0), 2.0);
+    assert_eq!(2.0f64.max(f64::NAN), 2.0);
+}
+
+#[test]
+fn test_nan() {
+    let nan: f64 = f64::NAN;
+    assert!(nan.is_nan());
+    assert!(!nan.is_infinite());
+    assert!(!nan.is_finite());
+    assert!(!nan.is_normal());
+    assert!(nan.is_sign_positive());
+    assert!(!nan.is_sign_negative());
+    assert_eq!(Fp::Nan, nan.classify());
+    // Ensure the quiet bit is set.
+    assert!(nan.to_bits() & (1 << (f64::MANTISSA_DIGITS - 2)) != 0);
+}
+
+#[test]
+fn test_infinity() {
+    let inf: f64 = f64::INFINITY;
+    assert!(inf.is_infinite());
+    assert!(!inf.is_finite());
+    assert!(inf.is_sign_positive());
+    assert!(!inf.is_sign_negative());
+    assert!(!inf.is_nan());
+    assert!(!inf.is_normal());
+    assert_eq!(Fp::Infinite, inf.classify());
+}
+
+#[test]
+fn test_neg_infinity() {
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert!(neg_inf.is_infinite());
+    assert!(!neg_inf.is_finite());
+    assert!(!neg_inf.is_sign_positive());
+    assert!(neg_inf.is_sign_negative());
+    assert!(!neg_inf.is_nan());
+    assert!(!neg_inf.is_normal());
+    assert_eq!(Fp::Infinite, neg_inf.classify());
+}
+
+#[test]
+fn test_zero() {
+    let zero: f64 = 0.0f64;
+    assert_eq!(0.0, zero);
+    assert!(!zero.is_infinite());
+    assert!(zero.is_finite());
+    assert!(zero.is_sign_positive());
+    assert!(!zero.is_sign_negative());
+    assert!(!zero.is_nan());
+    assert!(!zero.is_normal());
+    assert_eq!(Fp::Zero, zero.classify());
+}
+
+#[test]
+fn test_neg_zero() {
+    let neg_zero: f64 = -0.0;
+    assert_eq!(0.0, neg_zero);
+    assert!(!neg_zero.is_infinite());
+    assert!(neg_zero.is_finite());
+    assert!(!neg_zero.is_sign_positive());
+    assert!(neg_zero.is_sign_negative());
+    assert!(!neg_zero.is_nan());
+    assert!(!neg_zero.is_normal());
+    assert_eq!(Fp::Zero, neg_zero.classify());
+}
+
+#[test]
+fn test_one() {
+    let one: f64 = 1.0f64;
+    assert_eq!(1.0, one);
+    assert!(!one.is_infinite());
+    assert!(one.is_finite());
+    assert!(one.is_sign_positive());
+    assert!(!one.is_sign_negative());
+    assert!(!one.is_nan());
+    assert!(one.is_normal());
+    assert_eq!(Fp::Normal, one.classify());
+}
+
+#[test]
+fn test_is_nan() {
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert!(nan.is_nan());
+    assert!(!0.0f64.is_nan());
+    assert!(!5.3f64.is_nan());
+    assert!(!(-10.732f64).is_nan());
+    assert!(!inf.is_nan());
+    assert!(!neg_inf.is_nan());
+}
+
+#[test]
+fn test_is_infinite() {
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert!(!nan.is_infinite());
+    assert!(inf.is_infinite());
+    assert!(neg_inf.is_infinite());
+    assert!(!0.0f64.is_infinite());
+    assert!(!42.8f64.is_infinite());
+    assert!(!(-109.2f64).is_infinite());
+}
+
+#[test]
+fn test_is_finite() {
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert!(!nan.is_finite());
+    assert!(!inf.is_finite());
+    assert!(!neg_inf.is_finite());
+    assert!(0.0f64.is_finite());
+    assert!(42.8f64.is_finite());
+    assert!((-109.2f64).is_finite());
+}
+
+#[test]
+fn test_is_normal() {
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    let zero: f64 = 0.0f64;
+    let neg_zero: f64 = -0.0;
+    assert!(!nan.is_normal());
+    assert!(!inf.is_normal());
+    assert!(!neg_inf.is_normal());
+    assert!(!zero.is_normal());
+    assert!(!neg_zero.is_normal());
+    assert!(1f64.is_normal());
+    assert!(1e-307f64.is_normal());
+    assert!(!1e-308f64.is_normal());
+}
+
+#[test]
+fn test_classify() {
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    let zero: f64 = 0.0f64;
+    let neg_zero: f64 = -0.0;
+    assert_eq!(nan.classify(), Fp::Nan);
+    assert_eq!(inf.classify(), Fp::Infinite);
+    assert_eq!(neg_inf.classify(), Fp::Infinite);
+    assert_eq!(zero.classify(), Fp::Zero);
+    assert_eq!(neg_zero.classify(), Fp::Zero);
+    assert_eq!(1e-307f64.classify(), Fp::Normal);
+    assert_eq!(1e-308f64.classify(), Fp::Subnormal);
+}
+
+#[test]
+fn test_floor() {
+    assert_approx_eq!(f64::floor(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::floor(1.3f64), 1.0f64);
+    assert_approx_eq!(f64::floor(1.5f64), 1.0f64);
+    assert_approx_eq!(f64::floor(1.7f64), 1.0f64);
+    assert_approx_eq!(f64::floor(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::floor(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::floor(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::floor(-1.3f64), -2.0f64);
+    assert_approx_eq!(f64::floor(-1.5f64), -2.0f64);
+    assert_approx_eq!(f64::floor(-1.7f64), -2.0f64);
+}
+
+#[test]
+fn test_ceil() {
+    assert_approx_eq!(f64::ceil(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::ceil(1.3f64), 2.0f64);
+    assert_approx_eq!(f64::ceil(1.5f64), 2.0f64);
+    assert_approx_eq!(f64::ceil(1.7f64), 2.0f64);
+    assert_approx_eq!(f64::ceil(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::ceil(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::ceil(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::ceil(-1.3f64), -1.0f64);
+    assert_approx_eq!(f64::ceil(-1.5f64), -1.0f64);
+    assert_approx_eq!(f64::ceil(-1.7f64), -1.0f64);
+}
+
+#[test]
+fn test_round() {
+    assert_approx_eq!(f64::round(2.5f64), 3.0f64);
+    assert_approx_eq!(f64::round(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::round(1.3f64), 1.0f64);
+    assert_approx_eq!(f64::round(1.5f64), 2.0f64);
+    assert_approx_eq!(f64::round(1.7f64), 2.0f64);
+    assert_approx_eq!(f64::round(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::round(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::round(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::round(-1.3f64), -1.0f64);
+    assert_approx_eq!(f64::round(-1.5f64), -2.0f64);
+    assert_approx_eq!(f64::round(-1.7f64), -2.0f64);
+}
+
+#[test]
+fn test_round_ties_even() {
+    assert_approx_eq!(f64::round_ties_even(2.5f64), 2.0f64);
+    assert_approx_eq!(f64::round_ties_even(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::round_ties_even(1.3f64), 1.0f64);
+    assert_approx_eq!(f64::round_ties_even(1.5f64), 2.0f64);
+    assert_approx_eq!(f64::round_ties_even(1.7f64), 2.0f64);
+    assert_approx_eq!(f64::round_ties_even(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::round_ties_even(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::round_ties_even(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::round_ties_even(-1.3f64), -1.0f64);
+    assert_approx_eq!(f64::round_ties_even(-1.5f64), -2.0f64);
+    assert_approx_eq!(f64::round_ties_even(-1.7f64), -2.0f64);
+}
+
+#[test]
+fn test_trunc() {
+    assert_approx_eq!(f64::trunc(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::trunc(1.3f64), 1.0f64);
+    assert_approx_eq!(f64::trunc(1.5f64), 1.0f64);
+    assert_approx_eq!(f64::trunc(1.7f64), 1.0f64);
+    assert_approx_eq!(f64::trunc(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::trunc(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::trunc(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::trunc(-1.3f64), -1.0f64);
+    assert_approx_eq!(f64::trunc(-1.5f64), -1.0f64);
+    assert_approx_eq!(f64::trunc(-1.7f64), -1.0f64);
+}
+
+#[test]
+fn test_fract() {
+    assert_approx_eq!(f64::fract(1.0f64), 0.0f64);
+    assert_approx_eq!(f64::fract(1.3f64), 0.3f64);
+    assert_approx_eq!(f64::fract(1.5f64), 0.5f64);
+    assert_approx_eq!(f64::fract(1.7f64), 0.7f64);
+    assert_approx_eq!(f64::fract(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::fract(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::fract(-1.0f64), -0.0f64);
+    assert_approx_eq!(f64::fract(-1.3f64), -0.3f64);
+    assert_approx_eq!(f64::fract(-1.5f64), -0.5f64);
+    assert_approx_eq!(f64::fract(-1.7f64), -0.7f64);
+}
+
+#[test]
+fn test_abs() {
+    assert_eq!(f64::INFINITY.abs(), f64::INFINITY);
+    assert_eq!(1f64.abs(), 1f64);
+    assert_eq!(0f64.abs(), 0f64);
+    assert_eq!((-0f64).abs(), 0f64);
+    assert_eq!((-1f64).abs(), 1f64);
+    assert_eq!(f64::NEG_INFINITY.abs(), f64::INFINITY);
+    assert_eq!((1f64 / f64::NEG_INFINITY).abs(), 0f64);
+    assert!(f64::NAN.abs().is_nan());
+}
+
+#[test]
+fn test_signum() {
+    assert_eq!(f64::INFINITY.signum(), 1f64);
+    assert_eq!(1f64.signum(), 1f64);
+    assert_eq!(0f64.signum(), 1f64);
+    assert_eq!((-0f64).signum(), -1f64);
+    assert_eq!((-1f64).signum(), -1f64);
+    assert_eq!(f64::NEG_INFINITY.signum(), -1f64);
+    assert_eq!((1f64 / f64::NEG_INFINITY).signum(), -1f64);
+    assert!(f64::NAN.signum().is_nan());
+}
+
+#[test]
+fn test_is_sign_positive() {
+    assert!(f64::INFINITY.is_sign_positive());
+    assert!(1f64.is_sign_positive());
+    assert!(0f64.is_sign_positive());
+    assert!(!(-0f64).is_sign_positive());
+    assert!(!(-1f64).is_sign_positive());
+    assert!(!f64::NEG_INFINITY.is_sign_positive());
+    assert!(!(1f64 / f64::NEG_INFINITY).is_sign_positive());
+    assert!(f64::NAN.is_sign_positive());
+    assert!(!(-f64::NAN).is_sign_positive());
+}
+
+#[test]
+fn test_is_sign_negative() {
+    assert!(!f64::INFINITY.is_sign_negative());
+    assert!(!1f64.is_sign_negative());
+    assert!(!0f64.is_sign_negative());
+    assert!((-0f64).is_sign_negative());
+    assert!((-1f64).is_sign_negative());
+    assert!(f64::NEG_INFINITY.is_sign_negative());
+    assert!((1f64 / f64::NEG_INFINITY).is_sign_negative());
+    assert!(!f64::NAN.is_sign_negative());
+    assert!((-f64::NAN).is_sign_negative());
+}
+
+#[test]
+fn test_next_up() {
+    let tiny = f64::from_bits(TINY_BITS);
+    let tiny_up = f64::from_bits(TINY_UP_BITS);
+    let max_down = f64::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
+    assert_f64_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN);
+    assert_f64_biteq!(f64::MIN.next_up(), -max_down);
+    assert_f64_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0);
+    assert_f64_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_f64_biteq!((-tiny_up).next_up(), -tiny);
+    assert_f64_biteq!((-tiny).next_up(), -0.0f64);
+    assert_f64_biteq!((-0.0f64).next_up(), tiny);
+    assert_f64_biteq!(0.0f64.next_up(), tiny);
+    assert_f64_biteq!(tiny.next_up(), tiny_up);
+    assert_f64_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_f64_biteq!(1.0f64.next_up(), 1.0 + f64::EPSILON);
+    assert_f64_biteq!(f64::MAX.next_up(), f64::INFINITY);
+    assert_f64_biteq!(f64::INFINITY.next_up(), f64::INFINITY);
+
+    let nan0 = f64::NAN;
+    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
+    assert_f64_biteq!(nan0.next_up(), nan0);
+    assert_f64_biteq!(nan1.next_up(), nan1);
+    assert_f64_biteq!(nan2.next_up(), nan2);
+}
+
+#[test]
+fn test_next_down() {
+    let tiny = f64::from_bits(TINY_BITS);
+    let tiny_up = f64::from_bits(TINY_UP_BITS);
+    let max_down = f64::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
+    assert_f64_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
+    assert_f64_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY);
+    assert_f64_biteq!((-max_down).next_down(), f64::MIN);
+    assert_f64_biteq!((-1.0f64).next_down(), -1.0 - f64::EPSILON);
+    assert_f64_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_f64_biteq!((-tiny).next_down(), -tiny_up);
+    assert_f64_biteq!((-0.0f64).next_down(), -tiny);
+    assert_f64_biteq!((0.0f64).next_down(), -tiny);
+    assert_f64_biteq!(tiny.next_down(), 0.0f64);
+    assert_f64_biteq!(tiny_up.next_down(), tiny);
+    assert_f64_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_f64_biteq!((1.0 + f64::EPSILON).next_down(), 1.0f64);
+    assert_f64_biteq!(f64::MAX.next_down(), max_down);
+    assert_f64_biteq!(f64::INFINITY.next_down(), f64::MAX);
+
+    let nan0 = f64::NAN;
+    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
+    assert_f64_biteq!(nan0.next_down(), nan0);
+    assert_f64_biteq!(nan1.next_down(), nan1);
+    assert_f64_biteq!(nan2.next_down(), nan2);
+}
+
+// FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
+#[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)]
+#[test]
+fn test_mul_add() {
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05);
+    assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65);
+    assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2);
+    assert_approx_eq!(3.4f64.mul_add(-0.0, 5.6), 5.6);
+    assert!(nan.mul_add(7.8, 9.0).is_nan());
+    assert_eq!(inf.mul_add(7.8, 9.0), inf);
+    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_eq!(8.9f64.mul_add(inf, 3.2), inf);
+    assert_eq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf);
+}
+
+#[test]
+fn test_recip() {
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert_eq!(1.0f64.recip(), 1.0);
+    assert_eq!(2.0f64.recip(), 0.5);
+    assert_eq!((-0.4f64).recip(), -2.5);
+    assert_eq!(0.0f64.recip(), inf);
+    assert!(nan.recip().is_nan());
+    assert_eq!(inf.recip(), 0.0);
+    assert_eq!(neg_inf.recip(), 0.0);
+}
+
+#[test]
+fn test_powi() {
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert_eq!(1.0f64.powi(1), 1.0);
+    assert_approx_eq!((-3.1f64).powi(2), 9.61);
+    assert_approx_eq!(5.9f64.powi(-2), 0.028727);
+    assert_eq!(8.3f64.powi(0), 1.0);
+    assert!(nan.powi(2).is_nan());
+    assert_eq!(inf.powi(3), inf);
+    assert_eq!(neg_inf.powi(2), inf);
+}
+
+#[test]
+fn test_sqrt_domain() {
+    assert!(f64::NAN.sqrt().is_nan());
+    assert!(f64::NEG_INFINITY.sqrt().is_nan());
+    assert!((-1.0f64).sqrt().is_nan());
+    assert_eq!((-0.0f64).sqrt(), -0.0);
+    assert_eq!(0.0f64.sqrt(), 0.0);
+    assert_eq!(1.0f64.sqrt(), 1.0);
+    assert_eq!(f64::INFINITY.sqrt(), f64::INFINITY);
+}
+
+#[test]
+fn test_to_degrees() {
+    let pi: f64 = consts::PI;
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert_eq!(0.0f64.to_degrees(), 0.0);
+    assert_approx_eq!((-5.8f64).to_degrees(), -332.315521);
+    assert_eq!(pi.to_degrees(), 180.0);
+    assert!(nan.to_degrees().is_nan());
+    assert_eq!(inf.to_degrees(), inf);
+    assert_eq!(neg_inf.to_degrees(), neg_inf);
+}
+
+#[test]
+fn test_to_radians() {
+    let pi: f64 = consts::PI;
+    let nan: f64 = f64::NAN;
+    let inf: f64 = f64::INFINITY;
+    let neg_inf: f64 = f64::NEG_INFINITY;
+    assert_eq!(0.0f64.to_radians(), 0.0);
+    assert_approx_eq!(154.6f64.to_radians(), 2.698279);
+    assert_approx_eq!((-332.31f64).to_radians(), -5.799903);
+    assert_eq!(180.0f64.to_radians(), pi);
+    assert!(nan.to_radians().is_nan());
+    assert_eq!(inf.to_radians(), inf);
+    assert_eq!(neg_inf.to_radians(), neg_inf);
+}
+
+#[test]
+fn test_float_bits_conv() {
+    assert_eq!((1f64).to_bits(), 0x3ff0000000000000);
+    assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
+    assert_eq!((1337f64).to_bits(), 0x4094e40000000000);
+    assert_eq!((-14.25f64).to_bits(), 0xc02c800000000000);
+    assert_approx_eq!(f64::from_bits(0x3ff0000000000000), 1.0);
+    assert_approx_eq!(f64::from_bits(0x4029000000000000), 12.5);
+    assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
+    assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
+
+    // Check that NaNs roundtrip their bits regardless of signaling-ness
+    let masked_nan1 = f64::NAN.to_bits() ^ NAN_MASK1;
+    let masked_nan2 = f64::NAN.to_bits() ^ NAN_MASK2;
+    assert!(f64::from_bits(masked_nan1).is_nan());
+    assert!(f64::from_bits(masked_nan2).is_nan());
+
+    assert_eq!(f64::from_bits(masked_nan1).to_bits(), masked_nan1);
+    assert_eq!(f64::from_bits(masked_nan2).to_bits(), masked_nan2);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_min_greater_than_max() {
+    let _ = 1.0f64.clamp(3.0, 1.0);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_min_is_nan() {
+    let _ = 1.0f64.clamp(f64::NAN, 1.0);
+}
+
+#[test]
+#[should_panic]
+fn test_clamp_max_is_nan() {
+    let _ = 1.0f64.clamp(3.0, f64::NAN);
+}
+
+#[test]
+fn test_total_cmp() {
+    use core::cmp::Ordering;
+
+    fn quiet_bit_mask() -> u64 {
+        1 << (f64::MANTISSA_DIGITS - 2)
+    }
+
+    fn min_subnorm() -> f64 {
+        f64::MIN_POSITIVE / f64::powf(2.0, f64::MANTISSA_DIGITS as f64 - 1.0)
+    }
+
+    fn max_subnorm() -> f64 {
+        f64::MIN_POSITIVE - min_subnorm()
+    }
+
+    fn q_nan() -> f64 {
+        f64::from_bits(f64::NAN.to_bits() | quiet_bit_mask())
+    }
+
+    fn s_nan() -> f64 {
+        f64::from_bits((f64::NAN.to_bits() & !quiet_bit_mask()) + 42)
+    }
+
+    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
+    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Equal, (-f64::INFINITY).total_cmp(&-f64::INFINITY));
+    assert_eq!(Ordering::Equal, (-f64::MAX).total_cmp(&-f64::MAX));
+    assert_eq!(Ordering::Equal, (-2.5_f64).total_cmp(&-2.5));
+    assert_eq!(Ordering::Equal, (-1.0_f64).total_cmp(&-1.0));
+    assert_eq!(Ordering::Equal, (-1.5_f64).total_cmp(&-1.5));
+    assert_eq!(Ordering::Equal, (-0.5_f64).total_cmp(&-0.5));
+    assert_eq!(Ordering::Equal, (-f64::MIN_POSITIVE).total_cmp(&-f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Equal, (-0.0_f64).total_cmp(&-0.0));
+    assert_eq!(Ordering::Equal, 0.0_f64.total_cmp(&0.0));
+    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Equal, f64::MIN_POSITIVE.total_cmp(&f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Equal, 0.5_f64.total_cmp(&0.5));
+    assert_eq!(Ordering::Equal, 1.0_f64.total_cmp(&1.0));
+    assert_eq!(Ordering::Equal, 1.5_f64.total_cmp(&1.5));
+    assert_eq!(Ordering::Equal, 2.5_f64.total_cmp(&2.5));
+    assert_eq!(Ordering::Equal, f64::MAX.total_cmp(&f64::MAX));
+    assert_eq!(Ordering::Equal, f64::INFINITY.total_cmp(&f64::INFINITY));
+    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
+    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
+
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::INFINITY));
+    assert_eq!(Ordering::Less, (-f64::INFINITY).total_cmp(&-f64::MAX));
+    assert_eq!(Ordering::Less, (-f64::MAX).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-2.5_f64).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-1.5_f64).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-1.0_f64).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-0.5_f64).total_cmp(&-f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-f64::MIN_POSITIVE).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-0.0_f64).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, 0.0_f64.total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, f64::MIN_POSITIVE.total_cmp(&0.5));
+    assert_eq!(Ordering::Less, 0.5_f64.total_cmp(&1.0));
+    assert_eq!(Ordering::Less, 1.0_f64.total_cmp(&1.5));
+    assert_eq!(Ordering::Less, 1.5_f64.total_cmp(&2.5));
+    assert_eq!(Ordering::Less, 2.5_f64.total_cmp(&f64::MAX));
+    assert_eq!(Ordering::Less, f64::MAX.total_cmp(&f64::INFINITY));
+    assert_eq!(Ordering::Less, f64::INFINITY.total_cmp(&s_nan()));
+    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
+
+    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
+    assert_eq!(Ordering::Greater, (-f64::INFINITY).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Greater, (-f64::MAX).total_cmp(&-f64::INFINITY));
+    assert_eq!(Ordering::Greater, (-2.5_f64).total_cmp(&-f64::MAX));
+    assert_eq!(Ordering::Greater, (-1.5_f64).total_cmp(&-2.5));
+    assert_eq!(Ordering::Greater, (-1.0_f64).total_cmp(&-1.5));
+    assert_eq!(Ordering::Greater, (-0.5_f64).total_cmp(&-1.0));
+    assert_eq!(Ordering::Greater, (-f64::MIN_POSITIVE).total_cmp(&-0.5));
+    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Greater, (-0.0_f64).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Greater, 0.0_f64.total_cmp(&-0.0));
+    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
+    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Greater, f64::MIN_POSITIVE.total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Greater, 0.5_f64.total_cmp(&f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Greater, 1.0_f64.total_cmp(&0.5));
+    assert_eq!(Ordering::Greater, 1.5_f64.total_cmp(&1.0));
+    assert_eq!(Ordering::Greater, 2.5_f64.total_cmp(&1.5));
+    assert_eq!(Ordering::Greater, f64::MAX.total_cmp(&2.5));
+    assert_eq!(Ordering::Greater, f64::INFINITY.total_cmp(&f64::MAX));
+    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f64::INFINITY));
+    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
+
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::INFINITY));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::MAX));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::MAX));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::INFINITY));
+    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
+
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::INFINITY));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::MAX));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::MIN_POSITIVE));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::MAX));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY));
+    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
+}
+
+#[test]
+fn test_algebraic() {
+    let a: f64 = 123.0;
+    let b: f64 = 456.0;
+
+    // Check that individual operations match their primitive counterparts.
+    //
+    // This is a check of current implementations and does NOT imply any form of
+    // guarantee about future behavior. The compiler reserves the right to make
+    // these operations inexact matches in the future.
+    let eps = if cfg!(miri) { 1e-6 } else { 0.0 };
+
+    assert_approx_eq!(a.algebraic_add(b), a + b, eps);
+    assert_approx_eq!(a.algebraic_sub(b), a - b, eps);
+    assert_approx_eq!(a.algebraic_mul(b), a * b, eps);
+    assert_approx_eq!(a.algebraic_div(b), a / b, eps);
+    assert_approx_eq!(a.algebraic_rem(b), a % b, eps);
+}
diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs
new file mode 100644
index 00000000000..7de34271ad0
--- /dev/null
+++ b/library/coretests/tests/floats/mod.rs
@@ -0,0 +1,40 @@
+use std::fmt;
+use std::ops::{Add, Div, Mul, Rem, Sub};
+
+/// Verify that floats are within a tolerance of each other, 1.0e-6 by default.
+macro_rules! assert_approx_eq {
+    ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }};
+    ($a:expr, $b:expr, $lim:expr) => {{
+        let (a, b) = (&$a, &$b);
+        let diff = (*a - *b).abs();
+        assert!(
+            diff <= $lim,
+            "{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})",
+            lim = $lim
+        );
+    }};
+}
+
+/// Helper function for testing numeric operations
+pub fn test_num<T>(ten: T, two: T)
+where
+    T: PartialEq
+        + Add<Output = T>
+        + Sub<Output = T>
+        + Mul<Output = T>
+        + Div<Output = T>
+        + Rem<Output = T>
+        + fmt::Debug
+        + Copy,
+{
+    assert_eq!(ten.add(two), ten + two);
+    assert_eq!(ten.sub(two), ten - two);
+    assert_eq!(ten.mul(two), ten * two);
+    assert_eq!(ten.div(two), ten / two);
+    assert_eq!(ten.rem(two), ten % two);
+}
+
+mod f128;
+mod f16;
+mod f32;
+mod f64;
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 0575375cf4f..b98e52718f6 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -12,10 +12,12 @@
 #![feature(async_iterator)]
 #![feature(bigint_helper_methods)]
 #![feature(bstr)]
+#![feature(cfg_target_has_reliable_f16_f128)]
 #![feature(char_max_len)]
 #![feature(clone_to_uninit)]
 #![feature(const_eval_select)]
 #![feature(const_trait_impl)]
+#![feature(core_float_math)]
 #![feature(core_intrinsics)]
 #![feature(core_intrinsics_fallbacks)]
 #![feature(core_io_borrowed_buf)]
@@ -29,6 +31,10 @@
 #![feature(exact_size_is_empty)]
 #![feature(extend_one)]
 #![feature(extern_types)]
+#![feature(f128)]
+#![feature(f16)]
+#![feature(float_algebraic)]
+#![feature(float_gamma)]
 #![feature(float_minimum_maximum)]
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
@@ -144,6 +150,7 @@ mod cmp;
 mod const_ptr;
 mod convert;
 mod ffi;
+mod floats;
 mod fmt;
 mod future;
 mod hash;
diff --git a/library/coretests/tests/num/dec2flt/decimal.rs b/library/coretests/tests/num/dec2flt/decimal.rs
index 1fa06de692e..f759e1dbde6 100644
--- a/library/coretests/tests/num/dec2flt/decimal.rs
+++ b/library/coretests/tests/num/dec2flt/decimal.rs
@@ -7,6 +7,20 @@ const FPATHS_F32: &[FPath<f32>] =
 const FPATHS_F64: &[FPath<f64>] =
     &[((0, 0, false, false), Some(0.0)), ((0, 0, false, false), Some(0.0))];
 
+// FIXME(f16_f128): enable on all targets once possible.
+#[test]
+#[cfg(target_has_reliable_f16)]
+fn check_fast_path_f16() {
+    const FPATHS_F16: &[FPath<f16>] =
+        &[((0, 0, false, false), Some(0.0)), ((0, 0, false, false), Some(0.0))];
+    for ((exponent, mantissa, negative, many_digits), expected) in FPATHS_F16.iter().copied() {
+        let dec = Decimal { exponent, mantissa, negative, many_digits };
+        let actual = dec.try_fast_path::<f16>();
+
+        assert_eq!(actual, expected);
+    }
+}
+
 #[test]
 fn check_fast_path_f32() {
     for ((exponent, mantissa, negative, many_digits), expected) in FPATHS_F32.iter().copied() {
diff --git a/library/coretests/tests/num/dec2flt/float.rs b/library/coretests/tests/num/dec2flt/float.rs
index b5afd3e3b24..264de061be9 100644
--- a/library/coretests/tests/num/dec2flt/float.rs
+++ b/library/coretests/tests/num/dec2flt/float.rs
@@ -1,5 +1,24 @@
 use core::num::dec2flt::float::RawFloat;
 
+// FIXME(f16_f128): enable on all targets once possible.
+#[test]
+#[cfg(target_has_reliable_f16)]
+fn test_f16_integer_decode() {
+    assert_eq!(3.14159265359f16.integer_decode(), (1608, -9, 1));
+    assert_eq!((-8573.5918555f16).integer_decode(), (1072, 3, -1));
+    #[cfg(not(miri))] // miri doesn't have powf16
+    assert_eq!(2f16.powf(14.0).integer_decode(), (1 << 10, 4, 1));
+    assert_eq!(0f16.integer_decode(), (0, -25, 1));
+    assert_eq!((-0f16).integer_decode(), (0, -25, -1));
+    assert_eq!(f16::INFINITY.integer_decode(), (1 << 10, 6, 1));
+    assert_eq!(f16::NEG_INFINITY.integer_decode(), (1 << 10, 6, -1));
+
+    // Ignore the "sign" (quiet / signalling flag) of NAN.
+    // It can vary between runtime operations and LLVM folding.
+    let (nan_m, nan_p, _nan_s) = f16::NAN.integer_decode();
+    assert_eq!((nan_m, nan_p), (1536, 6));
+}
+
 #[test]
 fn test_f32_integer_decode() {
     assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1));
@@ -34,6 +53,27 @@ fn test_f64_integer_decode() {
 
 /* Sanity checks of computed magic numbers */
 
+// FIXME(f16_f128): enable on all targets once possible.
+#[test]
+#[cfg(target_has_reliable_f16)]
+fn test_f16_consts() {
+    assert_eq!(<f16 as RawFloat>::INFINITY, f16::INFINITY);
+    assert_eq!(<f16 as RawFloat>::NEG_INFINITY, -f16::INFINITY);
+    assert_eq!(<f16 as RawFloat>::NAN.to_bits(), f16::NAN.to_bits());
+    assert_eq!(<f16 as RawFloat>::NEG_NAN.to_bits(), (-f16::NAN).to_bits());
+    assert_eq!(<f16 as RawFloat>::SIG_BITS, 10);
+    assert_eq!(<f16 as RawFloat>::MIN_EXPONENT_ROUND_TO_EVEN, -22);
+    assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_ROUND_TO_EVEN, 5);
+    assert_eq!(<f16 as RawFloat>::MIN_EXPONENT_FAST_PATH, -4);
+    assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_FAST_PATH, 4);
+    assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_DISGUISED_FAST_PATH, 7);
+    assert_eq!(<f16 as RawFloat>::EXP_MIN, -14);
+    assert_eq!(<f16 as RawFloat>::EXP_SAT, 0x1f);
+    assert_eq!(<f16 as RawFloat>::SMALLEST_POWER_OF_TEN, -27);
+    assert_eq!(<f16 as RawFloat>::LARGEST_POWER_OF_TEN, 4);
+    assert_eq!(<f16 as RawFloat>::MAX_MANTISSA_FAST_PATH, 2048);
+}
+
 #[test]
 fn test_f32_consts() {
     assert_eq!(<f32 as RawFloat>::INFINITY, f32::INFINITY);
diff --git a/library/coretests/tests/num/dec2flt/lemire.rs b/library/coretests/tests/num/dec2flt/lemire.rs
index 0db80fbd525..6d49d85170e 100644
--- a/library/coretests/tests/num/dec2flt/lemire.rs
+++ b/library/coretests/tests/num/dec2flt/lemire.rs
@@ -1,6 +1,12 @@
 use core::num::dec2flt::float::RawFloat;
 use core::num::dec2flt::lemire::compute_float;
 
+#[cfg(target_has_reliable_f16)]
+fn compute_float16(q: i64, w: u64) -> (i32, u64) {
+    let fp = compute_float::<f16>(q, w);
+    (fp.p_biased, fp.m)
+}
+
 fn compute_float32(q: i64, w: u64) -> (i32, u64) {
     let fp = compute_float::<f32>(q, w);
     (fp.p_biased, fp.m)
@@ -11,23 +17,73 @@ fn compute_float64(q: i64, w: u64) -> (i32, u64) {
     (fp.p_biased, fp.m)
 }
 
+// FIXME(f16_f128): enable on all targets once possible.
+#[test]
+#[cfg(target_has_reliable_f16)]
+fn compute_float_f16_rounding() {
+    // The maximum integer that cna be converted to a `f16` without lost precision.
+    let val = 1 << 11;
+    let scale = 10_u64.pow(10);
+
+    // These test near-halfway cases for half-precision floats.
+    assert_eq!(compute_float16(0, val), (26, 0));
+    assert_eq!(compute_float16(0, val + 1), (26, 0));
+    assert_eq!(compute_float16(0, val + 2), (26, 1));
+    assert_eq!(compute_float16(0, val + 3), (26, 2));
+    assert_eq!(compute_float16(0, val + 4), (26, 2));
+
+    // For the next power up, the two nearest representable numbers are twice as far apart.
+    let val2 = 1 << 12;
+    assert_eq!(compute_float16(0, val2), (27, 0));
+    assert_eq!(compute_float16(0, val2 + 2), (27, 0));
+    assert_eq!(compute_float16(0, val2 + 4), (27, 1));
+    assert_eq!(compute_float16(0, val2 + 6), (27, 2));
+    assert_eq!(compute_float16(0, val2 + 8), (27, 2));
+
+    // These are examples of the above tests, with digits from the exponent shifted
+    // to the mantissa.
+    assert_eq!(compute_float16(-10, val * scale), (26, 0));
+    assert_eq!(compute_float16(-10, (val + 1) * scale), (26, 0));
+    assert_eq!(compute_float16(-10, (val + 2) * scale), (26, 1));
+    // Let's check the lines to see if anything is different in table...
+    assert_eq!(compute_float16(-10, (val + 3) * scale), (26, 2));
+    assert_eq!(compute_float16(-10, (val + 4) * scale), (26, 2));
+
+    // Check the rounding point between infinity and the next representable number down
+    assert_eq!(compute_float16(4, 6), (f16::INFINITE_POWER - 1, 851));
+    assert_eq!(compute_float16(4, 7), (f16::INFINITE_POWER, 0)); // infinity
+    assert_eq!(compute_float16(2, 655), (f16::INFINITE_POWER - 1, 1023));
+}
+
 #[test]
 fn compute_float_f32_rounding() {
+    // the maximum integer that cna be converted to a `f32` without lost precision.
+    let val = 1 << 24;
+    let scale = 10_u64.pow(10);
+
     // These test near-halfway cases for single-precision floats.
-    assert_eq!(compute_float32(0, 16777216), (151, 0));
-    assert_eq!(compute_float32(0, 16777217), (151, 0));
-    assert_eq!(compute_float32(0, 16777218), (151, 1));
-    assert_eq!(compute_float32(0, 16777219), (151, 2));
-    assert_eq!(compute_float32(0, 16777220), (151, 2));
-
-    // These are examples of the above tests, with
-    // digits from the exponent shifted to the mantissa.
-    assert_eq!(compute_float32(-10, 167772160000000000), (151, 0));
-    assert_eq!(compute_float32(-10, 167772170000000000), (151, 0));
-    assert_eq!(compute_float32(-10, 167772180000000000), (151, 1));
+    assert_eq!(compute_float32(0, val), (151, 0));
+    assert_eq!(compute_float32(0, val + 1), (151, 0));
+    assert_eq!(compute_float32(0, val + 2), (151, 1));
+    assert_eq!(compute_float32(0, val + 3), (151, 2));
+    assert_eq!(compute_float32(0, val + 4), (151, 2));
+
+    // For the next power up, the two nearest representable numbers are twice as far apart.
+    let val2 = 1 << 25;
+    assert_eq!(compute_float32(0, val2), (152, 0));
+    assert_eq!(compute_float32(0, val2 + 2), (152, 0));
+    assert_eq!(compute_float32(0, val2 + 4), (152, 1));
+    assert_eq!(compute_float32(0, val2 + 6), (152, 2));
+    assert_eq!(compute_float32(0, val2 + 8), (152, 2));
+
+    // These are examples of the above tests, with digits from the exponent shifted
+    // to the mantissa.
+    assert_eq!(compute_float32(-10, val * scale), (151, 0));
+    assert_eq!(compute_float32(-10, (val + 1) * scale), (151, 0));
+    assert_eq!(compute_float32(-10, (val + 2) * scale), (151, 1));
     // Let's check the lines to see if anything is different in table...
-    assert_eq!(compute_float32(-10, 167772190000000000), (151, 2));
-    assert_eq!(compute_float32(-10, 167772200000000000), (151, 2));
+    assert_eq!(compute_float32(-10, (val + 3) * scale), (151, 2));
+    assert_eq!(compute_float32(-10, (val + 4) * scale), (151, 2));
 
     // Check the rounding point between infinity and the next representable number down
     assert_eq!(compute_float32(38, 3), (f32::INFINITE_POWER - 1, 6402534));
@@ -37,23 +93,38 @@ fn compute_float_f32_rounding() {
 
 #[test]
 fn compute_float_f64_rounding() {
+    // The maximum integer that cna be converted to a `f64` without lost precision.
+    let val = 1 << 53;
+    let scale = 1000;
+
     // These test near-halfway cases for double-precision floats.
-    assert_eq!(compute_float64(0, 9007199254740992), (1076, 0));
-    assert_eq!(compute_float64(0, 9007199254740993), (1076, 0));
-    assert_eq!(compute_float64(0, 9007199254740994), (1076, 1));
-    assert_eq!(compute_float64(0, 9007199254740995), (1076, 2));
-    assert_eq!(compute_float64(0, 9007199254740996), (1076, 2));
-    assert_eq!(compute_float64(0, 18014398509481984), (1077, 0));
-    assert_eq!(compute_float64(0, 18014398509481986), (1077, 0));
-    assert_eq!(compute_float64(0, 18014398509481988), (1077, 1));
-    assert_eq!(compute_float64(0, 18014398509481990), (1077, 2));
-    assert_eq!(compute_float64(0, 18014398509481992), (1077, 2));
-
-    // These are examples of the above tests, with
-    // digits from the exponent shifted to the mantissa.
-    assert_eq!(compute_float64(-3, 9007199254740992000), (1076, 0));
-    assert_eq!(compute_float64(-3, 9007199254740993000), (1076, 0));
-    assert_eq!(compute_float64(-3, 9007199254740994000), (1076, 1));
-    assert_eq!(compute_float64(-3, 9007199254740995000), (1076, 2));
-    assert_eq!(compute_float64(-3, 9007199254740996000), (1076, 2));
+    assert_eq!(compute_float64(0, val), (1076, 0));
+    assert_eq!(compute_float64(0, val + 1), (1076, 0));
+    assert_eq!(compute_float64(0, val + 2), (1076, 1));
+    assert_eq!(compute_float64(0, val + 3), (1076, 2));
+    assert_eq!(compute_float64(0, val + 4), (1076, 2));
+
+    // For the next power up, the two nearest representable numbers are twice as far apart.
+    let val2 = 1 << 54;
+    assert_eq!(compute_float64(0, val2), (1077, 0));
+    assert_eq!(compute_float64(0, val2 + 2), (1077, 0));
+    assert_eq!(compute_float64(0, val2 + 4), (1077, 1));
+    assert_eq!(compute_float64(0, val2 + 6), (1077, 2));
+    assert_eq!(compute_float64(0, val2 + 8), (1077, 2));
+
+    // These are examples of the above tests, with digits from the exponent shifted
+    // to the mantissa.
+    assert_eq!(compute_float64(-3, val * scale), (1076, 0));
+    assert_eq!(compute_float64(-3, (val + 1) * scale), (1076, 0));
+    assert_eq!(compute_float64(-3, (val + 2) * scale), (1076, 1));
+    assert_eq!(compute_float64(-3, (val + 3) * scale), (1076, 2));
+    assert_eq!(compute_float64(-3, (val + 4) * scale), (1076, 2));
+
+    // Check the rounding point between infinity and the next representable number down
+    assert_eq!(compute_float64(308, 1), (f64::INFINITE_POWER - 1, 506821272651936));
+    assert_eq!(compute_float64(308, 2), (f64::INFINITE_POWER, 0)); // infinity
+    assert_eq!(
+        compute_float64(292, 17976931348623157),
+        (f64::INFINITE_POWER - 1, 4503599627370495)
+    );
 }
diff --git a/library/coretests/tests/num/dec2flt/mod.rs b/library/coretests/tests/num/dec2flt/mod.rs
index a9025be5ca7..b8ca220847c 100644
--- a/library/coretests/tests/num/dec2flt/mod.rs
+++ b/library/coretests/tests/num/dec2flt/mod.rs
@@ -11,15 +11,23 @@ mod parse;
 // Requires a *polymorphic literal*, i.e., one that can serve as f64 as well as f32.
 macro_rules! test_literal {
     ($x: expr) => {{
+        #[cfg(target_has_reliable_f16)]
+        let x16: f16 = $x;
         let x32: f32 = $x;
         let x64: f64 = $x;
         let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
+
         for input in inputs {
-            assert_eq!(input.parse(), Ok(x64));
-            assert_eq!(input.parse(), Ok(x32));
+            assert_eq!(input.parse(), Ok(x64), "failed f64 {input}");
+            assert_eq!(input.parse(), Ok(x32), "failed f32 {input}");
+            #[cfg(target_has_reliable_f16)]
+            assert_eq!(input.parse(), Ok(x16), "failed f16 {input}");
+
             let neg_input = format!("-{input}");
-            assert_eq!(neg_input.parse(), Ok(-x64));
-            assert_eq!(neg_input.parse(), Ok(-x32));
+            assert_eq!(neg_input.parse(), Ok(-x64), "failed f64 {neg_input}");
+            assert_eq!(neg_input.parse(), Ok(-x32), "failed f32 {neg_input}");
+            #[cfg(target_has_reliable_f16)]
+            assert_eq!(neg_input.parse(), Ok(-x16), "failed f16 {neg_input}");
         }
     }};
 }
@@ -84,48 +92,87 @@ fn fast_path_correct() {
     test_literal!(1.448997445238699);
 }
 
+// FIXME(f16_f128): remove gates once tests work on all targets
+
 #[test]
 fn lonely_dot() {
+    #[cfg(target_has_reliable_f16)]
+    assert!(".".parse::<f16>().is_err());
     assert!(".".parse::<f32>().is_err());
     assert!(".".parse::<f64>().is_err());
 }
 
 #[test]
 fn exponentiated_dot() {
+    #[cfg(target_has_reliable_f16)]
+    assert!(".e0".parse::<f16>().is_err());
     assert!(".e0".parse::<f32>().is_err());
     assert!(".e0".parse::<f64>().is_err());
 }
 
 #[test]
 fn lonely_sign() {
-    assert!("+".parse::<f32>().is_err());
-    assert!("-".parse::<f64>().is_err());
+    #[cfg(target_has_reliable_f16)]
+    assert!("+".parse::<f16>().is_err());
+    assert!("-".parse::<f32>().is_err());
+    assert!("+".parse::<f64>().is_err());
 }
 
 #[test]
 fn whitespace() {
+    #[cfg(target_has_reliable_f16)]
+    assert!("1.0 ".parse::<f16>().is_err());
     assert!(" 1.0".parse::<f32>().is_err());
     assert!("1.0 ".parse::<f64>().is_err());
 }
 
 #[test]
 fn nan() {
+    #[cfg(target_has_reliable_f16)]
+    {
+        assert!("NaN".parse::<f16>().unwrap().is_nan());
+        assert!("-NaN".parse::<f16>().unwrap().is_nan());
+    }
+
     assert!("NaN".parse::<f32>().unwrap().is_nan());
+    assert!("-NaN".parse::<f32>().unwrap().is_nan());
+
     assert!("NaN".parse::<f64>().unwrap().is_nan());
+    assert!("-NaN".parse::<f64>().unwrap().is_nan());
 }
 
 #[test]
 fn inf() {
-    assert_eq!("inf".parse(), Ok(f64::INFINITY));
-    assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
+    #[cfg(target_has_reliable_f16)]
+    {
+        assert_eq!("inf".parse(), Ok(f16::INFINITY));
+        assert_eq!("-inf".parse(), Ok(f16::NEG_INFINITY));
+    }
+
     assert_eq!("inf".parse(), Ok(f32::INFINITY));
     assert_eq!("-inf".parse(), Ok(f32::NEG_INFINITY));
+
+    assert_eq!("inf".parse(), Ok(f64::INFINITY));
+    assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
 }
 
 #[test]
 fn massive_exponent() {
+    #[cfg(target_has_reliable_f16)]
+    {
+        let max = i16::MAX;
+        assert_eq!(format!("1e{max}000").parse(), Ok(f16::INFINITY));
+        assert_eq!(format!("1e-{max}000").parse(), Ok(0.0f16));
+        assert_eq!(format!("1e{max}000").parse(), Ok(f16::INFINITY));
+    }
+
+    let max = i32::MAX;
+    assert_eq!(format!("1e{max}000").parse(), Ok(f32::INFINITY));
+    assert_eq!(format!("1e-{max}000").parse(), Ok(0.0f32));
+    assert_eq!(format!("1e{max}000").parse(), Ok(f32::INFINITY));
+
     let max = i64::MAX;
     assert_eq!(format!("1e{max}000").parse(), Ok(f64::INFINITY));
-    assert_eq!(format!("1e-{max}000").parse(), Ok(0.0));
+    assert_eq!(format!("1e-{max}000").parse(), Ok(0.0f64));
     assert_eq!(format!("1e{max}000").parse(), Ok(f64::INFINITY));
 }
diff --git a/library/coretests/tests/num/dec2flt/parse.rs b/library/coretests/tests/num/dec2flt/parse.rs
index 59be3915052..dccb6b5528d 100644
--- a/library/coretests/tests/num/dec2flt/parse.rs
+++ b/library/coretests/tests/num/dec2flt/parse.rs
@@ -10,6 +10,9 @@ fn new_dec(e: i64, m: u64) -> Decimal {
 fn missing_pieces() {
     let permutations = &[".e", "1e", "e4", "e", ".12e", "321.e", "32.12e+", "12.32e-"];
     for &s in permutations {
+        #[cfg(target_has_reliable_f16)]
+        assert_eq!(dec2flt::<f16>(s), Err(pfe_invalid()));
+        assert_eq!(dec2flt::<f32>(s), Err(pfe_invalid()));
         assert_eq!(dec2flt::<f64>(s), Err(pfe_invalid()));
     }
 }
@@ -17,15 +20,31 @@ fn missing_pieces() {
 #[test]
 fn invalid_chars() {
     let invalid = "r,?<j";
-    let error = Err(pfe_invalid());
     let valid_strings = &["123", "666.", ".1", "5e1", "7e-3", "0.0e+1"];
+
     for c in invalid.chars() {
         for s in valid_strings {
             for i in 0..s.len() {
                 let mut input = String::new();
                 input.push_str(s);
                 input.insert(i, c);
-                assert!(dec2flt::<f64>(&input) == error, "did not reject invalid {:?}", input);
+
+                #[cfg(target_has_reliable_f16)]
+                assert_eq!(
+                    dec2flt::<f16>(&input),
+                    Err(pfe_invalid()),
+                    "f16 did not reject invalid {input:?}",
+                );
+                assert_eq!(
+                    dec2flt::<f32>(&input),
+                    Err(pfe_invalid()),
+                    "f32 did not reject invalid {input:?}",
+                );
+                assert_eq!(
+                    dec2flt::<f64>(&input),
+                    Err(pfe_invalid()),
+                    "f64 did not reject invalid {input:?}",
+                );
             }
         }
     }
diff --git a/library/coretests/tests/num/flt2dec/mod.rs b/library/coretests/tests/num/flt2dec/mod.rs
index c64bb0a3072..ce36db33d05 100644
--- a/library/coretests/tests/num/flt2dec/mod.rs
+++ b/library/coretests/tests/num/flt2dec/mod.rs
@@ -16,7 +16,7 @@ mod random;
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
         FullDecoded::Finite(decoded) => decoded,
-        full_decoded => panic!("expected finite, got {full_decoded:?} instead"),
+        full_decoded => panic!("expected finite, got {full_decoded:?} instead for {v:?}"),
     }
 }
 
@@ -75,6 +75,11 @@ macro_rules! try_fixed {
     })
 }
 
+#[cfg(target_has_reliable_f16)]
+fn ldexp_f16(a: f16, b: i32) -> f16 {
+    ldexp_f64(a as f64, b) as f16
+}
+
 fn ldexp_f32(a: f32, b: i32) -> f32 {
     ldexp_f64(a as f64, b) as f32
 }
@@ -176,6 +181,13 @@ trait TestableFloat: DecodableFloat + fmt::Display {
     fn ldexpi(f: i64, exp: isize) -> Self;
 }
 
+#[cfg(target_has_reliable_f16)]
+impl TestableFloat for f16 {
+    fn ldexpi(f: i64, exp: isize) -> Self {
+        f as Self * (exp as Self).exp2()
+    }
+}
+
 impl TestableFloat for f32 {
     fn ldexpi(f: i64, exp: isize) -> Self {
         f as Self * (exp as Self).exp2()
@@ -225,6 +237,76 @@ macro_rules! check_exact_one {
 //
 // [1] Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion
 //     ftp://ftp.ee.lbl.gov/testbase-report.ps.Z
+//  or https://www.icir.org/vern/papers/testbase-report.pdf
+
+#[cfg(target_has_reliable_f16)]
+pub fn f16_shortest_sanity_test<F>(mut f: F)
+where
+    F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
+{
+    // 0.0999145507813
+    // 0.0999755859375
+    // 0.100036621094
+    check_shortest!(f(0.1f16) => b"1", 0);
+
+    // 0.3330078125
+    // 0.333251953125 (1/3 in the default rounding)
+    // 0.33349609375
+    check_shortest!(f(1.0f16/3.0) => b"3333", 0);
+
+    // 10^1 * 0.3138671875
+    // 10^1 * 0.3140625
+    // 10^1 * 0.3142578125
+    check_shortest!(f(3.14f16) => b"314", 1);
+
+    // 10^18 * 0.31415916243714048
+    // 10^18 * 0.314159196796878848
+    // 10^18 * 0.314159231156617216
+    check_shortest!(f(3.1415e4f16) => b"3141", 5);
+
+    // regression test for decoders
+    // 10^2 * 0.31984375
+    // 10^2 * 0.32
+    // 10^2 * 0.3203125
+    check_shortest!(f(ldexp_f16(1.0, 5)) => b"32", 2);
+
+    // 10^5 * 0.65472
+    // 10^5 * 0.65504
+    // 10^5 * 0.65536
+    check_shortest!(f(f16::MAX) => b"655", 5);
+
+    // 10^-4 * 0.60975551605224609375
+    // 10^-4 * 0.6103515625
+    // 10^-4 * 0.61094760894775390625
+    check_shortest!(f(f16::MIN_POSITIVE) => b"6104", -4);
+
+    // 10^-9 * 0
+    // 10^-9 * 0.59604644775390625
+    // 10^-8 * 0.11920928955078125
+    let minf16 = ldexp_f16(1.0, -24);
+    check_shortest!(f(minf16) => b"6", -7);
+}
+
+#[cfg(target_has_reliable_f16)]
+pub fn f16_exact_sanity_test<F>(mut f: F)
+where
+    F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
+{
+    let minf16 = ldexp_f16(1.0, -24);
+
+    check_exact!(f(0.1f16)            => b"999755859375     ", -1);
+    check_exact!(f(0.5f16)            => b"5                ", 0);
+    check_exact!(f(1.0f16/3.0)        => b"333251953125     ", 0);
+    check_exact!(f(3.141f16)          => b"3140625          ", 1);
+    check_exact!(f(3.141e4f16)        => b"31408            ", 5);
+    check_exact!(f(f16::MAX)          => b"65504            ", 5);
+    check_exact!(f(f16::MIN_POSITIVE) => b"6103515625       ", -4);
+    check_exact!(f(minf16)            => b"59604644775390625", -7);
+
+    // FIXME(f16_f128): these should gain the check_exact_one tests like `f32` and `f64` have,
+    // but these values are not easy to generate. The algorithm from the Paxon paper [1] needs
+    // to be adapted to binary16.
+}
 
 pub fn f32_shortest_sanity_test<F>(mut f: F)
 where
@@ -553,23 +635,45 @@ where
     assert_eq!(to_string(f, 1.9971e20, Minus, 1), "199710000000000000000.0");
     assert_eq!(to_string(f, 1.9971e20, Minus, 8), "199710000000000000000.00000000");
 
-    assert_eq!(to_string(f, f32::MAX, Minus, 0), format!("34028235{:0>31}", ""));
-    assert_eq!(to_string(f, f32::MAX, Minus, 1), format!("34028235{:0>31}.0", ""));
-    assert_eq!(to_string(f, f32::MAX, Minus, 8), format!("34028235{:0>31}.00000000", ""));
-
-    let minf32 = ldexp_f32(1.0, -149);
-    assert_eq!(to_string(f, minf32, Minus, 0), format!("0.{:0>44}1", ""));
-    assert_eq!(to_string(f, minf32, Minus, 45), format!("0.{:0>44}1", ""));
-    assert_eq!(to_string(f, minf32, Minus, 46), format!("0.{:0>44}10", ""));
+    #[cfg(target_has_reliable_f16)]
+    {
+        // f16
+        assert_eq!(to_string(f, f16::MAX, Minus, 0), "65500");
+        assert_eq!(to_string(f, f16::MAX, Minus, 1), "65500.0");
+        assert_eq!(to_string(f, f16::MAX, Minus, 8), "65500.00000000");
+
+        let minf16 = ldexp_f16(1.0, -24);
+        assert_eq!(to_string(f, minf16, Minus, 0), "0.00000006");
+        assert_eq!(to_string(f, minf16, Minus, 8), "0.00000006");
+        assert_eq!(to_string(f, minf16, Minus, 9), "0.000000060");
+    }
 
-    assert_eq!(to_string(f, f64::MAX, Minus, 0), format!("17976931348623157{:0>292}", ""));
-    assert_eq!(to_string(f, f64::MAX, Minus, 1), format!("17976931348623157{:0>292}.0", ""));
-    assert_eq!(to_string(f, f64::MAX, Minus, 8), format!("17976931348623157{:0>292}.00000000", ""));
+    {
+        // f32
+        assert_eq!(to_string(f, f32::MAX, Minus, 0), format!("34028235{:0>31}", ""));
+        assert_eq!(to_string(f, f32::MAX, Minus, 1), format!("34028235{:0>31}.0", ""));
+        assert_eq!(to_string(f, f32::MAX, Minus, 8), format!("34028235{:0>31}.00000000", ""));
+
+        let minf32 = ldexp_f32(1.0, -149);
+        assert_eq!(to_string(f, minf32, Minus, 0), format!("0.{:0>44}1", ""));
+        assert_eq!(to_string(f, minf32, Minus, 45), format!("0.{:0>44}1", ""));
+        assert_eq!(to_string(f, minf32, Minus, 46), format!("0.{:0>44}10", ""));
+    }
 
-    let minf64 = ldexp_f64(1.0, -1074);
-    assert_eq!(to_string(f, minf64, Minus, 0), format!("0.{:0>323}5", ""));
-    assert_eq!(to_string(f, minf64, Minus, 324), format!("0.{:0>323}5", ""));
-    assert_eq!(to_string(f, minf64, Minus, 325), format!("0.{:0>323}50", ""));
+    {
+        // f64
+        assert_eq!(to_string(f, f64::MAX, Minus, 0), format!("17976931348623157{:0>292}", ""));
+        assert_eq!(to_string(f, f64::MAX, Minus, 1), format!("17976931348623157{:0>292}.0", ""));
+        assert_eq!(
+            to_string(f, f64::MAX, Minus, 8),
+            format!("17976931348623157{:0>292}.00000000", "")
+        );
+
+        let minf64 = ldexp_f64(1.0, -1074);
+        assert_eq!(to_string(f, minf64, Minus, 0), format!("0.{:0>323}5", ""));
+        assert_eq!(to_string(f, minf64, Minus, 324), format!("0.{:0>323}5", ""));
+        assert_eq!(to_string(f, minf64, Minus, 325), format!("0.{:0>323}50", ""));
+    }
 
     if cfg!(miri) {
         // Miri is too slow
@@ -655,27 +759,45 @@ where
     assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), "100000000000000000000000");
     assert_eq!(to_string(f, 1.0e23, Minus, (24, 25), false), "1e23");
 
-    assert_eq!(to_string(f, f32::MAX, Minus, (-4, 16), false), "3.4028235e38");
-    assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38");
-    assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", ""));
-
-    let minf32 = ldexp_f32(1.0, -149);
-    assert_eq!(to_string(f, minf32, Minus, (-4, 16), false), "1e-45");
-    assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45");
-    assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", ""));
-
-    assert_eq!(to_string(f, f64::MAX, Minus, (-4, 16), false), "1.7976931348623157e308");
-    assert_eq!(
-        to_string(f, f64::MAX, Minus, (-308, 309), false),
-        format!("17976931348623157{:0>292}", "")
-    );
-    assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false), "1.7976931348623157e308");
+    #[cfg(target_has_reliable_f16)]
+    {
+        // f16
+        assert_eq!(to_string(f, f16::MAX, Minus, (-2, 2), false), "6.55e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, (-4, 4), false), "6.55e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, (-5, 5), false), "65500");
+
+        let minf16 = ldexp_f16(1.0, -24);
+        assert_eq!(to_string(f, minf16, Minus, (-2, 2), false), "6e-8");
+        assert_eq!(to_string(f, minf16, Minus, (-7, 7), false), "6e-8");
+        assert_eq!(to_string(f, minf16, Minus, (-8, 8), false), "0.00000006");
+    }
 
-    let minf64 = ldexp_f64(1.0, -1074);
-    assert_eq!(to_string(f, minf64, Minus, (-4, 16), false), "5e-324");
-    assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", ""));
-    assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324");
+    {
+        // f32
+        assert_eq!(to_string(f, f32::MAX, Minus, (-4, 16), false), "3.4028235e38");
+        assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38");
+        assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", ""));
+
+        let minf32 = ldexp_f32(1.0, -149);
+        assert_eq!(to_string(f, minf32, Minus, (-4, 16), false), "1e-45");
+        assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45");
+        assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", ""));
+    }
 
+    {
+        // f64
+        assert_eq!(to_string(f, f64::MAX, Minus, (-4, 16), false), "1.7976931348623157e308");
+        assert_eq!(
+            to_string(f, f64::MAX, Minus, (-308, 309), false),
+            format!("17976931348623157{:0>292}", "")
+        );
+        assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false), "1.7976931348623157e308");
+
+        let minf64 = ldexp_f64(1.0, -1074);
+        assert_eq!(to_string(f, minf64, Minus, (-4, 16), false), "5e-324");
+        assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", ""));
+        assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324");
+    }
     assert_eq!(to_string(f, 1.1, Minus, (i16::MIN, i16::MAX), false), "1.1");
 }
 
@@ -791,6 +913,26 @@ where
         "9.999999999999999547481118258862586856139387236908078193664550781250000e-7"
     );
 
+    #[cfg(target_has_reliable_f16)]
+    {
+        assert_eq!(to_string(f, f16::MAX, Minus, 1, false), "7e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 2, false), "6.6e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 4, false), "6.550e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 5, false), "6.5504e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 6, false), "6.55040e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 16, false), "6.550400000000000e4");
+
+        let minf16 = ldexp_f16(1.0, -24);
+        assert_eq!(to_string(f, minf16, Minus, 1, false), "6e-8");
+        assert_eq!(to_string(f, minf16, Minus, 2, false), "6.0e-8");
+        assert_eq!(to_string(f, minf16, Minus, 4, false), "5.960e-8");
+        assert_eq!(to_string(f, minf16, Minus, 8, false), "5.9604645e-8");
+        assert_eq!(to_string(f, minf16, Minus, 16, false), "5.960464477539062e-8");
+        assert_eq!(to_string(f, minf16, Minus, 17, false), "5.9604644775390625e-8");
+        assert_eq!(to_string(f, minf16, Minus, 18, false), "5.96046447753906250e-8");
+        assert_eq!(to_string(f, minf16, Minus, 24, false), "5.96046447753906250000000e-8");
+    }
+
     assert_eq!(to_string(f, f32::MAX, Minus, 1, false), "3e38");
     assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "3.4e38");
     assert_eq!(to_string(f, f32::MAX, Minus, 4, false), "3.403e38");
@@ -1069,6 +1211,13 @@ where
         "0.000000999999999999999954748111825886258685613938723690807819366455078125000"
     );
 
+    #[cfg(target_has_reliable_f16)]
+    {
+        assert_eq!(to_string(f, f16::MAX, Minus, 0), "65504");
+        assert_eq!(to_string(f, f16::MAX, Minus, 1), "65504.0");
+        assert_eq!(to_string(f, f16::MAX, Minus, 2), "65504.00");
+    }
+
     assert_eq!(to_string(f, f32::MAX, Minus, 0), "340282346638528859811704183484516925440");
     assert_eq!(to_string(f, f32::MAX, Minus, 1), "340282346638528859811704183484516925440.0");
     assert_eq!(to_string(f, f32::MAX, Minus, 2), "340282346638528859811704183484516925440.00");
@@ -1078,6 +1227,21 @@ where
         return;
     }
 
+    #[cfg(target_has_reliable_f16)]
+    {
+        let minf16 = ldexp_f16(1.0, -24);
+        assert_eq!(to_string(f, minf16, Minus, 0), "0");
+        assert_eq!(to_string(f, minf16, Minus, 1), "0.0");
+        assert_eq!(to_string(f, minf16, Minus, 2), "0.00");
+        assert_eq!(to_string(f, minf16, Minus, 4), "0.0000");
+        assert_eq!(to_string(f, minf16, Minus, 8), "0.00000006");
+        assert_eq!(to_string(f, minf16, Minus, 10), "0.0000000596");
+        assert_eq!(to_string(f, minf16, Minus, 15), "0.000000059604645");
+        assert_eq!(to_string(f, minf16, Minus, 20), "0.00000005960464477539");
+        assert_eq!(to_string(f, minf16, Minus, 24), "0.000000059604644775390625");
+        assert_eq!(to_string(f, minf16, Minus, 32), "0.00000005960464477539062500000000");
+    }
+
     let minf32 = ldexp_f32(1.0, -149);
     assert_eq!(to_string(f, minf32, Minus, 0), "0");
     assert_eq!(to_string(f, minf32, Minus, 1), "0.0");
diff --git a/library/coretests/tests/num/flt2dec/random.rs b/library/coretests/tests/num/flt2dec/random.rs
index 586b49df7d9..7386139aace 100644
--- a/library/coretests/tests/num/flt2dec/random.rs
+++ b/library/coretests/tests/num/flt2dec/random.rs
@@ -79,6 +79,20 @@ where
     (npassed, nignored)
 }
 
+#[cfg(target_has_reliable_f16)]
+pub fn f16_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
+where
+    F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>,
+    G: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
+{
+    let mut rng = crate::test_rng();
+    let f16_range = Uniform::new(0x0001u16, 0x7c00).unwrap();
+    iterate("f16_random_equivalence_test", k, n, f, g, |_| {
+        let x = f16::from_bits(f16_range.sample(&mut rng));
+        decode_finite(x)
+    });
+}
+
 pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
 where
     F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>,
@@ -105,6 +119,24 @@ where
     });
 }
 
+#[cfg(target_has_reliable_f16)]
+pub fn f16_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
+where
+    F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>,
+    G: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
+{
+    // Unlike the other float types, `f16` is small enough that these exhaustive tests
+    // can run in less than a second so we don't need to ignore it.
+
+    // iterate from 0x0001 to 0x7bff, i.e., all finite ranges
+    let (npassed, nignored) =
+        iterate("f16_exhaustive_equivalence_test", k, 0x7bff, f, g, |i: usize| {
+            let x = f16::from_bits(i as u16 + 1);
+            decode_finite(x)
+        });
+    assert_eq!((npassed, nignored), (29735, 2008));
+}
+
 pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
 where
     F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>,
@@ -133,6 +165,17 @@ fn shortest_random_equivalence_test() {
 
     f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, n);
     f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, n);
+    #[cfg(target_has_reliable_f16)]
+    f16_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, n);
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Miri is to slow
+#[cfg(target_has_reliable_f16)]
+fn shortest_f16_exhaustive_equivalence_test() {
+    // see the f32 version
+    use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+    f16_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
 }
 
 #[test]
@@ -159,6 +202,23 @@ fn shortest_f64_hard_random_equivalence_test() {
 }
 
 #[test]
+#[cfg(target_has_reliable_f16)]
+fn exact_f16_random_equivalence_test() {
+    use core::num::flt2dec::strategy::dragon::format_exact as fallback;
+    // Miri is too slow
+    let n = if cfg!(miri) { 3 } else { 1_000 };
+
+    for k in 1..21 {
+        f16_random_equivalence_test(
+            |d, buf| format_exact_opt(d, buf, i16::MIN),
+            |d, buf| fallback(d, buf, i16::MIN),
+            k,
+            n,
+        );
+    }
+}
+
+#[test]
 fn exact_f32_random_equivalence_test() {
     use core::num::flt2dec::strategy::dragon::format_exact as fallback;
     // Miri is too slow
diff --git a/library/coretests/tests/num/flt2dec/strategy/dragon.rs b/library/coretests/tests/num/flt2dec/strategy/dragon.rs
index be25fee3f6c..43bb6024f9c 100644
--- a/library/coretests/tests/num/flt2dec/strategy/dragon.rs
+++ b/library/coretests/tests/num/flt2dec/strategy/dragon.rs
@@ -18,6 +18,8 @@ fn test_mul_pow10() {
 fn shortest_sanity_test() {
     f64_shortest_sanity_test(format_shortest);
     f32_shortest_sanity_test(format_shortest);
+    #[cfg(target_has_reliable_f16)]
+    f16_shortest_sanity_test(format_shortest);
     more_shortest_sanity_test(format_shortest);
 }
 
@@ -41,6 +43,9 @@ fn exact_sanity_test() {
         f64_exact_sanity_test(format_exact);
     }
     f32_exact_sanity_test(format_exact);
+
+    #[cfg(target_has_reliable_f16)]
+    f16_exact_sanity_test(format_exact);
 }
 
 #[test]
diff --git a/library/coretests/tests/num/flt2dec/strategy/grisu.rs b/library/coretests/tests/num/flt2dec/strategy/grisu.rs
index 9b2f0453de7..117191e0c8f 100644
--- a/library/coretests/tests/num/flt2dec/strategy/grisu.rs
+++ b/library/coretests/tests/num/flt2dec/strategy/grisu.rs
@@ -38,6 +38,8 @@ fn test_max_pow10_no_more_than() {
 fn shortest_sanity_test() {
     f64_shortest_sanity_test(format_shortest);
     f32_shortest_sanity_test(format_shortest);
+    #[cfg(target_has_reliable_f16)]
+    f16_shortest_sanity_test(format_shortest);
     more_shortest_sanity_test(format_shortest);
 }
 
@@ -50,6 +52,8 @@ fn exact_sanity_test() {
         f64_exact_sanity_test(format_exact);
     }
     f32_exact_sanity_test(format_exact);
+    #[cfg(target_has_reliable_f16)]
+    f16_exact_sanity_test(format_exact);
 }
 
 #[test]
diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs
index 0add9a01e68..a6b75f70266 100644
--- a/library/coretests/tests/num/mod.rs
+++ b/library/coretests/tests/num/mod.rs
@@ -732,157 +732,157 @@ assume_usize_width! {
 }
 
 macro_rules! test_float {
-    ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
+    ($modname: ident, $fassert: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
         mod $modname {
             #[test]
             fn min() {
-                assert_eq!((0.0 as $fty).min(0.0), 0.0);
-                assert!((0.0 as $fty).min(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).min(-0.0), -0.0);
-                assert!((-0.0 as $fty).min(-0.0).is_sign_negative());
-                assert_eq!((9.0 as $fty).min(9.0), 9.0);
-                assert_eq!((-9.0 as $fty).min(0.0), -9.0);
-                assert_eq!((0.0 as $fty).min(9.0), 0.0);
-                assert!((0.0 as $fty).min(9.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).min(9.0), -0.0);
-                assert!((-0.0 as $fty).min(9.0).is_sign_negative());
-                assert_eq!((-0.0 as $fty).min(-9.0), -9.0);
-                assert_eq!(($inf as $fty).min(9.0), 9.0);
-                assert_eq!((9.0 as $fty).min($inf), 9.0);
-                assert_eq!(($inf as $fty).min(-9.0), -9.0);
-                assert_eq!((-9.0 as $fty).min($inf), -9.0);
-                assert_eq!(($neginf as $fty).min(9.0), $neginf);
-                assert_eq!((9.0 as $fty).min($neginf), $neginf);
-                assert_eq!(($neginf as $fty).min(-9.0), $neginf);
-                assert_eq!((-9.0 as $fty).min($neginf), $neginf);
-                assert_eq!(($nan as $fty).min(9.0), 9.0);
-                assert_eq!(($nan as $fty).min(-9.0), -9.0);
-                assert_eq!((9.0 as $fty).min($nan), 9.0);
-                assert_eq!((-9.0 as $fty).min($nan), -9.0);
-                assert!(($nan as $fty).min($nan).is_nan());
+                $fassert!((0.0 as $fty).min(0.0), 0.0);
+                $fassert!((0.0 as $fty).min(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).min(-0.0), -0.0);
+                $fassert!((-0.0 as $fty).min(-0.0).is_sign_negative());
+                $fassert!((9.0 as $fty).min(9.0), 9.0);
+                $fassert!((-9.0 as $fty).min(0.0), -9.0);
+                $fassert!((0.0 as $fty).min(9.0), 0.0);
+                $fassert!((0.0 as $fty).min(9.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).min(9.0), -0.0);
+                $fassert!((-0.0 as $fty).min(9.0).is_sign_negative());
+                $fassert!((-0.0 as $fty).min(-9.0), -9.0);
+                $fassert!(($inf as $fty).min(9.0), 9.0);
+                $fassert!((9.0 as $fty).min($inf), 9.0);
+                $fassert!(($inf as $fty).min(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).min($inf), -9.0);
+                $fassert!(($neginf as $fty).min(9.0), $neginf);
+                $fassert!((9.0 as $fty).min($neginf), $neginf);
+                $fassert!(($neginf as $fty).min(-9.0), $neginf);
+                $fassert!((-9.0 as $fty).min($neginf), $neginf);
+                $fassert!(($nan as $fty).min(9.0), 9.0);
+                $fassert!(($nan as $fty).min(-9.0), -9.0);
+                $fassert!((9.0 as $fty).min($nan), 9.0);
+                $fassert!((-9.0 as $fty).min($nan), -9.0);
+                $fassert!(($nan as $fty).min($nan).is_nan());
             }
             #[test]
             fn max() {
-                assert_eq!((0.0 as $fty).max(0.0), 0.0);
-                assert!((0.0 as $fty).max(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).max(-0.0), -0.0);
-                assert!((-0.0 as $fty).max(-0.0).is_sign_negative());
-                assert_eq!((9.0 as $fty).max(9.0), 9.0);
-                assert_eq!((-9.0 as $fty).max(0.0), 0.0);
-                assert!((-9.0 as $fty).max(0.0).is_sign_positive());
-                assert_eq!((-9.0 as $fty).max(-0.0), -0.0);
-                assert!((-9.0 as $fty).max(-0.0).is_sign_negative());
-                assert_eq!((0.0 as $fty).max(9.0), 9.0);
-                assert_eq!((0.0 as $fty).max(-9.0), 0.0);
-                assert!((0.0 as $fty).max(-9.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).max(-9.0), -0.0);
-                assert!((-0.0 as $fty).max(-9.0).is_sign_negative());
-                assert_eq!(($inf as $fty).max(9.0), $inf);
-                assert_eq!((9.0 as $fty).max($inf), $inf);
-                assert_eq!(($inf as $fty).max(-9.0), $inf);
-                assert_eq!((-9.0 as $fty).max($inf), $inf);
-                assert_eq!(($neginf as $fty).max(9.0), 9.0);
-                assert_eq!((9.0 as $fty).max($neginf), 9.0);
-                assert_eq!(($neginf as $fty).max(-9.0), -9.0);
-                assert_eq!((-9.0 as $fty).max($neginf), -9.0);
-                assert_eq!(($nan as $fty).max(9.0), 9.0);
-                assert_eq!(($nan as $fty).max(-9.0), -9.0);
-                assert_eq!((9.0 as $fty).max($nan), 9.0);
-                assert_eq!((-9.0 as $fty).max($nan), -9.0);
-                assert!(($nan as $fty).max($nan).is_nan());
+                $fassert!((0.0 as $fty).max(0.0), 0.0);
+                $fassert!((0.0 as $fty).max(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).max(-0.0), -0.0);
+                $fassert!((-0.0 as $fty).max(-0.0).is_sign_negative());
+                $fassert!((9.0 as $fty).max(9.0), 9.0);
+                $fassert!((-9.0 as $fty).max(0.0), 0.0);
+                $fassert!((-9.0 as $fty).max(0.0).is_sign_positive());
+                $fassert!((-9.0 as $fty).max(-0.0), -0.0);
+                $fassert!((-9.0 as $fty).max(-0.0).is_sign_negative());
+                $fassert!((0.0 as $fty).max(9.0), 9.0);
+                $fassert!((0.0 as $fty).max(-9.0), 0.0);
+                $fassert!((0.0 as $fty).max(-9.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).max(-9.0), -0.0);
+                $fassert!((-0.0 as $fty).max(-9.0).is_sign_negative());
+                $fassert!(($inf as $fty).max(9.0), $inf);
+                $fassert!((9.0 as $fty).max($inf), $inf);
+                $fassert!(($inf as $fty).max(-9.0), $inf);
+                $fassert!((-9.0 as $fty).max($inf), $inf);
+                $fassert!(($neginf as $fty).max(9.0), 9.0);
+                $fassert!((9.0 as $fty).max($neginf), 9.0);
+                $fassert!(($neginf as $fty).max(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).max($neginf), -9.0);
+                $fassert!(($nan as $fty).max(9.0), 9.0);
+                $fassert!(($nan as $fty).max(-9.0), -9.0);
+                $fassert!((9.0 as $fty).max($nan), 9.0);
+                $fassert!((-9.0 as $fty).max($nan), -9.0);
+                $fassert!(($nan as $fty).max($nan).is_nan());
             }
             #[test]
             fn minimum() {
-                assert_eq!((0.0 as $fty).minimum(0.0), 0.0);
-                assert!((0.0 as $fty).minimum(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).minimum(0.0), -0.0);
-                assert!((-0.0 as $fty).minimum(0.0).is_sign_negative());
-                assert_eq!((-0.0 as $fty).minimum(-0.0), -0.0);
-                assert!((-0.0 as $fty).minimum(-0.0).is_sign_negative());
-                assert_eq!((9.0 as $fty).minimum(9.0), 9.0);
-                assert_eq!((-9.0 as $fty).minimum(0.0), -9.0);
-                assert_eq!((0.0 as $fty).minimum(9.0), 0.0);
-                assert!((0.0 as $fty).minimum(9.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).minimum(9.0), -0.0);
-                assert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
-                assert_eq!((-0.0 as $fty).minimum(-9.0), -9.0);
-                assert_eq!(($inf as $fty).minimum(9.0), 9.0);
-                assert_eq!((9.0 as $fty).minimum($inf), 9.0);
-                assert_eq!(($inf as $fty).minimum(-9.0), -9.0);
-                assert_eq!((-9.0 as $fty).minimum($inf), -9.0);
-                assert_eq!(($neginf as $fty).minimum(9.0), $neginf);
-                assert_eq!((9.0 as $fty).minimum($neginf), $neginf);
-                assert_eq!(($neginf as $fty).minimum(-9.0), $neginf);
-                assert_eq!((-9.0 as $fty).minimum($neginf), $neginf);
-                assert!(($nan as $fty).minimum(9.0).is_nan());
-                assert!(($nan as $fty).minimum(-9.0).is_nan());
-                assert!((9.0 as $fty).minimum($nan).is_nan());
-                assert!((-9.0 as $fty).minimum($nan).is_nan());
-                assert!(($nan as $fty).minimum($nan).is_nan());
+                $fassert!((0.0 as $fty).minimum(0.0), 0.0);
+                $fassert!((0.0 as $fty).minimum(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).minimum(0.0), -0.0);
+                $fassert!((-0.0 as $fty).minimum(0.0).is_sign_negative());
+                $fassert!((-0.0 as $fty).minimum(-0.0), -0.0);
+                $fassert!((-0.0 as $fty).minimum(-0.0).is_sign_negative());
+                $fassert!((9.0 as $fty).minimum(9.0), 9.0);
+                $fassert!((-9.0 as $fty).minimum(0.0), -9.0);
+                $fassert!((0.0 as $fty).minimum(9.0), 0.0);
+                $fassert!((0.0 as $fty).minimum(9.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).minimum(9.0), -0.0);
+                $fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
+                $fassert!((-0.0 as $fty).minimum(-9.0), -9.0);
+                $fassert!(($inf as $fty).minimum(9.0), 9.0);
+                $fassert!((9.0 as $fty).minimum($inf), 9.0);
+                $fassert!(($inf as $fty).minimum(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).minimum($inf), -9.0);
+                $fassert!(($neginf as $fty).minimum(9.0), $neginf);
+                $fassert!((9.0 as $fty).minimum($neginf), $neginf);
+                $fassert!(($neginf as $fty).minimum(-9.0), $neginf);
+                $fassert!((-9.0 as $fty).minimum($neginf), $neginf);
+                $fassert!(($nan as $fty).minimum(9.0).is_nan());
+                $fassert!(($nan as $fty).minimum(-9.0).is_nan());
+                $fassert!((9.0 as $fty).minimum($nan).is_nan());
+                $fassert!((-9.0 as $fty).minimum($nan).is_nan());
+                $fassert!(($nan as $fty).minimum($nan).is_nan());
             }
             #[test]
             fn maximum() {
-                assert_eq!((0.0 as $fty).maximum(0.0), 0.0);
-                assert!((0.0 as $fty).maximum(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).maximum(0.0), 0.0);
-                assert!((-0.0 as $fty).maximum(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).maximum(-0.0), -0.0);
-                assert!((-0.0 as $fty).maximum(-0.0).is_sign_negative());
-                assert_eq!((9.0 as $fty).maximum(9.0), 9.0);
-                assert_eq!((-9.0 as $fty).maximum(0.0), 0.0);
-                assert!((-9.0 as $fty).maximum(0.0).is_sign_positive());
-                assert_eq!((-9.0 as $fty).maximum(-0.0), -0.0);
-                assert!((-9.0 as $fty).maximum(-0.0).is_sign_negative());
-                assert_eq!((0.0 as $fty).maximum(9.0), 9.0);
-                assert_eq!((0.0 as $fty).maximum(-9.0), 0.0);
-                assert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).maximum(-9.0), -0.0);
-                assert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
-                assert_eq!(($inf as $fty).maximum(9.0), $inf);
-                assert_eq!((9.0 as $fty).maximum($inf), $inf);
-                assert_eq!(($inf as $fty).maximum(-9.0), $inf);
-                assert_eq!((-9.0 as $fty).maximum($inf), $inf);
-                assert_eq!(($neginf as $fty).maximum(9.0), 9.0);
-                assert_eq!((9.0 as $fty).maximum($neginf), 9.0);
-                assert_eq!(($neginf as $fty).maximum(-9.0), -9.0);
-                assert_eq!((-9.0 as $fty).maximum($neginf), -9.0);
-                assert!(($nan as $fty).maximum(9.0).is_nan());
-                assert!(($nan as $fty).maximum(-9.0).is_nan());
-                assert!((9.0 as $fty).maximum($nan).is_nan());
-                assert!((-9.0 as $fty).maximum($nan).is_nan());
-                assert!(($nan as $fty).maximum($nan).is_nan());
+                $fassert!((0.0 as $fty).maximum(0.0), 0.0);
+                $fassert!((0.0 as $fty).maximum(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).maximum(0.0), 0.0);
+                $fassert!((-0.0 as $fty).maximum(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).maximum(-0.0), -0.0);
+                $fassert!((-0.0 as $fty).maximum(-0.0).is_sign_negative());
+                $fassert!((9.0 as $fty).maximum(9.0), 9.0);
+                $fassert!((-9.0 as $fty).maximum(0.0), 0.0);
+                $fassert!((-9.0 as $fty).maximum(0.0).is_sign_positive());
+                $fassert!((-9.0 as $fty).maximum(-0.0), -0.0);
+                $fassert!((-9.0 as $fty).maximum(-0.0).is_sign_negative());
+                $fassert!((0.0 as $fty).maximum(9.0), 9.0);
+                $fassert!((0.0 as $fty).maximum(-9.0), 0.0);
+                $fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).maximum(-9.0), -0.0);
+                $fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
+                $fassert!(($inf as $fty).maximum(9.0), $inf);
+                $fassert!((9.0 as $fty).maximum($inf), $inf);
+                $fassert!(($inf as $fty).maximum(-9.0), $inf);
+                $fassert!((-9.0 as $fty).maximum($inf), $inf);
+                $fassert!(($neginf as $fty).maximum(9.0), 9.0);
+                $fassert!((9.0 as $fty).maximum($neginf), 9.0);
+                $fassert!(($neginf as $fty).maximum(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).maximum($neginf), -9.0);
+                $fassert!(($nan as $fty).maximum(9.0).is_nan());
+                $fassert!(($nan as $fty).maximum(-9.0).is_nan());
+                $fassert!((9.0 as $fty).maximum($nan).is_nan());
+                $fassert!((-9.0 as $fty).maximum($nan).is_nan());
+                $fassert!(($nan as $fty).maximum($nan).is_nan());
             }
             #[test]
             fn midpoint() {
-                assert_eq!((0.5 as $fty).midpoint(0.5), 0.5);
-                assert_eq!((0.5 as $fty).midpoint(2.5), 1.5);
-                assert_eq!((3.0 as $fty).midpoint(4.0), 3.5);
-                assert_eq!((-3.0 as $fty).midpoint(4.0), 0.5);
-                assert_eq!((3.0 as $fty).midpoint(-4.0), -0.5);
-                assert_eq!((-3.0 as $fty).midpoint(-4.0), -3.5);
-                assert_eq!((0.0 as $fty).midpoint(0.0), 0.0);
-                assert_eq!((-0.0 as $fty).midpoint(-0.0), -0.0);
-                assert_eq!((-5.0 as $fty).midpoint(5.0), 0.0);
-                assert_eq!(($max as $fty).midpoint($min), 0.0);
-                assert_eq!(($min as $fty).midpoint($max), -0.0);
-                assert_eq!(($max as $fty).midpoint($min_pos), $max / 2.);
-                assert_eq!((-$max as $fty).midpoint($min_pos), -$max / 2.);
-                assert_eq!(($max as $fty).midpoint(-$min_pos), $max / 2.);
-                assert_eq!((-$max as $fty).midpoint(-$min_pos), -$max / 2.);
-                assert_eq!(($min_pos as $fty).midpoint($max), $max / 2.);
-                assert_eq!(($min_pos as $fty).midpoint(-$max), -$max / 2.);
-                assert_eq!((-$min_pos as $fty).midpoint($max), $max / 2.);
-                assert_eq!((-$min_pos as $fty).midpoint(-$max), -$max / 2.);
-                assert_eq!(($max as $fty).midpoint($max), $max);
-                assert_eq!(($min_pos as $fty).midpoint($min_pos), $min_pos);
-                assert_eq!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos);
-                assert_eq!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5);
-                assert_eq!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5);
-                assert_eq!(($inf as $fty).midpoint($inf), $inf);
-                assert_eq!(($neginf as $fty).midpoint($neginf), $neginf);
-                assert!(($nan as $fty).midpoint(1.0).is_nan());
-                assert!((1.0 as $fty).midpoint($nan).is_nan());
-                assert!(($nan as $fty).midpoint($nan).is_nan());
+                $fassert!((0.5 as $fty).midpoint(0.5), 0.5);
+                $fassert!((0.5 as $fty).midpoint(2.5), 1.5);
+                $fassert!((3.0 as $fty).midpoint(4.0), 3.5);
+                $fassert!((-3.0 as $fty).midpoint(4.0), 0.5);
+                $fassert!((3.0 as $fty).midpoint(-4.0), -0.5);
+                $fassert!((-3.0 as $fty).midpoint(-4.0), -3.5);
+                $fassert!((0.0 as $fty).midpoint(0.0), 0.0);
+                $fassert!((-0.0 as $fty).midpoint(-0.0), -0.0);
+                $fassert!((-5.0 as $fty).midpoint(5.0), 0.0);
+                $fassert!(($max as $fty).midpoint($min), 0.0);
+                $fassert!(($min as $fty).midpoint($max), -0.0);
+                $fassert!(($max as $fty).midpoint($min_pos), $max / 2.);
+                $fassert!((-$max as $fty).midpoint($min_pos), -$max / 2.);
+                $fassert!(($max as $fty).midpoint(-$min_pos), $max / 2.);
+                $fassert!((-$max as $fty).midpoint(-$min_pos), -$max / 2.);
+                $fassert!(($min_pos as $fty).midpoint($max), $max / 2.);
+                $fassert!(($min_pos as $fty).midpoint(-$max), -$max / 2.);
+                $fassert!((-$min_pos as $fty).midpoint($max), $max / 2.);
+                $fassert!((-$min_pos as $fty).midpoint(-$max), -$max / 2.);
+                $fassert!(($max as $fty).midpoint($max), $max);
+                $fassert!(($min_pos as $fty).midpoint($min_pos), $min_pos);
+                $fassert!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos);
+                $fassert!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5);
+                $fassert!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5);
+                $fassert!(($inf as $fty).midpoint($inf), $inf);
+                $fassert!(($neginf as $fty).midpoint($neginf), $neginf);
+                $fassert!(($nan as $fty).midpoint(1.0).is_nan());
+                $fassert!((1.0 as $fty).midpoint($nan).is_nan());
+                $fassert!(($nan as $fty).midpoint($nan).is_nan());
 
                 // test if large differences in magnitude are still correctly computed.
                 // NOTE: that because of how small x and y are, x + y can never overflow
@@ -907,19 +907,19 @@ macro_rules! test_float {
             }
             #[test]
             fn rem_euclid() {
-                let a: $fty = 42.0;
-                assert!($inf.rem_euclid(a).is_nan());
-                assert_eq!(a.rem_euclid($inf), a);
-                assert!(a.rem_euclid($nan).is_nan());
+                // FIXME: Use $fassert when rem_euclid becomes const
+                assert!($inf.rem_euclid((42.0 as $fty)).is_nan());
+                assert_eq!((42.0 as $fty).rem_euclid($inf), (42.0 as $fty));
+                assert!((42.0 as $fty).rem_euclid($nan).is_nan());
                 assert!($inf.rem_euclid($inf).is_nan());
                 assert!($inf.rem_euclid($nan).is_nan());
                 assert!($nan.rem_euclid($inf).is_nan());
             }
             #[test]
             fn div_euclid() {
-                let a: $fty = 42.0;
-                assert_eq!(a.div_euclid($inf), 0.0);
-                assert!(a.div_euclid($nan).is_nan());
+                // FIXME: Use $fassert when div_euclid becomes const
+                assert_eq!((42.0 as $fty).div_euclid($inf), 0.0);
+                assert!((42.0 as $fty).div_euclid($nan).is_nan());
                 assert!($inf.div_euclid($inf).is_nan());
                 assert!($inf.div_euclid($nan).is_nan());
                 assert!($nan.div_euclid($inf).is_nan());
@@ -928,8 +928,41 @@ macro_rules! test_float {
     };
 }
 
+// Custom assert macro that distribute between assert! and assert_eq! in a non-const context
+macro_rules! float_assert {
+    ($b:expr) => {
+        assert!($b);
+    };
+    ($left:expr, $right:expr) => {
+        assert_eq!($left, $right);
+    };
+}
+
+// Custom assert macro that only uses assert! in a const context
+macro_rules! float_const_assert {
+    ($b:expr) => {
+        assert!(const { $b });
+    };
+    ($left:expr, $right:expr) => {
+        assert!(const { $left == $right });
+    };
+}
+
 test_float!(
     f32,
+    float_assert,
+    f32,
+    f32::INFINITY,
+    f32::NEG_INFINITY,
+    f32::NAN,
+    f32::MIN,
+    f32::MAX,
+    f32::MIN_POSITIVE,
+    f32::MAX_EXP
+);
+test_float!(
+    f32_const,
+    float_const_assert,
     f32,
     f32::INFINITY,
     f32::NEG_INFINITY,
@@ -941,6 +974,19 @@ test_float!(
 );
 test_float!(
     f64,
+    float_assert,
+    f64,
+    f64::INFINITY,
+    f64::NEG_INFINITY,
+    f64::NAN,
+    f64::MIN,
+    f64::MAX,
+    f64::MIN_POSITIVE,
+    f64::MAX_EXP
+);
+test_float!(
+    f64_const,
+    float_const_assert,
     f64,
     f64::INFINITY,
     f64::NEG_INFINITY,
diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml
index 6f43ac4809a..d7d169671f0 100644
--- a/library/panic_abort/Cargo.toml
+++ b/library/panic_abort/Cargo.toml
@@ -12,10 +12,11 @@ bench = false
 doc = false
 
 [dependencies]
-alloc = { path = "../alloc" }
-cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 core = { path = "../core" }
 compiler_builtins = "0.1.0"
 
-[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
+[target.'cfg(target_os = "android")'.dependencies]
 libc = { version = "0.2", default-features = false }
+
+[target.'cfg(any(target_os = "android", target_os = "zkvm"))'.dependencies]
+alloc = { path = "../alloc" }
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index b2ad0f4ac3d..d1706b65252 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -7,15 +7,11 @@
 #![unstable(feature = "panic_abort", issue = "32837")]
 #![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 #![panic_runtime]
-#![allow(unused_features)]
-#![feature(asm_experimental_arch)]
-#![feature(core_intrinsics)]
 #![feature(panic_runtime)]
 #![feature(std_internals)]
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
 #![allow(internal_features)]
-#![deny(unsafe_op_in_unsafe_fn)]
 
 #[cfg(target_os = "android")]
 mod android;
@@ -45,75 +41,13 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
         zkvm::zkvm_set_abort_message(_payload);
     }
 
-    unsafe {
-        abort();
+    unsafe extern "Rust" {
+        // This is defined in std::rt.
+        #[rustc_std_internal_symbol]
+        safe fn __rust_abort() -> !;
     }
 
-    cfg_if::cfg_if! {
-        if #[cfg(any(unix, target_os = "solid_asp3"))] {
-            unsafe fn abort() -> ! {
-                unsafe { libc::abort(); }
-            }
-        } else if #[cfg(any(target_os = "hermit",
-                            all(target_vendor = "fortanix", target_env = "sgx"),
-                            target_os = "xous",
-                            target_os = "uefi",
-        ))] {
-            unsafe fn abort() -> ! {
-                // call std::sys::abort_internal
-                unsafe extern "C" {
-                    pub fn __rust_abort() -> !;
-                }
-                unsafe { __rust_abort(); }
-            }
-        } else if #[cfg(all(windows, not(miri)))] {
-            // On Windows, use the processor-specific __fastfail mechanism. In Windows 8
-            // and later, this will terminate the process immediately without running any
-            // in-process exception handlers. In earlier versions of Windows, this
-            // sequence of instructions will be treated as an access violation,
-            // terminating the process but without necessarily bypassing all exception
-            // handlers.
-            //
-            // https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
-            //
-            // Note: this is the same implementation as in std's `abort_internal`
-            unsafe fn abort() -> ! {
-                #[allow(unused)]
-                const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
-                cfg_if::cfg_if! {
-                    if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
-                        unsafe {
-                            core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
-                        }
-                    } else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
-                        unsafe {
-                            core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
-                        }
-                    } else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
-                        unsafe {
-                            core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
-                        }
-                    } else {
-                        core::intrinsics::abort();
-                    }
-                }
-            }
-        } else if #[cfg(target_os = "teeos")] {
-            mod teeos {
-                unsafe extern "C" {
-                    pub fn TEE_Panic(code: u32) -> !;
-                }
-            }
-
-            unsafe fn abort() -> ! {
-                unsafe { teeos::TEE_Panic(1); }
-            }
-        } else {
-            unsafe fn abort() -> ! {
-                core::intrinsics::abort();
-            }
-        }
-    }
+    __rust_abort()
 }
 
 // This... is a bit of an oddity. The tl;dr; is that this is required to link
diff --git a/library/panic_unwind/src/hermit.rs b/library/panic_unwind/src/hermit.rs
index 8f4562d07fc..b36d1a019fd 100644
--- a/library/panic_unwind/src/hermit.rs
+++ b/library/panic_unwind/src/hermit.rs
@@ -5,20 +5,16 @@
 use alloc::boxed::Box;
 use core::any::Any;
 
+unsafe extern "Rust" {
+    // This is defined in std::rt
+    #[rustc_std_internal_symbol]
+    safe fn __rust_abort() -> !;
+}
+
 pub(crate) unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
-    unsafe extern "C" {
-        fn __rust_abort() -> !;
-    }
-    unsafe {
-        __rust_abort();
-    }
+    __rust_abort()
 }
 
 pub(crate) unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
-    unsafe extern "C" {
-        fn __rust_abort() -> !;
-    }
-    unsafe {
-        __rust_abort();
-    }
+    __rust_abort()
 }
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index 6b2ba2e714c..bb4acde4822 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -14,365 +14,6 @@ use crate::sys::cmath;
 
 #[cfg(not(test))]
 impl f128 {
-    /// Returns the largest integer less than or equal to `self`.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let f = 3.7_f128;
-    /// let g = 3.0_f128;
-    /// let h = -3.7_f128;
-    ///
-    /// assert_eq!(f.floor(), 3.0);
-    /// assert_eq!(g.floor(), 3.0);
-    /// assert_eq!(h.floor(), -4.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn floor(self) -> f128 {
-        unsafe { intrinsics::floorf128(self) }
-    }
-
-    /// Returns the smallest integer greater than or equal to `self`.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let f = 3.01_f128;
-    /// let g = 4.0_f128;
-    ///
-    /// assert_eq!(f.ceil(), 4.0);
-    /// assert_eq!(g.ceil(), 4.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[doc(alias = "ceiling")]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn ceil(self) -> f128 {
-        unsafe { intrinsics::ceilf128(self) }
-    }
-
-    /// Returns the nearest integer to `self`. If a value is half-way between two
-    /// integers, round away from `0.0`.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let f = 3.3_f128;
-    /// let g = -3.3_f128;
-    /// let h = -3.7_f128;
-    /// let i = 3.5_f128;
-    /// let j = 4.5_f128;
-    ///
-    /// assert_eq!(f.round(), 3.0);
-    /// assert_eq!(g.round(), -3.0);
-    /// assert_eq!(h.round(), -4.0);
-    /// assert_eq!(i.round(), 4.0);
-    /// assert_eq!(j.round(), 5.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn round(self) -> f128 {
-        unsafe { intrinsics::roundf128(self) }
-    }
-
-    /// Returns the nearest integer to a number. Rounds half-way cases to the number
-    /// with an even least significant digit.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let f = 3.3_f128;
-    /// let g = -3.3_f128;
-    /// let h = 3.5_f128;
-    /// let i = 4.5_f128;
-    ///
-    /// assert_eq!(f.round_ties_even(), 3.0);
-    /// assert_eq!(g.round_ties_even(), -3.0);
-    /// assert_eq!(h.round_ties_even(), 4.0);
-    /// assert_eq!(i.round_ties_even(), 4.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn round_ties_even(self) -> f128 {
-        intrinsics::round_ties_even_f128(self)
-    }
-
-    /// Returns the integer part of `self`.
-    /// This means that non-integer numbers are always truncated towards zero.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let f = 3.7_f128;
-    /// let g = 3.0_f128;
-    /// let h = -3.7_f128;
-    ///
-    /// assert_eq!(f.trunc(), 3.0);
-    /// assert_eq!(g.trunc(), 3.0);
-    /// assert_eq!(h.trunc(), -3.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[doc(alias = "truncate")]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn trunc(self) -> f128 {
-        unsafe { intrinsics::truncf128(self) }
-    }
-
-    /// Returns the fractional part of `self`.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let x = 3.6_f128;
-    /// let y = -3.6_f128;
-    /// let abs_difference_x = (x.fract() - 0.6).abs();
-    /// let abs_difference_y = (y.fract() - (-0.6)).abs();
-    ///
-    /// assert!(abs_difference_x <= f128::EPSILON);
-    /// assert!(abs_difference_y <= f128::EPSILON);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn fract(self) -> f128 {
-        self - self.trunc()
-    }
-
-    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
-    /// error, yielding a more accurate result than an unfused multiply-add.
-    ///
-    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
-    /// the target architecture has a dedicated `fma` CPU instruction. However,
-    /// this is not always true, and will be heavily dependant on designing
-    /// algorithms with specific target hardware in mind.
-    ///
-    /// # Precision
-    ///
-    /// The result of this operation is guaranteed to be the rounded
-    /// infinite-precision result. It is specified by IEEE 754 as
-    /// `fusedMultiplyAdd` and guaranteed not to change.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let m = 10.0_f128;
-    /// let x = 4.0_f128;
-    /// let b = 60.0_f128;
-    ///
-    /// assert_eq!(m.mul_add(x, b), 100.0);
-    /// assert_eq!(m * x + b, 100.0);
-    ///
-    /// let one_plus_eps = 1.0_f128 + f128::EPSILON;
-    /// let one_minus_eps = 1.0_f128 - f128::EPSILON;
-    /// let minus_one = -1.0_f128;
-    ///
-    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
-    /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f128::EPSILON * f128::EPSILON);
-    /// // Different rounding with the non-fused multiply and add.
-    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[doc(alias = "fmaf128", alias = "fusedMultiplyAdd")]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn mul_add(self, a: f128, b: f128) -> f128 {
-        unsafe { intrinsics::fmaf128(self, a, b) }
-    }
-
-    /// Calculates Euclidean division, the matching method for `rem_euclid`.
-    ///
-    /// This computes the integer `n` such that
-    /// `self = n * rhs + self.rem_euclid(rhs)`.
-    /// In other words, the result is `self / rhs` rounded to the integer `n`
-    /// such that `self >= n * rhs`.
-    ///
-    /// # Precision
-    ///
-    /// The result of this operation is guaranteed to be the rounded
-    /// infinite-precision result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let a: f128 = 7.0;
-    /// let b = 4.0;
-    /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
-    /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
-    /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
-    /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn div_euclid(self, rhs: f128) -> f128 {
-        let q = (self / rhs).trunc();
-        if self % rhs < 0.0 {
-            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
-        }
-        q
-    }
-
-    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
-    ///
-    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
-    /// most cases. However, due to a floating point round-off error it can
-    /// result in `r == rhs.abs()`, violating the mathematical definition, if
-    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
-    /// This result is not an element of the function's codomain, but it is the
-    /// closest floating point number in the real numbers and thus fulfills the
-    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
-    /// approximately.
-    ///
-    /// # Precision
-    ///
-    /// The result of this operation is guaranteed to be the rounded
-    /// infinite-precision result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let a: f128 = 7.0;
-    /// let b = 4.0;
-    /// assert_eq!(a.rem_euclid(b), 3.0);
-    /// assert_eq!((-a).rem_euclid(b), 1.0);
-    /// assert_eq!(a.rem_euclid(-b), 3.0);
-    /// assert_eq!((-a).rem_euclid(-b), 1.0);
-    /// // limitation due to round-off error
-    /// assert!((-f128::EPSILON).rem_euclid(3.0) != 0.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[doc(alias = "modulo", alias = "mod")]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn rem_euclid(self, rhs: f128) -> f128 {
-        let r = self % rhs;
-        if r < 0.0 { r + rhs.abs() } else { r }
-    }
-
-    /// Raises a number to an integer power.
-    ///
-    /// Using this function is generally faster than using `powf`.
-    /// It might have a different sequence of rounding operations than `powf`,
-    /// so the results are not guaranteed to agree.
-    ///
-    /// # Unspecified precision
-    ///
-    /// The precision of this function is non-deterministic. This means it varies by platform,
-    /// Rust version, and can even differ within the same execution from one invocation to the next.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let x = 2.0_f128;
-    /// let abs_difference = (x.powi(2) - (x * x)).abs();
-    /// assert!(abs_difference <= f128::EPSILON);
-    ///
-    /// assert_eq!(f128::powi(f128::NAN, 0), 1.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn powi(self, n: i32) -> f128 {
-        unsafe { intrinsics::powif128(self, n) }
-    }
-
     /// Raises a number to a floating point power.
     ///
     /// # Unspecified precision
@@ -405,43 +46,6 @@ impl f128 {
         unsafe { intrinsics::powf128(self, n) }
     }
 
-    /// Returns the square root of a number.
-    ///
-    /// Returns NaN if `self` is a negative number other than `-0.0`.
-    ///
-    /// # Precision
-    ///
-    /// The result of this operation is guaranteed to be the rounded
-    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
-    /// and guaranteed not to change.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f128)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f128_math)] {
-    ///
-    /// let positive = 4.0_f128;
-    /// let negative = -4.0_f128;
-    /// let negative_zero = -0.0_f128;
-    ///
-    /// assert_eq!(positive.sqrt(), 2.0);
-    /// assert!(negative.sqrt().is_nan());
-    /// assert!(negative_zero.sqrt() == negative_zero);
-    /// # }
-    /// ```
-    #[inline]
-    #[doc(alias = "squareRoot")]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f128", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn sqrt(self) -> f128 {
-        unsafe { intrinsics::sqrtf128(self) }
-    }
-
     /// Returns `e^(self)`, (the exponential function).
     ///
     /// # Unspecified precision
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index d6bc1d3118a..4792eac1f9e 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -14,365 +14,6 @@ use crate::sys::cmath;
 
 #[cfg(not(test))]
 impl f16 {
-    /// Returns the largest integer less than or equal to `self`.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let f = 3.7_f16;
-    /// let g = 3.0_f16;
-    /// let h = -3.7_f16;
-    ///
-    /// assert_eq!(f.floor(), 3.0);
-    /// assert_eq!(g.floor(), 3.0);
-    /// assert_eq!(h.floor(), -4.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn floor(self) -> f16 {
-        unsafe { intrinsics::floorf16(self) }
-    }
-
-    /// Returns the smallest integer greater than or equal to `self`.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let f = 3.01_f16;
-    /// let g = 4.0_f16;
-    ///
-    /// assert_eq!(f.ceil(), 4.0);
-    /// assert_eq!(g.ceil(), 4.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[doc(alias = "ceiling")]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn ceil(self) -> f16 {
-        unsafe { intrinsics::ceilf16(self) }
-    }
-
-    /// Returns the nearest integer to `self`. If a value is half-way between two
-    /// integers, round away from `0.0`.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let f = 3.3_f16;
-    /// let g = -3.3_f16;
-    /// let h = -3.7_f16;
-    /// let i = 3.5_f16;
-    /// let j = 4.5_f16;
-    ///
-    /// assert_eq!(f.round(), 3.0);
-    /// assert_eq!(g.round(), -3.0);
-    /// assert_eq!(h.round(), -4.0);
-    /// assert_eq!(i.round(), 4.0);
-    /// assert_eq!(j.round(), 5.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn round(self) -> f16 {
-        unsafe { intrinsics::roundf16(self) }
-    }
-
-    /// Returns the nearest integer to a number. Rounds half-way cases to the number
-    /// with an even least significant digit.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let f = 3.3_f16;
-    /// let g = -3.3_f16;
-    /// let h = 3.5_f16;
-    /// let i = 4.5_f16;
-    ///
-    /// assert_eq!(f.round_ties_even(), 3.0);
-    /// assert_eq!(g.round_ties_even(), -3.0);
-    /// assert_eq!(h.round_ties_even(), 4.0);
-    /// assert_eq!(i.round_ties_even(), 4.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn round_ties_even(self) -> f16 {
-        intrinsics::round_ties_even_f16(self)
-    }
-
-    /// Returns the integer part of `self`.
-    /// This means that non-integer numbers are always truncated towards zero.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let f = 3.7_f16;
-    /// let g = 3.0_f16;
-    /// let h = -3.7_f16;
-    ///
-    /// assert_eq!(f.trunc(), 3.0);
-    /// assert_eq!(g.trunc(), 3.0);
-    /// assert_eq!(h.trunc(), -3.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[doc(alias = "truncate")]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn trunc(self) -> f16 {
-        unsafe { intrinsics::truncf16(self) }
-    }
-
-    /// Returns the fractional part of `self`.
-    ///
-    /// This function always returns the precise result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let x = 3.6_f16;
-    /// let y = -3.6_f16;
-    /// let abs_difference_x = (x.fract() - 0.6).abs();
-    /// let abs_difference_y = (y.fract() - (-0.6)).abs();
-    ///
-    /// assert!(abs_difference_x <= f16::EPSILON);
-    /// assert!(abs_difference_y <= f16::EPSILON);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn fract(self) -> f16 {
-        self - self.trunc()
-    }
-
-    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
-    /// error, yielding a more accurate result than an unfused multiply-add.
-    ///
-    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
-    /// the target architecture has a dedicated `fma` CPU instruction. However,
-    /// this is not always true, and will be heavily dependant on designing
-    /// algorithms with specific target hardware in mind.
-    ///
-    /// # Precision
-    ///
-    /// The result of this operation is guaranteed to be the rounded
-    /// infinite-precision result. It is specified by IEEE 754 as
-    /// `fusedMultiplyAdd` and guaranteed not to change.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let m = 10.0_f16;
-    /// let x = 4.0_f16;
-    /// let b = 60.0_f16;
-    ///
-    /// assert_eq!(m.mul_add(x, b), 100.0);
-    /// assert_eq!(m * x + b, 100.0);
-    ///
-    /// let one_plus_eps = 1.0_f16 + f16::EPSILON;
-    /// let one_minus_eps = 1.0_f16 - f16::EPSILON;
-    /// let minus_one = -1.0_f16;
-    ///
-    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
-    /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f16::EPSILON * f16::EPSILON);
-    /// // Different rounding with the non-fused multiply and add.
-    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[doc(alias = "fmaf16", alias = "fusedMultiplyAdd")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn mul_add(self, a: f16, b: f16) -> f16 {
-        unsafe { intrinsics::fmaf16(self, a, b) }
-    }
-
-    /// Calculates Euclidean division, the matching method for `rem_euclid`.
-    ///
-    /// This computes the integer `n` such that
-    /// `self = n * rhs + self.rem_euclid(rhs)`.
-    /// In other words, the result is `self / rhs` rounded to the integer `n`
-    /// such that `self >= n * rhs`.
-    ///
-    /// # Precision
-    ///
-    /// The result of this operation is guaranteed to be the rounded
-    /// infinite-precision result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let a: f16 = 7.0;
-    /// let b = 4.0;
-    /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
-    /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
-    /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
-    /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn div_euclid(self, rhs: f16) -> f16 {
-        let q = (self / rhs).trunc();
-        if self % rhs < 0.0 {
-            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
-        }
-        q
-    }
-
-    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
-    ///
-    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
-    /// most cases. However, due to a floating point round-off error it can
-    /// result in `r == rhs.abs()`, violating the mathematical definition, if
-    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
-    /// This result is not an element of the function's codomain, but it is the
-    /// closest floating point number in the real numbers and thus fulfills the
-    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
-    /// approximately.
-    ///
-    /// # Precision
-    ///
-    /// The result of this operation is guaranteed to be the rounded
-    /// infinite-precision result.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let a: f16 = 7.0;
-    /// let b = 4.0;
-    /// assert_eq!(a.rem_euclid(b), 3.0);
-    /// assert_eq!((-a).rem_euclid(b), 1.0);
-    /// assert_eq!(a.rem_euclid(-b), 3.0);
-    /// assert_eq!((-a).rem_euclid(-b), 1.0);
-    /// // limitation due to round-off error
-    /// assert!((-f16::EPSILON).rem_euclid(3.0) != 0.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[doc(alias = "modulo", alias = "mod")]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn rem_euclid(self, rhs: f16) -> f16 {
-        let r = self % rhs;
-        if r < 0.0 { r + rhs.abs() } else { r }
-    }
-
-    /// Raises a number to an integer power.
-    ///
-    /// Using this function is generally faster than using `powf`.
-    /// It might have a different sequence of rounding operations than `powf`,
-    /// so the results are not guaranteed to agree.
-    ///
-    /// # Unspecified precision
-    ///
-    /// The precision of this function is non-deterministic. This means it varies by platform,
-    /// Rust version, and can even differ within the same execution from one invocation to the next.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let x = 2.0_f16;
-    /// let abs_difference = (x.powi(2) - (x * x)).abs();
-    /// assert!(abs_difference <= f16::EPSILON);
-    ///
-    /// assert_eq!(f16::powi(f16::NAN, 0), 1.0);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn powi(self, n: i32) -> f16 {
-        unsafe { intrinsics::powif16(self, n) }
-    }
-
     /// Raises a number to a floating point power.
     ///
     /// # Unspecified precision
@@ -405,43 +46,6 @@ impl f16 {
         unsafe { intrinsics::powf16(self, n) }
     }
 
-    /// Returns the square root of a number.
-    ///
-    /// Returns NaN if `self` is a negative number other than `-0.0`.
-    ///
-    /// # Precision
-    ///
-    /// The result of this operation is guaranteed to be the rounded
-    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
-    /// and guaranteed not to change.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let positive = 4.0_f16;
-    /// let negative = -4.0_f16;
-    /// let negative_zero = -0.0_f16;
-    ///
-    /// assert_eq!(positive.sqrt(), 2.0);
-    /// assert!(negative.sqrt().is_nan());
-    /// assert!(negative_zero.sqrt() == negative_zero);
-    /// # }
-    /// ```
-    #[inline]
-    #[doc(alias = "squareRoot")]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn sqrt(self) -> f16 {
-        unsafe { intrinsics::sqrtf16(self) }
-    }
-
     /// Returns `e^(self)`, (the exponential function).
     ///
     /// # Unspecified precision
@@ -702,41 +306,6 @@ impl f16 {
         unsafe { intrinsics::log10f16(self) }
     }
 
-    /// Returns the cube root of a number.
-    ///
-    /// # Unspecified precision
-    ///
-    /// The precision of this function is non-deterministic. This means it varies by platform,
-    /// Rust version, and can even differ within the same execution from one invocation to the next.
-    ///
-    /// This function currently corresponds to the `cbrtf` from libc on Unix
-    /// and Windows. Note that this might change in the future.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(f16)]
-    /// # #![feature(cfg_target_has_reliable_f16_f128)]
-    /// # #![expect(internal_features)]
-    /// # #[cfg(not(miri))]
-    /// # #[cfg(target_has_reliable_f16_math)] {
-    ///
-    /// let x = 8.0f16;
-    ///
-    /// // x^(1/3) - 2 == 0
-    /// let abs_difference = (x.cbrt() - 2.0).abs();
-    ///
-    /// assert!(abs_difference <= f16::EPSILON);
-    /// # }
-    /// ```
-    #[inline]
-    #[rustc_allow_incoherent_impl]
-    #[unstable(feature = "f16", issue = "116909")]
-    #[must_use = "method returns a new number and does not mutate the original value"]
-    pub fn cbrt(self) -> f16 {
-        cmath::cbrtf(self as f32) as f16
-    }
-
     /// Compute the distance between the origin and a point (`x`, `y`) on the
     /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a
     /// right-angle triangle with other sides having length `x.abs()` and
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index baf7002f380..94140d01d8b 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -46,7 +46,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn floor(self) -> f32 {
-        unsafe { intrinsics::floorf32(self) }
+        core::f32::floor(self)
     }
 
     /// Returns the smallest integer greater than or equal to `self`.
@@ -68,7 +68,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn ceil(self) -> f32 {
-        unsafe { intrinsics::ceilf32(self) }
+        core::f32::ceil(self)
     }
 
     /// Returns the nearest integer to `self`. If a value is half-way between two
@@ -96,7 +96,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn round(self) -> f32 {
-        unsafe { intrinsics::roundf32(self) }
+        core::f32::round(self)
     }
 
     /// Returns the nearest integer to a number. Rounds half-way cases to the number
@@ -122,7 +122,7 @@ impl f32 {
     #[stable(feature = "round_ties_even", since = "1.77.0")]
     #[inline]
     pub fn round_ties_even(self) -> f32 {
-        intrinsics::round_ties_even_f32(self)
+        core::f32::round_ties_even(self)
     }
 
     /// Returns the integer part of `self`.
@@ -147,7 +147,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn trunc(self) -> f32 {
-        unsafe { intrinsics::truncf32(self) }
+        core::f32::trunc(self)
     }
 
     /// Returns the fractional part of `self`.
@@ -170,7 +170,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn fract(self) -> f32 {
-        self - self.trunc()
+        core::f32::fract(self)
     }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
@@ -212,7 +212,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn mul_add(self, a: f32, b: f32) -> f32 {
-        unsafe { intrinsics::fmaf32(self, a, b) }
+        core::f32::mul_add(self, a, b)
     }
 
     /// Calculates Euclidean division, the matching method for `rem_euclid`.
@@ -242,11 +242,7 @@ impl f32 {
     #[inline]
     #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn div_euclid(self, rhs: f32) -> f32 {
-        let q = (self / rhs).trunc();
-        if self % rhs < 0.0 {
-            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
-        }
-        q
+        core::f32::div_euclid(self, rhs)
     }
 
     /// Calculates the least nonnegative remainder of `self (mod rhs)`.
@@ -283,8 +279,7 @@ impl f32 {
     #[inline]
     #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn rem_euclid(self, rhs: f32) -> f32 {
-        let r = self % rhs;
-        if r < 0.0 { r + rhs.abs() } else { r }
+        core::f32::rem_euclid(self, rhs)
     }
 
     /// Raises a number to an integer power.
@@ -312,7 +307,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn powi(self, n: i32) -> f32 {
-        unsafe { intrinsics::powif32(self, n) }
+        core::f32::powi(self, n)
     }
 
     /// Raises a number to a floating point power.
@@ -367,7 +362,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sqrt(self) -> f32 {
-        unsafe { intrinsics::sqrtf32(self) }
+        core::f32::sqrt(self)
     }
 
     /// Returns `e^(self)`, (the exponential function).
@@ -599,7 +594,8 @@ impl f32 {
                 filing an issue describing your use-case too)."
     )]
     pub fn abs_sub(self, other: f32) -> f32 {
-        cmath::fdimf(self, other)
+        #[allow(deprecated)]
+        core::f32::abs_sub(self, other)
     }
 
     /// Returns the cube root of a number.
@@ -626,7 +622,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn cbrt(self) -> f32 {
-        cmath::cbrtf(self)
+        core::f32::cbrt(self)
     }
 
     /// Compute the distance between the origin and a point (`x`, `y`) on the
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 84fd9bfb7b6..051061ae605 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -46,7 +46,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn floor(self) -> f64 {
-        unsafe { intrinsics::floorf64(self) }
+        core::f64::floor(self)
     }
 
     /// Returns the smallest integer greater than or equal to `self`.
@@ -68,7 +68,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn ceil(self) -> f64 {
-        unsafe { intrinsics::ceilf64(self) }
+        core::f64::ceil(self)
     }
 
     /// Returns the nearest integer to `self`. If a value is half-way between two
@@ -96,7 +96,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn round(self) -> f64 {
-        unsafe { intrinsics::roundf64(self) }
+        core::f64::round(self)
     }
 
     /// Returns the nearest integer to a number. Rounds half-way cases to the number
@@ -122,7 +122,7 @@ impl f64 {
     #[stable(feature = "round_ties_even", since = "1.77.0")]
     #[inline]
     pub fn round_ties_even(self) -> f64 {
-        intrinsics::round_ties_even_f64(self)
+        core::f64::round_ties_even(self)
     }
 
     /// Returns the integer part of `self`.
@@ -147,7 +147,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn trunc(self) -> f64 {
-        unsafe { intrinsics::truncf64(self) }
+        core::f64::trunc(self)
     }
 
     /// Returns the fractional part of `self`.
@@ -170,7 +170,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn fract(self) -> f64 {
-        self - self.trunc()
+        core::f64::fract(self)
     }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
@@ -212,7 +212,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn mul_add(self, a: f64, b: f64) -> f64 {
-        unsafe { intrinsics::fmaf64(self, a, b) }
+        core::f64::mul_add(self, a, b)
     }
 
     /// Calculates Euclidean division, the matching method for `rem_euclid`.
@@ -242,11 +242,7 @@ impl f64 {
     #[inline]
     #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn div_euclid(self, rhs: f64) -> f64 {
-        let q = (self / rhs).trunc();
-        if self % rhs < 0.0 {
-            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
-        }
-        q
+        core::f64::div_euclid(self, rhs)
     }
 
     /// Calculates the least nonnegative remainder of `self (mod rhs)`.
@@ -283,8 +279,7 @@ impl f64 {
     #[inline]
     #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn rem_euclid(self, rhs: f64) -> f64 {
-        let r = self % rhs;
-        if r < 0.0 { r + rhs.abs() } else { r }
+        core::f64::rem_euclid(self, rhs)
     }
 
     /// Raises a number to an integer power.
@@ -312,7 +307,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn powi(self, n: i32) -> f64 {
-        unsafe { intrinsics::powif64(self, n) }
+        core::f64::powi(self, n)
     }
 
     /// Raises a number to a floating point power.
@@ -367,7 +362,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sqrt(self) -> f64 {
-        unsafe { intrinsics::sqrtf64(self) }
+        core::f64::sqrt(self)
     }
 
     /// Returns `e^(self)`, (the exponential function).
@@ -599,7 +594,8 @@ impl f64 {
                 filing an issue describing your use-case too)."
     )]
     pub fn abs_sub(self, other: f64) -> f64 {
-        cmath::fdim(self, other)
+        #[allow(deprecated)]
+        core::f64::abs_sub(self, other)
     }
 
     /// Returns the cube root of a number.
@@ -626,7 +622,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn cbrt(self) -> f64 {
-        cmath::cbrt(self)
+        core::f64::cbrt(self)
     }
 
     /// Compute the distance between the origin and a point (`x`, `y`) on the
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 0bb40ee4b31..ca04a381271 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -287,6 +287,7 @@
 #![feature(cfi_encoding)]
 #![feature(char_max_len)]
 #![feature(concat_idents)]
+#![feature(core_float_math)]
 #![feature(decl_macro)]
 #![feature(deprecated_suggestion)]
 #![feature(doc_cfg)]
@@ -304,7 +305,6 @@
 #![feature(iter_advance_by)]
 #![feature(iter_next_chunk)]
 #![feature(lang_items)]
-#![feature(let_chains)]
 #![feature(link_cfg)]
 #![feature(linkage)]
 #![feature(macro_metavar_expr_concat)]
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index 1cab04a454d..1bd3bab5e37 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -307,11 +307,11 @@ impl UnixStream {
     ///
     /// ```no_run
     /// use std::io;
-    /// use std::net::UdpSocket;
+    /// use std::os::unix::net::UnixStream;
     /// use std::time::Duration;
     ///
     /// fn main() -> std::io::Result<()> {
-    ///     let socket = UdpSocket::bind("127.0.0.1:34254")?;
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
     ///     let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
     ///     let err = result.unwrap_err();
     ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs
index 34f0e89f2f1..5ea91dd6521 100644
--- a/library/std/src/os/wasi/fs.rs
+++ b/library/std/src/os/wasi/fs.rs
@@ -72,7 +72,6 @@ pub trait FileExt {
     /// If this function returns an error, it is unspecified how many bytes it
     /// has read, but it will never read more than would be necessary to
     /// completely fill the buffer.
-    #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
     fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
         while !buf.is_empty() {
             match self.read_at(buf, offset) {
@@ -144,7 +143,6 @@ pub trait FileExt {
     /// non-[`io::ErrorKind::Interrupted`] kind that [`write_at`] returns.
     ///
     /// [`write_at`]: FileExt::write_at
-    #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
     fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
         while !buf.is_empty() {
             match self.write_at(buf, offset) {
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index a084f452e55..c223eee95b5 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -344,6 +344,27 @@ pub trait CommandExt: Sealed {
         &mut self,
         attribute_list: &ProcThreadAttributeList<'_>,
     ) -> io::Result<process::Child>;
+
+    /// When true, sets the `STARTF_RUNFULLSCREEN` flag on the [STARTUPINFO][1] struct before passing it to `CreateProcess`.
+    ///
+    /// [1]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
+    #[unstable(feature = "windows_process_extensions_startupinfo", issue = "141010")]
+    fn startupinfo_fullscreen(&mut self, enabled: bool) -> &mut process::Command;
+
+    /// When true, sets the `STARTF_UNTRUSTEDSOURCE` flag on the [STARTUPINFO][1] struct before passing it to `CreateProcess`.
+    ///
+    /// [1]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
+    #[unstable(feature = "windows_process_extensions_startupinfo", issue = "141010")]
+    fn startupinfo_untrusted_source(&mut self, enabled: bool) -> &mut process::Command;
+
+    /// When specified, sets the following flags on the [STARTUPINFO][1] struct before passing it to `CreateProcess`:
+    /// - If `Some(true)`, sets `STARTF_FORCEONFEEDBACK`
+    /// - If `Some(false)`, sets `STARTF_FORCEOFFFEEDBACK`
+    /// - If `None`, does not set any flags
+    ///
+    /// [1]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
+    #[unstable(feature = "windows_process_extensions_startupinfo", issue = "141010")]
+    fn startupinfo_force_feedback(&mut self, enabled: Option<bool>) -> &mut process::Command;
 }
 
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
@@ -385,6 +406,21 @@ impl CommandExt for process::Command {
             .spawn_with_attributes(sys::process::Stdio::Inherit, true, Some(attribute_list))
             .map(process::Child::from_inner)
     }
+
+    fn startupinfo_fullscreen(&mut self, enabled: bool) -> &mut process::Command {
+        self.as_inner_mut().startupinfo_fullscreen(enabled);
+        self
+    }
+
+    fn startupinfo_untrusted_source(&mut self, enabled: bool) -> &mut process::Command {
+        self.as_inner_mut().startupinfo_untrusted_source(enabled);
+        self
+    }
+
+    fn startupinfo_force_feedback(&mut self, enabled: Option<bool>) -> &mut process::Command {
+        self.as_inner_mut().startupinfo_force_feedback(enabled);
+        self
+    }
 }
 
 #[unstable(feature = "windows_process_extensions_main_thread_handle", issue = "96723")]
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index 9737b2f5bfe..b3f3b301e3d 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -26,6 +26,13 @@ use crate::sync::Once;
 use crate::thread::{self, main_thread};
 use crate::{mem, panic, sys};
 
+// This function is needed by the panic runtime.
+#[cfg(not(test))]
+#[rustc_std_internal_symbol]
+fn __rust_abort() {
+    crate::process::abort();
+}
+
 // Prints to the "panic output", depending on the platform this may be:
 // - the standard error output
 // - some dedicated platform specific output
@@ -47,7 +54,7 @@ macro_rules! rtabort {
     ($($t:tt)*) => {
         {
             rtprintpanic!("fatal runtime error: {}, aborting\n", format_args!($($t)*));
-            crate::sys::abort_internal();
+            crate::process::abort();
         }
     }
 }
diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs
index 668fd928534..299ce1a6ff0 100644
--- a/library/std/src/sys/cmath.rs
+++ b/library/std/src/sys/cmath.rs
@@ -7,13 +7,9 @@ unsafe extern "C" {
     pub safe fn asin(n: f64) -> f64;
     pub safe fn atan(n: f64) -> f64;
     pub safe fn atan2(a: f64, b: f64) -> f64;
-    pub safe fn cbrt(n: f64) -> f64;
-    pub safe fn cbrtf(n: f32) -> f32;
     pub safe fn cosh(n: f64) -> f64;
     pub safe fn expm1(n: f64) -> f64;
     pub safe fn expm1f(n: f32) -> f32;
-    pub safe fn fdim(a: f64, b: f64) -> f64;
-    pub safe fn fdimf(a: f32, b: f32) -> f32;
     #[cfg_attr(target_env = "msvc", link_name = "_hypot")]
     pub safe fn hypot(x: f64, y: f64) -> f64;
     #[cfg_attr(target_env = "msvc", link_name = "_hypotf")]
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index 863358596c1..a3e520fdeef 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -1498,11 +1498,10 @@ impl File {
             None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }),
         };
         cfg_if::cfg_if! {
-            if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", target_os = "vxworks", target_os = "nuttx"))] {
+            if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", target_os = "nuttx"))] {
                 // Redox doesn't appear to support `UTIME_OMIT`.
                 // ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
                 // the same as for Redox.
-                // `futimens` and `UTIME_OMIT` are a work in progress for vxworks.
                 let _ = times;
                 Err(io::const_error!(
                     io::ErrorKind::Unsupported,
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index ea636938d70..fb8d69b7375 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -43,15 +43,6 @@ pub fn abort_internal() -> ! {
     unsafe { hermit_abi::abort() }
 }
 
-// This function is needed by the panic runtime. The symbol is named in
-// pre-link args for the target specification, so keep that in sync.
-#[cfg(not(test))]
-#[unsafe(no_mangle)]
-// NB. used by both libunwind and libpanic_abort
-pub extern "C" fn __rust_abort() {
-    abort_internal();
-}
-
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
 pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 3932f64c0ef..6e43a79ddec 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -112,11 +112,14 @@ pub fn abort_internal() -> ! {
     abi::usercalls::exit(true)
 }
 
-// This function is needed by the panic runtime. The symbol is named in
+// This function is needed by libunwind. The symbol is named in
 // pre-link args for the target specification, so keep that in sync.
+// Note: contrary to the `__rust_abort` in `crate::rt`, this uses `no_mangle`
+//       because it is actually used from C code. Because symbols annotated with
+//       #[rustc_std_internal_symbol] get mangled, this will not lead to linker
+//       conflicts.
 #[cfg(not(test))]
 #[unsafe(no_mangle)]
-// NB. used by both libunwind and libpanic_abort
 pub extern "C" fn __rust_abort() {
     abort_internal();
 }
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index 78fcfcb3b77..8911a2ee519 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -161,14 +161,6 @@ pub fn abort_internal() -> ! {
     core::intrinsics::abort();
 }
 
-// This function is needed by the panic runtime. The symbol is named in
-// pre-link args for the target specification, so keep that in sync.
-#[cfg(not(test))]
-#[unsafe(no_mangle)]
-pub extern "C" fn __rust_abort() {
-    abort_internal();
-}
-
 /// Disable access to BootServices if `EVT_SIGNAL_EXIT_BOOT_SERVICES` is signaled
 extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) {
     uefi::env::disable_boot_services();
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 8bf6d833515..a3be2cdf738 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -25,15 +25,36 @@ impl Drop for Handler {
     }
 }
 
-#[cfg(any(
-    target_os = "linux",
-    target_os = "freebsd",
-    target_os = "hurd",
-    target_os = "macos",
-    target_os = "netbsd",
-    target_os = "openbsd",
-    target_os = "solaris",
-    target_os = "illumos",
+#[cfg(all(
+    not(miri),
+    any(
+        target_os = "linux",
+        target_os = "freebsd",
+        target_os = "hurd",
+        target_os = "macos",
+        target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "solaris",
+        target_os = "illumos",
+    ),
+))]
+mod thread_info;
+
+// miri doesn't model signals nor stack overflows and this code has some
+// synchronization properties that we don't want to expose to user code,
+// hence we disable it on miri.
+#[cfg(all(
+    not(miri),
+    any(
+        target_os = "linux",
+        target_os = "freebsd",
+        target_os = "hurd",
+        target_os = "macos",
+        target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "solaris",
+        target_os = "illumos",
+    )
 ))]
 mod imp {
     use libc::{
@@ -46,22 +67,13 @@ mod imp {
     use libc::{mmap64, mprotect, munmap};
 
     use super::Handler;
-    use crate::cell::Cell;
+    use super::thread_info::{delete_current_info, set_current_info, with_current_info};
     use crate::ops::Range;
     use crate::sync::OnceLock;
     use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering};
     use crate::sys::pal::unix::os;
-    use crate::{io, mem, ptr, thread};
-
-    // We use a TLS variable to store the address of the guard page. While TLS
-    // variables are not guaranteed to be signal-safe, this works out in practice
-    // since we make sure to write to the variable before the signal stack is
-    // installed, thereby ensuring that the variable is always allocated when
-    // the signal handler is called.
-    thread_local! {
-        // FIXME: use `Range` once that implements `Copy`.
-        static GUARD: Cell<(usize, usize)> = const { Cell::new((0, 0)) };
-    }
+    use crate::thread::with_current_name;
+    use crate::{io, mem, panic, ptr};
 
     // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages
     // (unmapped pages) at the end of every thread's stack, so if a thread ends
@@ -93,29 +105,35 @@ mod imp {
         info: *mut libc::siginfo_t,
         _data: *mut libc::c_void,
     ) {
-        let (start, end) = GUARD.get();
         // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`.
-        let addr = unsafe { (*info).si_addr().addr() };
+        let fault_addr = unsafe { (*info).si_addr().addr() };
+
+        // `with_current_info` expects that the process aborts after it is
+        // called. If the signal was not caused by a memory access, this might
+        // not be true. We detect this by noticing that the `si_addr` field is
+        // zero if the signal is synthetic.
+        if fault_addr != 0 {
+            with_current_info(|thread_info| {
+                // If the faulting address is within the guard page, then we print a
+                // message saying so and abort.
+                if let Some(thread_info) = thread_info
+                    && thread_info.guard_page_range.contains(&fault_addr)
+                {
+                    let name = thread_info.thread_name.as_deref().unwrap_or("<unknown>");
+                    rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
+                    rtabort!("stack overflow");
+                }
+            })
+        }
 
-        // If the faulting address is within the guard page, then we print a
-        // message saying so and abort.
-        if start <= addr && addr < end {
-            thread::with_current_name(|name| {
-                let name = name.unwrap_or("<unknown>");
-                rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
-            });
+        // Unregister ourselves by reverting back to the default behavior.
+        // SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
+        let mut action: sigaction = unsafe { mem::zeroed() };
+        action.sa_sigaction = SIG_DFL;
+        // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction
+        unsafe { sigaction(signum, &action, ptr::null_mut()) };
 
-            rtabort!("stack overflow");
-        } else {
-            // Unregister ourselves by reverting back to the default behavior.
-            // SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
-            let mut action: sigaction = unsafe { mem::zeroed() };
-            action.sa_sigaction = SIG_DFL;
-            // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction
-            unsafe { sigaction(signum, &action, ptr::null_mut()) };
-
-            // See comment above for why this function returns.
-        }
+        // See comment above for why this function returns.
     }
 
     static PAGE_SIZE: Atomic<usize> = AtomicUsize::new(0);
@@ -128,9 +146,7 @@ mod imp {
     pub unsafe fn init() {
         PAGE_SIZE.store(os::page_size(), Ordering::Relaxed);
 
-        // Always write to GUARD to ensure the TLS variable is allocated.
-        let guard = unsafe { install_main_guard().unwrap_or(0..0) };
-        GUARD.set((guard.start, guard.end));
+        let mut guard_page_range = unsafe { install_main_guard() };
 
         // SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
         let mut action: sigaction = unsafe { mem::zeroed() };
@@ -145,7 +161,13 @@ mod imp {
                     let handler = unsafe { make_handler(true) };
                     MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
                     mem::forget(handler);
+
+                    if let Some(guard_page_range) = guard_page_range.take() {
+                        let thread_name = with_current_name(|name| name.map(Box::from));
+                        set_current_info(guard_page_range, thread_name);
+                    }
                 }
+
                 action.sa_flags = SA_SIGINFO | SA_ONSTACK;
                 action.sa_sigaction = signal_handler as sighandler_t;
                 // SAFETY: only overriding signals if the default is set
@@ -214,9 +236,10 @@ mod imp {
         }
 
         if !main_thread {
-            // Always write to GUARD to ensure the TLS variable is allocated.
-            let guard = unsafe { current_guard() }.unwrap_or(0..0);
-            GUARD.set((guard.start, guard.end));
+            if let Some(guard_page_range) = unsafe { current_guard() } {
+                let thread_name = with_current_name(|name| name.map(Box::from));
+                set_current_info(guard_page_range, thread_name);
+            }
         }
 
         // SAFETY: assuming stack_t is zero-initializable
@@ -261,6 +284,8 @@ mod imp {
             // a mapping that started one page earlier, so walk back a page and unmap from there.
             unsafe { munmap(data.sub(page_size), sigstack_size + page_size) };
         }
+
+        delete_current_info();
     }
 
     /// Modern kernels on modern hardware can have dynamic signal stack sizes.
@@ -590,17 +615,20 @@ mod imp {
 // usually have fewer qualms about forwards compatibility, since the runtime
 // is shipped with the OS):
 // <https://github.com/apple/swift/blob/swift-5.10-RELEASE/stdlib/public/runtime/CrashHandlerMacOS.cpp>
-#[cfg(not(any(
-    target_os = "linux",
-    target_os = "freebsd",
-    target_os = "hurd",
-    target_os = "macos",
-    target_os = "netbsd",
-    target_os = "openbsd",
-    target_os = "solaris",
-    target_os = "illumos",
-    target_os = "cygwin",
-)))]
+#[cfg(any(
+    miri,
+    not(any(
+        target_os = "linux",
+        target_os = "freebsd",
+        target_os = "hurd",
+        target_os = "macos",
+        target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "solaris",
+        target_os = "illumos",
+        target_os = "cygwin",
+    ))
+))]
 mod imp {
     pub unsafe fn init() {}
 
diff --git a/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs b/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs
new file mode 100644
index 00000000000..e81429b98a6
--- /dev/null
+++ b/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs
@@ -0,0 +1,129 @@
+//! TLS, but async-signal-safe.
+//!
+//! Unfortunately, because thread local storage isn't async-signal-safe, we
+//! cannot soundly use it in our stack overflow handler. While this works
+//! without problems on most platforms, it can lead to undefined behaviour
+//! on others (such as GNU/Linux). Luckily, the POSIX specification documents
+//! two thread-specific values that can be accessed in asynchronous signal
+//! handlers: the value of `pthread_self()` and the address of `errno`. As
+//! `pthread_t` is an opaque platform-specific type, we use the address of
+//! `errno` here. As it is thread-specific and does not change over the
+//! lifetime of a thread, we can use `&errno` as a key for a `BTreeMap`
+//! that stores thread-specific data.
+//!
+//! Concurrent access to this map is synchronized by two locks – an outer
+//! [`Mutex`] and an inner spin lock that also remembers the identity of
+//! the lock owner:
+//! * The spin lock is the primary means of synchronization: since it only
+//!   uses native atomics, it can be soundly used inside the signal handle
+//!   as opposed to [`Mutex`], which might not be async-signal-safe.
+//! * The [`Mutex`] prevents busy-waiting in the setup logic, as all accesses
+//!   there are performed with the [`Mutex`] held, which makes the spin-lock
+//!   redundant in the common case.
+//! * Finally, by using the `errno` address as the locked value of the spin
+//!   lock, we can detect cases where a SIGSEGV occurred while the thread
+//!   info is being modified.
+
+use crate::collections::BTreeMap;
+use crate::hint::spin_loop;
+use crate::ops::Range;
+use crate::sync::Mutex;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sys::os::errno_location;
+
+pub struct ThreadInfo {
+    pub guard_page_range: Range<usize>,
+    pub thread_name: Option<Box<str>>,
+}
+
+static LOCK: Mutex<()> = Mutex::new(());
+static SPIN_LOCK: AtomicUsize = AtomicUsize::new(0);
+// This uses a `BTreeMap` instead of a hashmap since it supports constant
+// initialization and automatically reduces the amount of memory used when
+// items are removed.
+static mut THREAD_INFO: BTreeMap<usize, ThreadInfo> = BTreeMap::new();
+
+struct UnlockOnDrop;
+
+impl Drop for UnlockOnDrop {
+    fn drop(&mut self) {
+        SPIN_LOCK.store(0, Ordering::Release);
+    }
+}
+
+/// Get the current thread's information, if available.
+///
+/// Calling this function might freeze other threads if they attempt to modify
+/// their thread information. Thus, the caller should ensure that the process
+/// is aborted shortly after this function is called.
+///
+/// This function is guaranteed to be async-signal-safe if `f` is too.
+pub fn with_current_info<R>(f: impl FnOnce(Option<&ThreadInfo>) -> R) -> R {
+    let this = errno_location().addr();
+    let mut attempt = 0;
+    let _guard = loop {
+        // If we are just spinning endlessly, it's very likely that the thread
+        // modifying the thread info map has a lower priority than us and will
+        // not continue until we stop running. Just give up in that case.
+        if attempt == 10_000_000 {
+            rtprintpanic!("deadlock in SIGSEGV handler");
+            return f(None);
+        }
+
+        match SPIN_LOCK.compare_exchange(0, this, Ordering::Acquire, Ordering::Relaxed) {
+            Ok(_) => break UnlockOnDrop,
+            Err(owner) if owner == this => {
+                rtabort!("a thread received SIGSEGV while modifying its stack overflow information")
+            }
+            // Spin until the lock can be acquired – there is nothing better to
+            // do. This is unfortunately a priority hole, but a stack overflow
+            // is a fatal error anyway.
+            Err(_) => {
+                spin_loop();
+                attempt += 1;
+            }
+        }
+    };
+
+    // SAFETY: we own the spin lock, so `THREAD_INFO` cannot not be aliased.
+    let thread_info = unsafe { &*(&raw const THREAD_INFO) };
+    f(thread_info.get(&this))
+}
+
+fn spin_lock_in_setup(this: usize) -> UnlockOnDrop {
+    loop {
+        match SPIN_LOCK.compare_exchange(0, this, Ordering::Acquire, Ordering::Relaxed) {
+            Ok(_) => return UnlockOnDrop,
+            Err(owner) if owner == this => {
+                unreachable!("the thread info setup logic isn't recursive")
+            }
+            // This function is always called with the outer lock held,
+            // meaning the only time locking can fail is if another thread has
+            // encountered a stack overflow. Since that will abort the process,
+            // we just stop the current thread until that time. We use `pause`
+            // instead of spinning to avoid priority inversion.
+            // SAFETY: this doesn't have any safety preconditions.
+            Err(_) => drop(unsafe { libc::pause() }),
+        }
+    }
+}
+
+pub fn set_current_info(guard_page_range: Range<usize>, thread_name: Option<Box<str>>) {
+    let this = errno_location().addr();
+    let _lock_guard = LOCK.lock();
+    let _spin_guard = spin_lock_in_setup(this);
+
+    // SAFETY: we own the spin lock, so `THREAD_INFO` cannot be aliased.
+    let thread_info = unsafe { &mut *(&raw mut THREAD_INFO) };
+    thread_info.insert(this, ThreadInfo { guard_page_range, thread_name });
+}
+
+pub fn delete_current_info() {
+    let this = errno_location().addr();
+    let _lock_guard = LOCK.lock();
+    let _spin_guard = spin_lock_in_setup(this);
+
+    // SAFETY: we own the spin lock, so `THREAD_INFO` cannot not be aliased.
+    let thread_info = unsafe { &mut *(&raw mut THREAD_INFO) };
+    thread_info.remove(&this);
+}
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index afda7c65e10..d8b189413f4 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -222,16 +222,8 @@ impl Thread {
 
     #[cfg(target_os = "vxworks")]
     pub fn set_name(name: &CStr) {
-        // FIXME(libc): adding real STATUS, ERROR type eventually.
-        unsafe extern "C" {
-            fn taskNameSet(task_id: libc::TASK_ID, task_name: *mut libc::c_char) -> libc::c_int;
-        }
-
-        //  VX_TASK_NAME_LEN is 31 in VxWorks 7.
-        const VX_TASK_NAME_LEN: usize = 31;
-
-        let mut name = truncate_cstr::<{ VX_TASK_NAME_LEN }>(name);
-        let res = unsafe { taskNameSet(libc::taskIdSelf(), name.as_mut_ptr()) };
+        let mut name = truncate_cstr::<{ libc::VX_TASK_RENAME_LENGTH - 1 }>(name);
+        let res = unsafe { libc::taskNameSet(libc::taskIdSelf(), name.as_mut_ptr()) };
         debug_assert_eq!(res, libc::OK);
     }
 
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index 4f18c4009ab..8f54e2376eb 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -328,8 +328,12 @@ pub fn dur2timeout(dur: Duration) -> u32 {
 
 /// Use `__fastfail` to abort the process
 ///
-/// This is the same implementation as in libpanic_abort's `__rust_start_panic`. See
-/// that function for more information on `__fastfail`
+/// In Windows 8 and later, this will terminate the process immediately without
+/// running any in-process exception handlers. In earlier versions of Windows,
+/// this sequence of instructions will be treated as an access violation, which
+/// will still terminate the process but might run some exception handlers.
+///
+/// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
 #[cfg(not(miri))] // inline assembly does not work in Miri
 pub fn abort_internal() -> ! {
     unsafe {
diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs
index 383d031ed43..042c4ff862f 100644
--- a/library/std/src/sys/pal/xous/mod.rs
+++ b/library/std/src/sys/pal/xous/mod.rs
@@ -1,5 +1,7 @@
 #![forbid(unsafe_op_in_unsafe_fn)]
 
+use crate::os::xous::ffi::exit;
+
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
@@ -9,3 +11,7 @@ pub mod time;
 #[path = "../unsupported/common.rs"]
 mod common;
 pub use common::*;
+
+pub fn abort_internal() -> ! {
+    exit(101);
+}
diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs
index 2230dabe096..d612a27d2bd 100644
--- a/library/std/src/sys/pal/xous/os.rs
+++ b/library/std/src/sys/pal/xous/os.rs
@@ -62,14 +62,6 @@ mod c_compat {
         }
         exit(unsafe { main() });
     }
-
-    // This function is needed by the panic runtime. The symbol is named in
-    // pre-link args for the target specification, so keep that in sync.
-    #[unsafe(no_mangle)]
-    // NB. used by both libunwind and libpanic_abort
-    pub extern "C" fn __rust_abort() -> ! {
-        exit(101);
-    }
 }
 
 pub fn errno() -> i32 {
diff --git a/library/std/src/sys/process/windows.rs b/library/std/src/sys/process/windows.rs
index 4acd753eec9..1ee3fbd285f 100644
--- a/library/std/src/sys/process/windows.rs
+++ b/library/std/src/sys/process/windows.rs
@@ -155,6 +155,9 @@ pub struct Command {
     stdout: Option<Stdio>,
     stderr: Option<Stdio>,
     force_quotes_enabled: bool,
+    startupinfo_fullscreen: bool,
+    startupinfo_untrusted_source: bool,
+    startupinfo_force_feedback: Option<bool>,
 }
 
 pub enum Stdio {
@@ -186,6 +189,9 @@ impl Command {
             stdout: None,
             stderr: None,
             force_quotes_enabled: false,
+            startupinfo_fullscreen: false,
+            startupinfo_untrusted_source: false,
+            startupinfo_force_feedback: None,
         }
     }
 
@@ -222,6 +228,18 @@ impl Command {
         self.args.push(Arg::Raw(command_str_to_append.to_os_string()))
     }
 
+    pub fn startupinfo_fullscreen(&mut self, enabled: bool) {
+        self.startupinfo_fullscreen = enabled;
+    }
+
+    pub fn startupinfo_untrusted_source(&mut self, enabled: bool) {
+        self.startupinfo_untrusted_source = enabled;
+    }
+
+    pub fn startupinfo_force_feedback(&mut self, enabled: Option<bool>) {
+        self.startupinfo_force_feedback = enabled;
+    }
+
     pub fn get_program(&self) -> &OsStr {
         &self.program
     }
@@ -343,6 +361,24 @@ impl Command {
             si.wShowWindow = cmd_show;
         }
 
+        if self.startupinfo_fullscreen {
+            si.dwFlags |= c::STARTF_RUNFULLSCREEN;
+        }
+
+        if self.startupinfo_untrusted_source {
+            si.dwFlags |= c::STARTF_UNTRUSTEDSOURCE;
+        }
+
+        match self.startupinfo_force_feedback {
+            Some(true) => {
+                si.dwFlags |= c::STARTF_FORCEONFEEDBACK;
+            }
+            Some(false) => {
+                si.dwFlags |= c::STARTF_FORCEOFFFEEDBACK;
+            }
+            None => {}
+        }
+
         let si_ptr: *mut c::STARTUPINFOW;
 
         let mut si_ex;
diff --git a/library/std/tests/floats/f128.rs b/library/std/tests/floats/f128.rs
index c2618f3b315..e7c90faa05c 100644
--- a/library/std/tests/floats/f128.rs
+++ b/library/std/tests/floats/f128.rs
@@ -2,49 +2,26 @@
 #![cfg(target_has_reliable_f128)]
 
 use std::f128::consts;
-use std::num::FpCategory as Fp;
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-use std::ops::Rem;
 use std::ops::{Add, Div, Mul, Sub};
 
 // Note these tolerances make sense around zero, but not for more extreme exponents.
 
-/// For operations that are near exact, usually not involving math of different
-/// signs.
-const TOL_PRECISE: f128 = 1e-28;
-
 /// Default tolerances. Works for values that should be near precise but not exact. Roughly
 /// the precision carried by `100 * 100`.
+#[cfg(not(miri))]
+#[cfg(target_has_reliable_f128_math)]
 const TOL: f128 = 1e-12;
 
+/// For operations that are near exact, usually not involving math of different
+/// signs.
+const TOL_PRECISE: f128 = 1e-28;
+
 /// Tolerances for math that is allowed to be imprecise, usually due to multiple chained
 /// operations.
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f128_math)]
 const TOL_IMPR: f128 = 1e-10;
 
-/// Smallest number
-const TINY_BITS: u128 = 0x1;
-
-/// Next smallest number
-const TINY_UP_BITS: u128 = 0x2;
-
-/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
-const MAX_DOWN_BITS: u128 = 0x7ffefffffffffffffffffffffffffffe;
-
-/// Zeroed exponent, full significant
-const LARGEST_SUBNORMAL_BITS: u128 = 0x0000ffffffffffffffffffffffffffff;
-
-/// Exponent = 0b1, zeroed significand
-const SMALLEST_NORMAL_BITS: u128 = 0x00010000000000000000000000000000;
-
-/// First pattern over the mantissa
-const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
-
-/// Second pattern over the mantissa
-const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
-
 /// Compare by representation
 #[allow(unused_macros)]
 macro_rules! assert_f128_biteq {
@@ -68,459 +45,11 @@ fn test_num_f128() {
     assert_eq!(ten.div(two), ten / two);
 }
 
-// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
-// the intrinsics.
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_num_f128_rem() {
-    let ten = 10f128;
-    let two = 2f128;
-    assert_eq!(ten.rem(two), ten % two);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_min_nan() {
-    assert_eq!(f128::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f128.min(f128::NAN), 2.0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_max_nan() {
-    assert_eq!(f128::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f128.max(f128::NAN), 2.0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_minimum() {
-    assert!(f128::NAN.minimum(2.0).is_nan());
-    assert!(2.0f128.minimum(f128::NAN).is_nan());
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_maximum() {
-    assert!(f128::NAN.maximum(2.0).is_nan());
-    assert!(2.0f128.maximum(f128::NAN).is_nan());
-}
-
-#[test]
-fn test_nan() {
-    let nan: f128 = f128::NAN;
-    assert!(nan.is_nan());
-    assert!(!nan.is_infinite());
-    assert!(!nan.is_finite());
-    assert!(nan.is_sign_positive());
-    assert!(!nan.is_sign_negative());
-    assert!(!nan.is_normal());
-    assert_eq!(Fp::Nan, nan.classify());
-    // Ensure the quiet bit is set.
-    assert!(nan.to_bits() & (1 << (f128::MANTISSA_DIGITS - 2)) != 0);
-}
-
-#[test]
-fn test_infinity() {
-    let inf: f128 = f128::INFINITY;
-    assert!(inf.is_infinite());
-    assert!(!inf.is_finite());
-    assert!(inf.is_sign_positive());
-    assert!(!inf.is_sign_negative());
-    assert!(!inf.is_nan());
-    assert!(!inf.is_normal());
-    assert_eq!(Fp::Infinite, inf.classify());
-}
-
-#[test]
-fn test_neg_infinity() {
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert!(neg_inf.is_infinite());
-    assert!(!neg_inf.is_finite());
-    assert!(!neg_inf.is_sign_positive());
-    assert!(neg_inf.is_sign_negative());
-    assert!(!neg_inf.is_nan());
-    assert!(!neg_inf.is_normal());
-    assert_eq!(Fp::Infinite, neg_inf.classify());
-}
-
-#[test]
-fn test_zero() {
-    let zero: f128 = 0.0f128;
-    assert_eq!(0.0, zero);
-    assert!(!zero.is_infinite());
-    assert!(zero.is_finite());
-    assert!(zero.is_sign_positive());
-    assert!(!zero.is_sign_negative());
-    assert!(!zero.is_nan());
-    assert!(!zero.is_normal());
-    assert_eq!(Fp::Zero, zero.classify());
-}
-
-#[test]
-fn test_neg_zero() {
-    let neg_zero: f128 = -0.0;
-    assert_eq!(0.0, neg_zero);
-    assert!(!neg_zero.is_infinite());
-    assert!(neg_zero.is_finite());
-    assert!(!neg_zero.is_sign_positive());
-    assert!(neg_zero.is_sign_negative());
-    assert!(!neg_zero.is_nan());
-    assert!(!neg_zero.is_normal());
-    assert_eq!(Fp::Zero, neg_zero.classify());
-}
-
-#[test]
-fn test_one() {
-    let one: f128 = 1.0f128;
-    assert_eq!(1.0, one);
-    assert!(!one.is_infinite());
-    assert!(one.is_finite());
-    assert!(one.is_sign_positive());
-    assert!(!one.is_sign_negative());
-    assert!(!one.is_nan());
-    assert!(one.is_normal());
-    assert_eq!(Fp::Normal, one.classify());
-}
-
-#[test]
-fn test_is_nan() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert!(nan.is_nan());
-    assert!(!0.0f128.is_nan());
-    assert!(!5.3f128.is_nan());
-    assert!(!(-10.732f128).is_nan());
-    assert!(!inf.is_nan());
-    assert!(!neg_inf.is_nan());
-}
-
-#[test]
-fn test_is_infinite() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert!(!nan.is_infinite());
-    assert!(inf.is_infinite());
-    assert!(neg_inf.is_infinite());
-    assert!(!0.0f128.is_infinite());
-    assert!(!42.8f128.is_infinite());
-    assert!(!(-109.2f128).is_infinite());
-}
-
-#[test]
-fn test_is_finite() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert!(!nan.is_finite());
-    assert!(!inf.is_finite());
-    assert!(!neg_inf.is_finite());
-    assert!(0.0f128.is_finite());
-    assert!(42.8f128.is_finite());
-    assert!((-109.2f128).is_finite());
-}
-
-#[test]
-fn test_is_normal() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    let zero: f128 = 0.0f128;
-    let neg_zero: f128 = -0.0;
-    assert!(!nan.is_normal());
-    assert!(!inf.is_normal());
-    assert!(!neg_inf.is_normal());
-    assert!(!zero.is_normal());
-    assert!(!neg_zero.is_normal());
-    assert!(1f128.is_normal());
-    assert!(1e-4931f128.is_normal());
-    assert!(!1e-4932f128.is_normal());
-}
-
-#[test]
-fn test_classify() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    let zero: f128 = 0.0f128;
-    let neg_zero: f128 = -0.0;
-    assert_eq!(nan.classify(), Fp::Nan);
-    assert_eq!(inf.classify(), Fp::Infinite);
-    assert_eq!(neg_inf.classify(), Fp::Infinite);
-    assert_eq!(zero.classify(), Fp::Zero);
-    assert_eq!(neg_zero.classify(), Fp::Zero);
-    assert_eq!(1f128.classify(), Fp::Normal);
-    assert_eq!(1e-4931f128.classify(), Fp::Normal);
-    assert_eq!(1e-4932f128.classify(), Fp::Subnormal);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_floor() {
-    assert_approx_eq!(1.0f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.floor(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).floor(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).floor(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).floor(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).floor(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).floor(), -2.0f128, TOL_PRECISE);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_ceil() {
-    assert_approx_eq!(1.0f128.ceil(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.ceil(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).ceil(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).ceil(), -1.0f128, TOL_PRECISE);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_round() {
-    assert_approx_eq!(2.5f128.round(), 3.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.0f128.round(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.round(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.round(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.round(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.round(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).round(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).round(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).round(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).round(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).round(), -2.0f128, TOL_PRECISE);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_round_ties_even() {
-    assert_approx_eq!(2.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.0f128.round_ties_even(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.round_ties_even(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.round_ties_even(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).round_ties_even(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).round_ties_even(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).round_ties_even(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).round_ties_even(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).round_ties_even(), -2.0f128, TOL_PRECISE);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_trunc() {
-    assert_approx_eq!(1.0f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.trunc(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).trunc(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).trunc(), -1.0f128, TOL_PRECISE);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_fract() {
-    assert_approx_eq!(1.0f128.fract(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.fract(), 0.3f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.fract(), 0.5f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.fract(), 0.7f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.fract(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).fract(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).fract(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).fract(), -0.3f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).fract(), -0.5f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).fract(), -0.7f128, TOL_PRECISE);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_abs() {
-    assert_eq!(f128::INFINITY.abs(), f128::INFINITY);
-    assert_eq!(1f128.abs(), 1f128);
-    assert_eq!(0f128.abs(), 0f128);
-    assert_eq!((-0f128).abs(), 0f128);
-    assert_eq!((-1f128).abs(), 1f128);
-    assert_eq!(f128::NEG_INFINITY.abs(), f128::INFINITY);
-    assert_eq!((1f128 / f128::NEG_INFINITY).abs(), 0f128);
-    assert!(f128::NAN.abs().is_nan());
-}
-
-#[test]
-fn test_is_sign_positive() {
-    assert!(f128::INFINITY.is_sign_positive());
-    assert!(1f128.is_sign_positive());
-    assert!(0f128.is_sign_positive());
-    assert!(!(-0f128).is_sign_positive());
-    assert!(!(-1f128).is_sign_positive());
-    assert!(!f128::NEG_INFINITY.is_sign_positive());
-    assert!(!(1f128 / f128::NEG_INFINITY).is_sign_positive());
-    assert!(f128::NAN.is_sign_positive());
-    assert!(!(-f128::NAN).is_sign_positive());
-}
-
-#[test]
-fn test_is_sign_negative() {
-    assert!(!f128::INFINITY.is_sign_negative());
-    assert!(!1f128.is_sign_negative());
-    assert!(!0f128.is_sign_negative());
-    assert!((-0f128).is_sign_negative());
-    assert!((-1f128).is_sign_negative());
-    assert!(f128::NEG_INFINITY.is_sign_negative());
-    assert!((1f128 / f128::NEG_INFINITY).is_sign_negative());
-    assert!(!f128::NAN.is_sign_negative());
-    assert!((-f128::NAN).is_sign_negative());
-}
-
-#[test]
-fn test_next_up() {
-    let tiny = f128::from_bits(TINY_BITS);
-    let tiny_up = f128::from_bits(TINY_UP_BITS);
-    let max_down = f128::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f128_biteq!(f128::NEG_INFINITY.next_up(), f128::MIN);
-    assert_f128_biteq!(f128::MIN.next_up(), -max_down);
-    assert_f128_biteq!((-1.0 - f128::EPSILON).next_up(), -1.0);
-    assert_f128_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f128_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f128_biteq!((-tiny).next_up(), -0.0f128);
-    assert_f128_biteq!((-0.0f128).next_up(), tiny);
-    assert_f128_biteq!(0.0f128.next_up(), tiny);
-    assert_f128_biteq!(tiny.next_up(), tiny_up);
-    assert_f128_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f128_biteq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
-    assert_f128_biteq!(f128::MAX.next_up(), f128::INFINITY);
-    assert_f128_biteq!(f128::INFINITY.next_up(), f128::INFINITY);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f128::NAN;
-    let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
-    let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
-    assert_f128_biteq!(nan0.next_up(), nan0);
-    assert_f128_biteq!(nan1.next_up(), nan1);
-    assert_f128_biteq!(nan2.next_up(), nan2);
-}
-
-#[test]
-fn test_next_down() {
-    let tiny = f128::from_bits(TINY_BITS);
-    let tiny_up = f128::from_bits(TINY_UP_BITS);
-    let max_down = f128::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f128_biteq!(f128::NEG_INFINITY.next_down(), f128::NEG_INFINITY);
-    assert_f128_biteq!(f128::MIN.next_down(), f128::NEG_INFINITY);
-    assert_f128_biteq!((-max_down).next_down(), f128::MIN);
-    assert_f128_biteq!((-1.0f128).next_down(), -1.0 - f128::EPSILON);
-    assert_f128_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f128_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f128_biteq!((-0.0f128).next_down(), -tiny);
-    assert_f128_biteq!((0.0f128).next_down(), -tiny);
-    assert_f128_biteq!(tiny.next_down(), 0.0f128);
-    assert_f128_biteq!(tiny_up.next_down(), tiny);
-    assert_f128_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f128_biteq!((1.0 + f128::EPSILON).next_down(), 1.0f128);
-    assert_f128_biteq!(f128::MAX.next_down(), max_down);
-    assert_f128_biteq!(f128::INFINITY.next_down(), f128::MAX);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f128::NAN;
-    let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
-    let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
-    assert_f128_biteq!(nan0.next_down(), nan0);
-    assert_f128_biteq!(nan1.next_down(), nan1);
-    assert_f128_biteq!(nan2.next_down(), nan2);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_mul_add() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_approx_eq!(12.3f128.mul_add(4.5, 6.7), 62.05, TOL_PRECISE);
-    assert_approx_eq!((-12.3f128).mul_add(-4.5, -6.7), 48.65, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.mul_add(8.9, 1.2), 1.2, TOL_PRECISE);
-    assert_approx_eq!(3.4f128.mul_add(-0.0, 5.6), 5.6, TOL_PRECISE);
-    assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f128.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f128).mul_add(2.4, neg_inf), neg_inf);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_recip() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(1.0f128.recip(), 1.0);
-    assert_eq!(2.0f128.recip(), 0.5);
-    assert_eq!((-0.4f128).recip(), -2.5);
-    assert_eq!(0.0f128.recip(), inf);
-    assert_approx_eq!(
-        f128::MAX.recip(),
-        8.40525785778023376565669454330438228902076605e-4933,
-        1e-4900
-    );
-    assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
-}
-
 // Many math functions allow for less accurate results, so the next tolerance up is used
 
 #[test]
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f128_math)]
-fn test_powi() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(1.0f128.powi(1), 1.0);
-    assert_approx_eq!((-3.1f128).powi(2), 9.6100000000000005506706202140776519387, TOL);
-    assert_approx_eq!(5.9f128.powi(-2), 0.028727377190462507313100483690639638451, TOL);
-    assert_eq!(8.3f128.powi(0), 1.0);
-    assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
 fn test_powf() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
@@ -539,19 +68,6 @@ fn test_powf() {
 #[test]
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f128_math)]
-fn test_sqrt_domain() {
-    assert!(f128::NAN.sqrt().is_nan());
-    assert!(f128::NEG_INFINITY.sqrt().is_nan());
-    assert!((-1.0f128).sqrt().is_nan());
-    assert_eq!((-0.0f128).sqrt(), -0.0);
-    assert_eq!(0.0f128.sqrt(), 0.0);
-    assert_eq!(1.0f128.sqrt(), 1.0);
-    assert_eq!(f128::INFINITY.sqrt(), f128::INFINITY);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
 fn test_exp() {
     assert_eq!(1.0, 0.0f128.exp());
     assert_approx_eq!(consts::E, 1.0f128.exp(), TOL);
@@ -655,38 +171,6 @@ fn test_log10() {
 }
 
 #[test]
-fn test_to_degrees() {
-    let pi: f128 = consts::PI;
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(0.0f128.to_degrees(), 0.0);
-    assert_approx_eq!((-5.8f128).to_degrees(), -332.31552117587745090765431723855668471, TOL);
-    assert_approx_eq!(pi.to_degrees(), 180.0, TOL);
-    assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f128.to_degrees(), 57.2957795130823208767981548141051703);
-}
-
-#[test]
-fn test_to_radians() {
-    let pi: f128 = consts::PI;
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(0.0f128.to_radians(), 0.0);
-    assert_approx_eq!(154.6f128.to_radians(), 2.6982790235832334267135442069489767804, TOL);
-    assert_approx_eq!((-332.31f128).to_radians(), -5.7999036373023566567593094812182763013, TOL);
-    // check approx rather than exact because round trip for pi doesn't fall on an exactly
-    // representable value (unlike `f32` and `f64`).
-    assert_approx_eq!(180.0f128.to_radians(), pi, TOL_PRECISE);
-    assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
-}
-
-#[test]
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f128_math)]
 fn test_asinh() {
@@ -835,237 +319,3 @@ fn test_real_consts() {
         assert_approx_eq!(ln_10, 10f128.ln(), TOL_PRECISE);
     }
 }
-
-#[test]
-fn test_float_bits_conv() {
-    assert_eq!((1f128).to_bits(), 0x3fff0000000000000000000000000000);
-    assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
-    assert_eq!((1337f128).to_bits(), 0x40094e40000000000000000000000000);
-    assert_eq!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000);
-    assert_approx_eq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0x40029000000000000000000000000000), 12.5, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25, TOL_PRECISE);
-
-    // Check that NaNs roundtrip their bits regardless of signaling-ness
-    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
-    let masked_nan1 = f128::NAN.to_bits() ^ NAN_MASK1;
-    let masked_nan2 = f128::NAN.to_bits() ^ NAN_MASK2;
-    assert!(f128::from_bits(masked_nan1).is_nan());
-    assert!(f128::from_bits(masked_nan2).is_nan());
-
-    assert_eq!(f128::from_bits(masked_nan1).to_bits(), masked_nan1);
-    assert_eq!(f128::from_bits(masked_nan2).to_bits(), masked_nan2);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_greater_than_max() {
-    let _ = 1.0f128.clamp(3.0, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_is_nan() {
-    let _ = 1.0f128.clamp(f128::NAN, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_max_is_nan() {
-    let _ = 1.0f128.clamp(3.0, f128::NAN);
-}
-
-#[test]
-fn test_total_cmp() {
-    use core::cmp::Ordering;
-
-    fn quiet_bit_mask() -> u128 {
-        1 << (f128::MANTISSA_DIGITS - 2)
-    }
-
-    // FIXME(f16_f128): test subnormals when powf is available
-    // fn min_subnorm() -> f128 {
-    //     f128::MIN_POSITIVE / f128::powf(2.0, f128::MANTISSA_DIGITS as f128 - 1.0)
-    // }
-
-    // fn max_subnorm() -> f128 {
-    //     f128::MIN_POSITIVE - min_subnorm()
-    // }
-
-    fn q_nan() -> f128 {
-        f128::from_bits(f128::NAN.to_bits() | quiet_bit_mask())
-    }
-
-    fn s_nan() -> f128 {
-        f128::from_bits((f128::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    }
-
-    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Equal, (-f128::INFINITY).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Equal, (-f128::MAX).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Equal, (-2.5_f128).total_cmp(&-2.5));
-    assert_eq!(Ordering::Equal, (-1.0_f128).total_cmp(&-1.0));
-    assert_eq!(Ordering::Equal, (-1.5_f128).total_cmp(&-1.5));
-    assert_eq!(Ordering::Equal, (-0.5_f128).total_cmp(&-0.5));
-    assert_eq!(Ordering::Equal, (-f128::MIN_POSITIVE).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Equal, (-0.0_f128).total_cmp(&-0.0));
-    assert_eq!(Ordering::Equal, 0.0_f128.total_cmp(&0.0));
-    // assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Equal, f128::MIN_POSITIVE.total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, 0.5_f128.total_cmp(&0.5));
-    assert_eq!(Ordering::Equal, 1.0_f128.total_cmp(&1.0));
-    assert_eq!(Ordering::Equal, 1.5_f128.total_cmp(&1.5));
-    assert_eq!(Ordering::Equal, 2.5_f128.total_cmp(&2.5));
-    assert_eq!(Ordering::Equal, f128::MAX.total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Equal, f128::INFINITY.total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
-    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Less, (-f128::INFINITY).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Less, (-f128::MAX).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-2.5_f128).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-1.5_f128).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-1.0_f128).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-0.5_f128).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-f128::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    // assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-0.0_f128).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, 0.0_f128.total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    // assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, f128::MIN_POSITIVE.total_cmp(&0.5));
-    assert_eq!(Ordering::Less, 0.5_f128.total_cmp(&1.0));
-    assert_eq!(Ordering::Less, 1.0_f128.total_cmp(&1.5));
-    assert_eq!(Ordering::Less, 1.5_f128.total_cmp(&2.5));
-    assert_eq!(Ordering::Less, 2.5_f128.total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Less, f128::MAX.total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Less, f128::INFINITY.total_cmp(&s_nan()));
-    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Greater, (-f128::INFINITY).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Greater, (-f128::MAX).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Greater, (-2.5_f128).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Greater, (-1.5_f128).total_cmp(&-2.5));
-    assert_eq!(Ordering::Greater, (-1.0_f128).total_cmp(&-1.5));
-    assert_eq!(Ordering::Greater, (-0.5_f128).total_cmp(&-1.0));
-    assert_eq!(Ordering::Greater, (-f128::MIN_POSITIVE).total_cmp(&-0.5));
-    // assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Greater, (-0.0_f128).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Greater, 0.0_f128.total_cmp(&-0.0));
-    // assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    // assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Greater, f128::MIN_POSITIVE.total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Greater, 0.5_f128.total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, 1.0_f128.total_cmp(&0.5));
-    assert_eq!(Ordering::Greater, 1.5_f128.total_cmp(&1.0));
-    assert_eq!(Ordering::Greater, 2.5_f128.total_cmp(&1.5));
-    assert_eq!(Ordering::Greater, f128::MAX.total_cmp(&2.5));
-    assert_eq!(Ordering::Greater, f128::INFINITY.total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
-}
-
-#[test]
-fn test_algebraic() {
-    let a: f128 = 123.0;
-    let b: f128 = 456.0;
-
-    // Check that individual operations match their primitive counterparts.
-    //
-    // This is a check of current implementations and does NOT imply any form of
-    // guarantee about future behavior. The compiler reserves the right to make
-    // these operations inexact matches in the future.
-    let eps = if cfg!(miri) { 1e-6 } else { 0.0 };
-
-    assert_approx_eq!(a.algebraic_add(b), a + b, eps);
-    assert_approx_eq!(a.algebraic_sub(b), a - b, eps);
-    assert_approx_eq!(a.algebraic_mul(b), a * b, eps);
-    assert_approx_eq!(a.algebraic_div(b), a / b, eps);
-    assert_approx_eq!(a.algebraic_rem(b), a % b, eps);
-}
-
-#[test]
-fn test_from() {
-    assert_eq!(f128::from(false), 0.0);
-    assert_eq!(f128::from(true), 1.0);
-    assert_eq!(f128::from(u8::MIN), 0.0);
-    assert_eq!(f128::from(42_u8), 42.0);
-    assert_eq!(f128::from(u8::MAX), 255.0);
-    assert_eq!(f128::from(i8::MIN), -128.0);
-    assert_eq!(f128::from(42_i8), 42.0);
-    assert_eq!(f128::from(i8::MAX), 127.0);
-    assert_eq!(f128::from(u16::MIN), 0.0);
-    assert_eq!(f128::from(42_u16), 42.0);
-    assert_eq!(f128::from(u16::MAX), 65535.0);
-    assert_eq!(f128::from(i16::MIN), -32768.0);
-    assert_eq!(f128::from(42_i16), 42.0);
-    assert_eq!(f128::from(i16::MAX), 32767.0);
-    assert_eq!(f128::from(u32::MIN), 0.0);
-    assert_eq!(f128::from(42_u32), 42.0);
-    assert_eq!(f128::from(u32::MAX), 4294967295.0);
-    assert_eq!(f128::from(i32::MIN), -2147483648.0);
-    assert_eq!(f128::from(42_i32), 42.0);
-    assert_eq!(f128::from(i32::MAX), 2147483647.0);
-    // FIXME(f16_f128): Uncomment these tests once the From<{u64,i64}> impls are added.
-    // assert_eq!(f128::from(u64::MIN), 0.0);
-    // assert_eq!(f128::from(42_u64), 42.0);
-    // assert_eq!(f128::from(u64::MAX), 18446744073709551615.0);
-    // assert_eq!(f128::from(i64::MIN), -9223372036854775808.0);
-    // assert_eq!(f128::from(42_i64), 42.0);
-    // assert_eq!(f128::from(i64::MAX), 9223372036854775807.0);
-}
diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs
index 70bbcd07160..0f8b4138d22 100644
--- a/library/std/tests/floats/f16.rs
+++ b/library/std/tests/floats/f16.rs
@@ -2,7 +2,6 @@
 #![cfg(target_has_reliable_f16)]
 
 use std::f16::consts;
-use std::num::FpCategory as Fp;
 
 /// Tolerance for results on the order of 10.0e-2
 #[allow(unused)]
@@ -20,27 +19,6 @@ const TOL_P2: f16 = 0.5;
 #[allow(unused)]
 const TOL_P4: f16 = 10.0;
 
-/// Smallest number
-const TINY_BITS: u16 = 0x1;
-
-/// Next smallest number
-const TINY_UP_BITS: u16 = 0x2;
-
-/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
-const MAX_DOWN_BITS: u16 = 0x7bfe;
-
-/// Zeroed exponent, full significant
-const LARGEST_SUBNORMAL_BITS: u16 = 0x03ff;
-
-/// Exponent = 0b1, zeroed significand
-const SMALLEST_NORMAL_BITS: u16 = 0x0400;
-
-/// First pattern over the mantissa
-const NAN_MASK1: u16 = 0x02aa;
-
-/// Second pattern over the mantissa
-const NAN_MASK2: u16 = 0x0155;
-
 /// Compare by representation
 #[allow(unused_macros)]
 macro_rules! assert_f16_biteq {
@@ -53,446 +31,6 @@ macro_rules! assert_f16_biteq {
 }
 
 #[test]
-fn test_num_f16() {
-    crate::test_num(10f16, 2f16);
-}
-
-// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
-// the intrinsics.
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_min_nan() {
-    assert_eq!(f16::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f16.min(f16::NAN), 2.0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_max_nan() {
-    assert_eq!(f16::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f16.max(f16::NAN), 2.0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_minimum() {
-    assert!(f16::NAN.minimum(2.0).is_nan());
-    assert!(2.0f16.minimum(f16::NAN).is_nan());
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_maximum() {
-    assert!(f16::NAN.maximum(2.0).is_nan());
-    assert!(2.0f16.maximum(f16::NAN).is_nan());
-}
-
-#[test]
-fn test_nan() {
-    let nan: f16 = f16::NAN;
-    assert!(nan.is_nan());
-    assert!(!nan.is_infinite());
-    assert!(!nan.is_finite());
-    assert!(nan.is_sign_positive());
-    assert!(!nan.is_sign_negative());
-    assert!(!nan.is_normal());
-    assert_eq!(Fp::Nan, nan.classify());
-    // Ensure the quiet bit is set.
-    assert!(nan.to_bits() & (1 << (f16::MANTISSA_DIGITS - 2)) != 0);
-}
-
-#[test]
-fn test_infinity() {
-    let inf: f16 = f16::INFINITY;
-    assert!(inf.is_infinite());
-    assert!(!inf.is_finite());
-    assert!(inf.is_sign_positive());
-    assert!(!inf.is_sign_negative());
-    assert!(!inf.is_nan());
-    assert!(!inf.is_normal());
-    assert_eq!(Fp::Infinite, inf.classify());
-}
-
-#[test]
-fn test_neg_infinity() {
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert!(neg_inf.is_infinite());
-    assert!(!neg_inf.is_finite());
-    assert!(!neg_inf.is_sign_positive());
-    assert!(neg_inf.is_sign_negative());
-    assert!(!neg_inf.is_nan());
-    assert!(!neg_inf.is_normal());
-    assert_eq!(Fp::Infinite, neg_inf.classify());
-}
-
-#[test]
-fn test_zero() {
-    let zero: f16 = 0.0f16;
-    assert_eq!(0.0, zero);
-    assert!(!zero.is_infinite());
-    assert!(zero.is_finite());
-    assert!(zero.is_sign_positive());
-    assert!(!zero.is_sign_negative());
-    assert!(!zero.is_nan());
-    assert!(!zero.is_normal());
-    assert_eq!(Fp::Zero, zero.classify());
-}
-
-#[test]
-fn test_neg_zero() {
-    let neg_zero: f16 = -0.0;
-    assert_eq!(0.0, neg_zero);
-    assert!(!neg_zero.is_infinite());
-    assert!(neg_zero.is_finite());
-    assert!(!neg_zero.is_sign_positive());
-    assert!(neg_zero.is_sign_negative());
-    assert!(!neg_zero.is_nan());
-    assert!(!neg_zero.is_normal());
-    assert_eq!(Fp::Zero, neg_zero.classify());
-}
-
-#[test]
-fn test_one() {
-    let one: f16 = 1.0f16;
-    assert_eq!(1.0, one);
-    assert!(!one.is_infinite());
-    assert!(one.is_finite());
-    assert!(one.is_sign_positive());
-    assert!(!one.is_sign_negative());
-    assert!(!one.is_nan());
-    assert!(one.is_normal());
-    assert_eq!(Fp::Normal, one.classify());
-}
-
-#[test]
-fn test_is_nan() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert!(nan.is_nan());
-    assert!(!0.0f16.is_nan());
-    assert!(!5.3f16.is_nan());
-    assert!(!(-10.732f16).is_nan());
-    assert!(!inf.is_nan());
-    assert!(!neg_inf.is_nan());
-}
-
-#[test]
-fn test_is_infinite() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert!(!nan.is_infinite());
-    assert!(inf.is_infinite());
-    assert!(neg_inf.is_infinite());
-    assert!(!0.0f16.is_infinite());
-    assert!(!42.8f16.is_infinite());
-    assert!(!(-109.2f16).is_infinite());
-}
-
-#[test]
-fn test_is_finite() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert!(!nan.is_finite());
-    assert!(!inf.is_finite());
-    assert!(!neg_inf.is_finite());
-    assert!(0.0f16.is_finite());
-    assert!(42.8f16.is_finite());
-    assert!((-109.2f16).is_finite());
-}
-
-#[test]
-fn test_is_normal() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    let zero: f16 = 0.0f16;
-    let neg_zero: f16 = -0.0;
-    assert!(!nan.is_normal());
-    assert!(!inf.is_normal());
-    assert!(!neg_inf.is_normal());
-    assert!(!zero.is_normal());
-    assert!(!neg_zero.is_normal());
-    assert!(1f16.is_normal());
-    assert!(1e-4f16.is_normal());
-    assert!(!1e-5f16.is_normal());
-}
-
-#[test]
-fn test_classify() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    let zero: f16 = 0.0f16;
-    let neg_zero: f16 = -0.0;
-    assert_eq!(nan.classify(), Fp::Nan);
-    assert_eq!(inf.classify(), Fp::Infinite);
-    assert_eq!(neg_inf.classify(), Fp::Infinite);
-    assert_eq!(zero.classify(), Fp::Zero);
-    assert_eq!(neg_zero.classify(), Fp::Zero);
-    assert_eq!(1f16.classify(), Fp::Normal);
-    assert_eq!(1e-4f16.classify(), Fp::Normal);
-    assert_eq!(1e-5f16.classify(), Fp::Subnormal);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_floor() {
-    assert_approx_eq!(1.0f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.floor(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).floor(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).floor(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).floor(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).floor(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).floor(), -2.0f16, TOL_0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_ceil() {
-    assert_approx_eq!(1.0f16.ceil(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.ceil(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).ceil(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).ceil(), -1.0f16, TOL_0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_round() {
-    assert_approx_eq!(2.5f16.round(), 3.0f16, TOL_0);
-    assert_approx_eq!(1.0f16.round(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.round(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.round(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.round(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.round(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).round(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).round(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).round(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).round(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).round(), -2.0f16, TOL_0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_round_ties_even() {
-    assert_approx_eq!(2.5f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.0f16.round_ties_even(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.round_ties_even(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.round_ties_even(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).round_ties_even(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).round_ties_even(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).round_ties_even(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).round_ties_even(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).round_ties_even(), -2.0f16, TOL_0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_trunc() {
-    assert_approx_eq!(1.0f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.trunc(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).trunc(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).trunc(), -1.0f16, TOL_0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_fract() {
-    assert_approx_eq!(1.0f16.fract(), 0.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.fract(), 0.3f16, TOL_0);
-    assert_approx_eq!(1.5f16.fract(), 0.5f16, TOL_0);
-    assert_approx_eq!(1.7f16.fract(), 0.7f16, TOL_0);
-    assert_approx_eq!(0.0f16.fract(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).fract(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).fract(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).fract(), -0.3f16, TOL_0);
-    assert_approx_eq!((-1.5f16).fract(), -0.5f16, TOL_0);
-    assert_approx_eq!((-1.7f16).fract(), -0.7f16, TOL_0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_abs() {
-    assert_eq!(f16::INFINITY.abs(), f16::INFINITY);
-    assert_eq!(1f16.abs(), 1f16);
-    assert_eq!(0f16.abs(), 0f16);
-    assert_eq!((-0f16).abs(), 0f16);
-    assert_eq!((-1f16).abs(), 1f16);
-    assert_eq!(f16::NEG_INFINITY.abs(), f16::INFINITY);
-    assert_eq!((1f16 / f16::NEG_INFINITY).abs(), 0f16);
-    assert!(f16::NAN.abs().is_nan());
-}
-
-#[test]
-fn test_is_sign_positive() {
-    assert!(f16::INFINITY.is_sign_positive());
-    assert!(1f16.is_sign_positive());
-    assert!(0f16.is_sign_positive());
-    assert!(!(-0f16).is_sign_positive());
-    assert!(!(-1f16).is_sign_positive());
-    assert!(!f16::NEG_INFINITY.is_sign_positive());
-    assert!(!(1f16 / f16::NEG_INFINITY).is_sign_positive());
-    assert!(f16::NAN.is_sign_positive());
-    assert!(!(-f16::NAN).is_sign_positive());
-}
-
-#[test]
-fn test_is_sign_negative() {
-    assert!(!f16::INFINITY.is_sign_negative());
-    assert!(!1f16.is_sign_negative());
-    assert!(!0f16.is_sign_negative());
-    assert!((-0f16).is_sign_negative());
-    assert!((-1f16).is_sign_negative());
-    assert!(f16::NEG_INFINITY.is_sign_negative());
-    assert!((1f16 / f16::NEG_INFINITY).is_sign_negative());
-    assert!(!f16::NAN.is_sign_negative());
-    assert!((-f16::NAN).is_sign_negative());
-}
-
-#[test]
-fn test_next_up() {
-    let tiny = f16::from_bits(TINY_BITS);
-    let tiny_up = f16::from_bits(TINY_UP_BITS);
-    let max_down = f16::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f16_biteq!(f16::NEG_INFINITY.next_up(), f16::MIN);
-    assert_f16_biteq!(f16::MIN.next_up(), -max_down);
-    assert_f16_biteq!((-1.0 - f16::EPSILON).next_up(), -1.0);
-    assert_f16_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f16_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f16_biteq!((-tiny).next_up(), -0.0f16);
-    assert_f16_biteq!((-0.0f16).next_up(), tiny);
-    assert_f16_biteq!(0.0f16.next_up(), tiny);
-    assert_f16_biteq!(tiny.next_up(), tiny_up);
-    assert_f16_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f16_biteq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
-    assert_f16_biteq!(f16::MAX.next_up(), f16::INFINITY);
-    assert_f16_biteq!(f16::INFINITY.next_up(), f16::INFINITY);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f16::NAN;
-    let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
-    assert_f16_biteq!(nan0.next_up(), nan0);
-    assert_f16_biteq!(nan1.next_up(), nan1);
-    assert_f16_biteq!(nan2.next_up(), nan2);
-}
-
-#[test]
-fn test_next_down() {
-    let tiny = f16::from_bits(TINY_BITS);
-    let tiny_up = f16::from_bits(TINY_UP_BITS);
-    let max_down = f16::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f16_biteq!(f16::NEG_INFINITY.next_down(), f16::NEG_INFINITY);
-    assert_f16_biteq!(f16::MIN.next_down(), f16::NEG_INFINITY);
-    assert_f16_biteq!((-max_down).next_down(), f16::MIN);
-    assert_f16_biteq!((-1.0f16).next_down(), -1.0 - f16::EPSILON);
-    assert_f16_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f16_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f16_biteq!((-0.0f16).next_down(), -tiny);
-    assert_f16_biteq!((0.0f16).next_down(), -tiny);
-    assert_f16_biteq!(tiny.next_down(), 0.0f16);
-    assert_f16_biteq!(tiny_up.next_down(), tiny);
-    assert_f16_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f16_biteq!((1.0 + f16::EPSILON).next_down(), 1.0f16);
-    assert_f16_biteq!(f16::MAX.next_down(), max_down);
-    assert_f16_biteq!(f16::INFINITY.next_down(), f16::MAX);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f16::NAN;
-    let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
-    assert_f16_biteq!(nan0.next_down(), nan0);
-    assert_f16_biteq!(nan1.next_down(), nan1);
-    assert_f16_biteq!(nan2.next_down(), nan2);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_mul_add() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_approx_eq!(12.3f16.mul_add(4.5, 6.7), 62.05, TOL_P2);
-    assert_approx_eq!((-12.3f16).mul_add(-4.5, -6.7), 48.65, TOL_P2);
-    assert_approx_eq!(0.0f16.mul_add(8.9, 1.2), 1.2, TOL_0);
-    assert_approx_eq!(3.4f16.mul_add(-0.0, 5.6), 5.6, TOL_0);
-    assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f16.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_recip() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(1.0f16.recip(), 1.0);
-    assert_eq!(2.0f16.recip(), 0.5);
-    assert_eq!((-0.4f16).recip(), -2.5);
-    assert_eq!(0.0f16.recip(), inf);
-    assert_approx_eq!(f16::MAX.recip(), 1.526624e-5f16, 1e-4);
-    assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_powi() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(1.0f16.powi(1), 1.0);
-    assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0);
-    assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2);
-    assert_eq!(8.3f16.powi(0), 1.0);
-    assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
-}
-
-#[test]
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f16_math)]
 fn test_powf() {
@@ -513,19 +51,6 @@ fn test_powf() {
 #[test]
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f16_math)]
-fn test_sqrt_domain() {
-    assert!(f16::NAN.sqrt().is_nan());
-    assert!(f16::NEG_INFINITY.sqrt().is_nan());
-    assert!((-1.0f16).sqrt().is_nan());
-    assert_eq!((-0.0f16).sqrt(), -0.0);
-    assert_eq!(0.0f16.sqrt(), 0.0);
-    assert_eq!(1.0f16.sqrt(), 1.0);
-    assert_eq!(f16::INFINITY.sqrt(), f16::INFINITY);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
 fn test_exp() {
     assert_eq!(1.0, 0.0f16.exp());
     assert_approx_eq!(2.718282, 1.0f16.exp(), TOL_0);
@@ -629,36 +154,6 @@ fn test_log10() {
 }
 
 #[test]
-fn test_to_degrees() {
-    let pi: f16 = consts::PI;
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(0.0f16.to_degrees(), 0.0);
-    assert_approx_eq!((-5.8f16).to_degrees(), -332.315521, TOL_P2);
-    assert_approx_eq!(pi.to_degrees(), 180.0, TOL_P2);
-    assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703);
-}
-
-#[test]
-fn test_to_radians() {
-    let pi: f16 = consts::PI;
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(0.0f16.to_radians(), 0.0);
-    assert_approx_eq!(154.6f16.to_radians(), 2.698279, TOL_0);
-    assert_approx_eq!((-332.31f16).to_radians(), -5.799903, TOL_0);
-    assert_approx_eq!(180.0f16.to_radians(), pi, TOL_0);
-    assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
-}
-
-#[test]
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f16_math)]
 fn test_asinh() {
@@ -803,220 +298,3 @@ fn test_real_consts() {
         assert_approx_eq!(ln_10, 10f16.ln(), TOL_0);
     }
 }
-
-#[test]
-fn test_float_bits_conv() {
-    assert_eq!((1f16).to_bits(), 0x3c00);
-    assert_eq!((12.5f16).to_bits(), 0x4a40);
-    assert_eq!((1337f16).to_bits(), 0x6539);
-    assert_eq!((-14.25f16).to_bits(), 0xcb20);
-    assert_approx_eq!(f16::from_bits(0x3c00), 1.0, TOL_0);
-    assert_approx_eq!(f16::from_bits(0x4a40), 12.5, TOL_0);
-    assert_approx_eq!(f16::from_bits(0x6539), 1337.0, TOL_P4);
-    assert_approx_eq!(f16::from_bits(0xcb20), -14.25, TOL_0);
-
-    // Check that NaNs roundtrip their bits regardless of signaling-ness
-    let masked_nan1 = f16::NAN.to_bits() ^ NAN_MASK1;
-    let masked_nan2 = f16::NAN.to_bits() ^ NAN_MASK2;
-    assert!(f16::from_bits(masked_nan1).is_nan());
-    assert!(f16::from_bits(masked_nan2).is_nan());
-
-    assert_eq!(f16::from_bits(masked_nan1).to_bits(), masked_nan1);
-    assert_eq!(f16::from_bits(masked_nan2).to_bits(), masked_nan2);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_greater_than_max() {
-    let _ = 1.0f16.clamp(3.0, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_is_nan() {
-    let _ = 1.0f16.clamp(f16::NAN, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_max_is_nan() {
-    let _ = 1.0f16.clamp(3.0, f16::NAN);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_total_cmp() {
-    use core::cmp::Ordering;
-
-    fn quiet_bit_mask() -> u16 {
-        1 << (f16::MANTISSA_DIGITS - 2)
-    }
-
-    fn min_subnorm() -> f16 {
-        f16::MIN_POSITIVE / f16::powf(2.0, f16::MANTISSA_DIGITS as f16 - 1.0)
-    }
-
-    fn max_subnorm() -> f16 {
-        f16::MIN_POSITIVE - min_subnorm()
-    }
-
-    fn q_nan() -> f16 {
-        f16::from_bits(f16::NAN.to_bits() | quiet_bit_mask())
-    }
-
-    fn s_nan() -> f16 {
-        f16::from_bits((f16::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    }
-
-    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Equal, (-f16::INFINITY).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Equal, (-f16::MAX).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Equal, (-2.5_f16).total_cmp(&-2.5));
-    assert_eq!(Ordering::Equal, (-1.0_f16).total_cmp(&-1.0));
-    assert_eq!(Ordering::Equal, (-1.5_f16).total_cmp(&-1.5));
-    assert_eq!(Ordering::Equal, (-0.5_f16).total_cmp(&-0.5));
-    assert_eq!(Ordering::Equal, (-f16::MIN_POSITIVE).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Equal, (-0.0_f16).total_cmp(&-0.0));
-    assert_eq!(Ordering::Equal, 0.0_f16.total_cmp(&0.0));
-    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Equal, f16::MIN_POSITIVE.total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, 0.5_f16.total_cmp(&0.5));
-    assert_eq!(Ordering::Equal, 1.0_f16.total_cmp(&1.0));
-    assert_eq!(Ordering::Equal, 1.5_f16.total_cmp(&1.5));
-    assert_eq!(Ordering::Equal, 2.5_f16.total_cmp(&2.5));
-    assert_eq!(Ordering::Equal, f16::MAX.total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Equal, f16::INFINITY.total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
-    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Less, (-f16::INFINITY).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Less, (-f16::MAX).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-2.5_f16).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-1.5_f16).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-1.0_f16).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-0.5_f16).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-f16::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-0.0_f16).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, 0.0_f16.total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, f16::MIN_POSITIVE.total_cmp(&0.5));
-    assert_eq!(Ordering::Less, 0.5_f16.total_cmp(&1.0));
-    assert_eq!(Ordering::Less, 1.0_f16.total_cmp(&1.5));
-    assert_eq!(Ordering::Less, 1.5_f16.total_cmp(&2.5));
-    assert_eq!(Ordering::Less, 2.5_f16.total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Less, f16::MAX.total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Less, f16::INFINITY.total_cmp(&s_nan()));
-    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Greater, (-f16::INFINITY).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Greater, (-f16::MAX).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Greater, (-2.5_f16).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Greater, (-1.5_f16).total_cmp(&-2.5));
-    assert_eq!(Ordering::Greater, (-1.0_f16).total_cmp(&-1.5));
-    assert_eq!(Ordering::Greater, (-0.5_f16).total_cmp(&-1.0));
-    assert_eq!(Ordering::Greater, (-f16::MIN_POSITIVE).total_cmp(&-0.5));
-    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Greater, (-0.0_f16).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Greater, 0.0_f16.total_cmp(&-0.0));
-    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Greater, f16::MIN_POSITIVE.total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Greater, 0.5_f16.total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, 1.0_f16.total_cmp(&0.5));
-    assert_eq!(Ordering::Greater, 1.5_f16.total_cmp(&1.0));
-    assert_eq!(Ordering::Greater, 2.5_f16.total_cmp(&1.5));
-    assert_eq!(Ordering::Greater, f16::MAX.total_cmp(&2.5));
-    assert_eq!(Ordering::Greater, f16::INFINITY.total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
-}
-
-#[test]
-fn test_algebraic() {
-    let a: f16 = 123.0;
-    let b: f16 = 456.0;
-
-    // Check that individual operations match their primitive counterparts.
-    //
-    // This is a check of current implementations and does NOT imply any form of
-    // guarantee about future behavior. The compiler reserves the right to make
-    // these operations inexact matches in the future.
-    let eps_add = if cfg!(miri) { 1e1 } else { 0.0 };
-    let eps_mul = if cfg!(miri) { 1e3 } else { 0.0 };
-    let eps_div = if cfg!(miri) { 1e0 } else { 0.0 };
-
-    assert_approx_eq!(a.algebraic_add(b), a + b, eps_add);
-    assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add);
-    assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul);
-    assert_approx_eq!(a.algebraic_div(b), a / b, eps_div);
-    assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div);
-}
-
-#[test]
-fn test_from() {
-    assert_eq!(f16::from(false), 0.0);
-    assert_eq!(f16::from(true), 1.0);
-    assert_eq!(f16::from(u8::MIN), 0.0);
-    assert_eq!(f16::from(42_u8), 42.0);
-    assert_eq!(f16::from(u8::MAX), 255.0);
-    assert_eq!(f16::from(i8::MIN), -128.0);
-    assert_eq!(f16::from(42_i8), 42.0);
-    assert_eq!(f16::from(i8::MAX), 127.0);
-}
diff --git a/library/std/tests/floats/f32.rs b/library/std/tests/floats/f32.rs
index 9af23afc5bb..e54f227bb77 100644
--- a/library/std/tests/floats/f32.rs
+++ b/library/std/tests/floats/f32.rs
@@ -1,26 +1,4 @@
 use std::f32::consts;
-use std::num::FpCategory as Fp;
-
-/// Smallest number
-const TINY_BITS: u32 = 0x1;
-
-/// Next smallest number
-const TINY_UP_BITS: u32 = 0x2;
-
-/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
-const MAX_DOWN_BITS: u32 = 0x7f7f_fffe;
-
-/// Zeroed exponent, full significant
-const LARGEST_SUBNORMAL_BITS: u32 = 0x007f_ffff;
-
-/// Exponent = 0b1, zeroed significand
-const SMALLEST_NORMAL_BITS: u32 = 0x0080_0000;
-
-/// First pattern over the mantissa
-const NAN_MASK1: u32 = 0x002a_aaaa;
-
-/// Second pattern over the mantissa
-const NAN_MASK2: u32 = 0x0055_5555;
 
 #[allow(unused_macros)]
 macro_rules! assert_f32_biteq {
@@ -34,426 +12,6 @@ macro_rules! assert_f32_biteq {
 }
 
 #[test]
-fn test_num_f32() {
-    crate::test_num(10f32, 2f32);
-}
-
-#[test]
-fn test_min_nan() {
-    assert_eq!(f32::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f32.min(f32::NAN), 2.0);
-}
-
-#[test]
-fn test_max_nan() {
-    assert_eq!(f32::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f32.max(f32::NAN), 2.0);
-}
-
-#[test]
-fn test_minimum() {
-    assert!(f32::NAN.minimum(2.0).is_nan());
-    assert!(2.0f32.minimum(f32::NAN).is_nan());
-}
-
-#[test]
-fn test_maximum() {
-    assert!(f32::NAN.maximum(2.0).is_nan());
-    assert!(2.0f32.maximum(f32::NAN).is_nan());
-}
-
-#[test]
-fn test_nan() {
-    let nan: f32 = f32::NAN;
-    assert!(nan.is_nan());
-    assert!(!nan.is_infinite());
-    assert!(!nan.is_finite());
-    assert!(!nan.is_normal());
-    assert!(nan.is_sign_positive());
-    assert!(!nan.is_sign_negative());
-    assert_eq!(Fp::Nan, nan.classify());
-    // Ensure the quiet bit is set.
-    assert!(nan.to_bits() & (1 << (f32::MANTISSA_DIGITS - 2)) != 0);
-}
-
-#[test]
-fn test_infinity() {
-    let inf: f32 = f32::INFINITY;
-    assert!(inf.is_infinite());
-    assert!(!inf.is_finite());
-    assert!(inf.is_sign_positive());
-    assert!(!inf.is_sign_negative());
-    assert!(!inf.is_nan());
-    assert!(!inf.is_normal());
-    assert_eq!(Fp::Infinite, inf.classify());
-}
-
-#[test]
-fn test_neg_infinity() {
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert!(neg_inf.is_infinite());
-    assert!(!neg_inf.is_finite());
-    assert!(!neg_inf.is_sign_positive());
-    assert!(neg_inf.is_sign_negative());
-    assert!(!neg_inf.is_nan());
-    assert!(!neg_inf.is_normal());
-    assert_eq!(Fp::Infinite, neg_inf.classify());
-}
-
-#[test]
-fn test_zero() {
-    let zero: f32 = 0.0f32;
-    assert_eq!(0.0, zero);
-    assert!(!zero.is_infinite());
-    assert!(zero.is_finite());
-    assert!(zero.is_sign_positive());
-    assert!(!zero.is_sign_negative());
-    assert!(!zero.is_nan());
-    assert!(!zero.is_normal());
-    assert_eq!(Fp::Zero, zero.classify());
-}
-
-#[test]
-fn test_neg_zero() {
-    let neg_zero: f32 = -0.0;
-    assert_eq!(0.0, neg_zero);
-    assert!(!neg_zero.is_infinite());
-    assert!(neg_zero.is_finite());
-    assert!(!neg_zero.is_sign_positive());
-    assert!(neg_zero.is_sign_negative());
-    assert!(!neg_zero.is_nan());
-    assert!(!neg_zero.is_normal());
-    assert_eq!(Fp::Zero, neg_zero.classify());
-}
-
-#[test]
-fn test_one() {
-    let one: f32 = 1.0f32;
-    assert_eq!(1.0, one);
-    assert!(!one.is_infinite());
-    assert!(one.is_finite());
-    assert!(one.is_sign_positive());
-    assert!(!one.is_sign_negative());
-    assert!(!one.is_nan());
-    assert!(one.is_normal());
-    assert_eq!(Fp::Normal, one.classify());
-}
-
-#[test]
-fn test_is_nan() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert!(nan.is_nan());
-    assert!(!0.0f32.is_nan());
-    assert!(!5.3f32.is_nan());
-    assert!(!(-10.732f32).is_nan());
-    assert!(!inf.is_nan());
-    assert!(!neg_inf.is_nan());
-}
-
-#[test]
-fn test_is_infinite() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert!(!nan.is_infinite());
-    assert!(inf.is_infinite());
-    assert!(neg_inf.is_infinite());
-    assert!(!0.0f32.is_infinite());
-    assert!(!42.8f32.is_infinite());
-    assert!(!(-109.2f32).is_infinite());
-}
-
-#[test]
-fn test_is_finite() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert!(!nan.is_finite());
-    assert!(!inf.is_finite());
-    assert!(!neg_inf.is_finite());
-    assert!(0.0f32.is_finite());
-    assert!(42.8f32.is_finite());
-    assert!((-109.2f32).is_finite());
-}
-
-#[test]
-fn test_is_normal() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    let zero: f32 = 0.0f32;
-    let neg_zero: f32 = -0.0;
-    assert!(!nan.is_normal());
-    assert!(!inf.is_normal());
-    assert!(!neg_inf.is_normal());
-    assert!(!zero.is_normal());
-    assert!(!neg_zero.is_normal());
-    assert!(1f32.is_normal());
-    assert!(1e-37f32.is_normal());
-    assert!(!1e-38f32.is_normal());
-}
-
-#[test]
-fn test_classify() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    let zero: f32 = 0.0f32;
-    let neg_zero: f32 = -0.0;
-    assert_eq!(nan.classify(), Fp::Nan);
-    assert_eq!(inf.classify(), Fp::Infinite);
-    assert_eq!(neg_inf.classify(), Fp::Infinite);
-    assert_eq!(zero.classify(), Fp::Zero);
-    assert_eq!(neg_zero.classify(), Fp::Zero);
-    assert_eq!(1f32.classify(), Fp::Normal);
-    assert_eq!(1e-37f32.classify(), Fp::Normal);
-    assert_eq!(1e-38f32.classify(), Fp::Subnormal);
-}
-
-#[test]
-fn test_floor() {
-    assert_approx_eq!(1.0f32.floor(), 1.0f32);
-    assert_approx_eq!(1.3f32.floor(), 1.0f32);
-    assert_approx_eq!(1.5f32.floor(), 1.0f32);
-    assert_approx_eq!(1.7f32.floor(), 1.0f32);
-    assert_approx_eq!(0.0f32.floor(), 0.0f32);
-    assert_approx_eq!((-0.0f32).floor(), -0.0f32);
-    assert_approx_eq!((-1.0f32).floor(), -1.0f32);
-    assert_approx_eq!((-1.3f32).floor(), -2.0f32);
-    assert_approx_eq!((-1.5f32).floor(), -2.0f32);
-    assert_approx_eq!((-1.7f32).floor(), -2.0f32);
-}
-
-#[test]
-fn test_ceil() {
-    assert_approx_eq!(1.0f32.ceil(), 1.0f32);
-    assert_approx_eq!(1.3f32.ceil(), 2.0f32);
-    assert_approx_eq!(1.5f32.ceil(), 2.0f32);
-    assert_approx_eq!(1.7f32.ceil(), 2.0f32);
-    assert_approx_eq!(0.0f32.ceil(), 0.0f32);
-    assert_approx_eq!((-0.0f32).ceil(), -0.0f32);
-    assert_approx_eq!((-1.0f32).ceil(), -1.0f32);
-    assert_approx_eq!((-1.3f32).ceil(), -1.0f32);
-    assert_approx_eq!((-1.5f32).ceil(), -1.0f32);
-    assert_approx_eq!((-1.7f32).ceil(), -1.0f32);
-}
-
-#[test]
-fn test_round() {
-    assert_approx_eq!(2.5f32.round(), 3.0f32);
-    assert_approx_eq!(1.0f32.round(), 1.0f32);
-    assert_approx_eq!(1.3f32.round(), 1.0f32);
-    assert_approx_eq!(1.5f32.round(), 2.0f32);
-    assert_approx_eq!(1.7f32.round(), 2.0f32);
-    assert_approx_eq!(0.0f32.round(), 0.0f32);
-    assert_approx_eq!((-0.0f32).round(), -0.0f32);
-    assert_approx_eq!((-1.0f32).round(), -1.0f32);
-    assert_approx_eq!((-1.3f32).round(), -1.0f32);
-    assert_approx_eq!((-1.5f32).round(), -2.0f32);
-    assert_approx_eq!((-1.7f32).round(), -2.0f32);
-}
-
-#[test]
-fn test_round_ties_even() {
-    assert_approx_eq!(2.5f32.round_ties_even(), 2.0f32);
-    assert_approx_eq!(1.0f32.round_ties_even(), 1.0f32);
-    assert_approx_eq!(1.3f32.round_ties_even(), 1.0f32);
-    assert_approx_eq!(1.5f32.round_ties_even(), 2.0f32);
-    assert_approx_eq!(1.7f32.round_ties_even(), 2.0f32);
-    assert_approx_eq!(0.0f32.round_ties_even(), 0.0f32);
-    assert_approx_eq!((-0.0f32).round_ties_even(), -0.0f32);
-    assert_approx_eq!((-1.0f32).round_ties_even(), -1.0f32);
-    assert_approx_eq!((-1.3f32).round_ties_even(), -1.0f32);
-    assert_approx_eq!((-1.5f32).round_ties_even(), -2.0f32);
-    assert_approx_eq!((-1.7f32).round_ties_even(), -2.0f32);
-}
-
-#[test]
-fn test_trunc() {
-    assert_approx_eq!(1.0f32.trunc(), 1.0f32);
-    assert_approx_eq!(1.3f32.trunc(), 1.0f32);
-    assert_approx_eq!(1.5f32.trunc(), 1.0f32);
-    assert_approx_eq!(1.7f32.trunc(), 1.0f32);
-    assert_approx_eq!(0.0f32.trunc(), 0.0f32);
-    assert_approx_eq!((-0.0f32).trunc(), -0.0f32);
-    assert_approx_eq!((-1.0f32).trunc(), -1.0f32);
-    assert_approx_eq!((-1.3f32).trunc(), -1.0f32);
-    assert_approx_eq!((-1.5f32).trunc(), -1.0f32);
-    assert_approx_eq!((-1.7f32).trunc(), -1.0f32);
-}
-
-#[test]
-fn test_fract() {
-    assert_approx_eq!(1.0f32.fract(), 0.0f32);
-    assert_approx_eq!(1.3f32.fract(), 0.3f32);
-    assert_approx_eq!(1.5f32.fract(), 0.5f32);
-    assert_approx_eq!(1.7f32.fract(), 0.7f32);
-    assert_approx_eq!(0.0f32.fract(), 0.0f32);
-    assert_approx_eq!((-0.0f32).fract(), -0.0f32);
-    assert_approx_eq!((-1.0f32).fract(), -0.0f32);
-    assert_approx_eq!((-1.3f32).fract(), -0.3f32);
-    assert_approx_eq!((-1.5f32).fract(), -0.5f32);
-    assert_approx_eq!((-1.7f32).fract(), -0.7f32);
-}
-
-#[test]
-fn test_abs() {
-    assert_eq!(f32::INFINITY.abs(), f32::INFINITY);
-    assert_eq!(1f32.abs(), 1f32);
-    assert_eq!(0f32.abs(), 0f32);
-    assert_eq!((-0f32).abs(), 0f32);
-    assert_eq!((-1f32).abs(), 1f32);
-    assert_eq!(f32::NEG_INFINITY.abs(), f32::INFINITY);
-    assert_eq!((1f32 / f32::NEG_INFINITY).abs(), 0f32);
-    assert!(f32::NAN.abs().is_nan());
-}
-
-#[test]
-fn test_signum() {
-    assert_eq!(f32::INFINITY.signum(), 1f32);
-    assert_eq!(1f32.signum(), 1f32);
-    assert_eq!(0f32.signum(), 1f32);
-    assert_eq!((-0f32).signum(), -1f32);
-    assert_eq!((-1f32).signum(), -1f32);
-    assert_eq!(f32::NEG_INFINITY.signum(), -1f32);
-    assert_eq!((1f32 / f32::NEG_INFINITY).signum(), -1f32);
-    assert!(f32::NAN.signum().is_nan());
-}
-
-#[test]
-fn test_is_sign_positive() {
-    assert!(f32::INFINITY.is_sign_positive());
-    assert!(1f32.is_sign_positive());
-    assert!(0f32.is_sign_positive());
-    assert!(!(-0f32).is_sign_positive());
-    assert!(!(-1f32).is_sign_positive());
-    assert!(!f32::NEG_INFINITY.is_sign_positive());
-    assert!(!(1f32 / f32::NEG_INFINITY).is_sign_positive());
-    assert!(f32::NAN.is_sign_positive());
-    assert!(!(-f32::NAN).is_sign_positive());
-}
-
-#[test]
-fn test_is_sign_negative() {
-    assert!(!f32::INFINITY.is_sign_negative());
-    assert!(!1f32.is_sign_negative());
-    assert!(!0f32.is_sign_negative());
-    assert!((-0f32).is_sign_negative());
-    assert!((-1f32).is_sign_negative());
-    assert!(f32::NEG_INFINITY.is_sign_negative());
-    assert!((1f32 / f32::NEG_INFINITY).is_sign_negative());
-    assert!(!f32::NAN.is_sign_negative());
-    assert!((-f32::NAN).is_sign_negative());
-}
-
-#[test]
-fn test_next_up() {
-    let tiny = f32::from_bits(TINY_BITS);
-    let tiny_up = f32::from_bits(TINY_UP_BITS);
-    let max_down = f32::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f32_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN);
-    assert_f32_biteq!(f32::MIN.next_up(), -max_down);
-    assert_f32_biteq!((-1.0 - f32::EPSILON).next_up(), -1.0);
-    assert_f32_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f32_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f32_biteq!((-tiny).next_up(), -0.0f32);
-    assert_f32_biteq!((-0.0f32).next_up(), tiny);
-    assert_f32_biteq!(0.0f32.next_up(), tiny);
-    assert_f32_biteq!(tiny.next_up(), tiny_up);
-    assert_f32_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f32_biteq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
-    assert_f32_biteq!(f32::MAX.next_up(), f32::INFINITY);
-    assert_f32_biteq!(f32::INFINITY.next_up(), f32::INFINITY);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f32::NAN;
-    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
-    assert_f32_biteq!(nan0.next_up(), nan0);
-    assert_f32_biteq!(nan1.next_up(), nan1);
-    assert_f32_biteq!(nan2.next_up(), nan2);
-}
-
-#[test]
-fn test_next_down() {
-    let tiny = f32::from_bits(TINY_BITS);
-    let tiny_up = f32::from_bits(TINY_UP_BITS);
-    let max_down = f32::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f32_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
-    assert_f32_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY);
-    assert_f32_biteq!((-max_down).next_down(), f32::MIN);
-    assert_f32_biteq!((-1.0f32).next_down(), -1.0 - f32::EPSILON);
-    assert_f32_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f32_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f32_biteq!((-0.0f32).next_down(), -tiny);
-    assert_f32_biteq!((0.0f32).next_down(), -tiny);
-    assert_f32_biteq!(tiny.next_down(), 0.0f32);
-    assert_f32_biteq!(tiny_up.next_down(), tiny);
-    assert_f32_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f32_biteq!((1.0 + f32::EPSILON).next_down(), 1.0f32);
-    assert_f32_biteq!(f32::MAX.next_down(), max_down);
-    assert_f32_biteq!(f32::INFINITY.next_down(), f32::MAX);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f32::NAN;
-    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
-    assert_f32_biteq!(nan0.next_down(), nan0);
-    assert_f32_biteq!(nan1.next_down(), nan1);
-    assert_f32_biteq!(nan2.next_down(), nan2);
-}
-
-#[test]
-fn test_mul_add() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_approx_eq!(12.3f32.mul_add(4.5, 6.7), 62.05);
-    assert_approx_eq!((-12.3f32).mul_add(-4.5, -6.7), 48.65);
-    assert_approx_eq!(0.0f32.mul_add(8.9, 1.2), 1.2);
-    assert_approx_eq!(3.4f32.mul_add(-0.0, 5.6), 5.6);
-    assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f32.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f32).mul_add(2.4, neg_inf), neg_inf);
-}
-
-#[test]
-fn test_recip() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(1.0f32.recip(), 1.0);
-    assert_eq!(2.0f32.recip(), 0.5);
-    assert_eq!((-0.4f32).recip(), -2.5);
-    assert_eq!(0.0f32.recip(), inf);
-    assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
-}
-
-#[test]
-fn test_powi() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(1.0f32.powi(1), 1.0);
-    assert_approx_eq!((-3.1f32).powi(2), 9.61);
-    assert_approx_eq!(5.9f32.powi(-2), 0.028727);
-    assert_eq!(8.3f32.powi(0), 1.0);
-    assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
-}
-
-#[test]
 fn test_powf() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
@@ -470,17 +28,6 @@ fn test_powf() {
 }
 
 #[test]
-fn test_sqrt_domain() {
-    assert!(f32::NAN.sqrt().is_nan());
-    assert!(f32::NEG_INFINITY.sqrt().is_nan());
-    assert!((-1.0f32).sqrt().is_nan());
-    assert_eq!((-0.0f32).sqrt(), -0.0);
-    assert_eq!(0.0f32.sqrt(), 0.0);
-    assert_eq!(1.0f32.sqrt(), 1.0);
-    assert_eq!(f32::INFINITY.sqrt(), f32::INFINITY);
-}
-
-#[test]
 fn test_exp() {
     assert_eq!(1.0, 0.0f32.exp());
     assert_approx_eq!(2.718282, 1.0f32.exp());
@@ -574,36 +121,6 @@ fn test_log10() {
 }
 
 #[test]
-fn test_to_degrees() {
-    let pi: f32 = consts::PI;
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(0.0f32.to_degrees(), 0.0);
-    assert_approx_eq!((-5.8f32).to_degrees(), -332.315521);
-    assert_eq!(pi.to_degrees(), 180.0);
-    assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
-}
-
-#[test]
-fn test_to_radians() {
-    let pi: f32 = consts::PI;
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(0.0f32.to_radians(), 0.0);
-    assert_approx_eq!(154.6f32.to_radians(), 2.698279);
-    assert_approx_eq!((-332.31f32).to_radians(), -5.799903);
-    assert_eq!(180.0f32.to_radians(), pi);
-    assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
-}
-
-#[test]
 fn test_asinh() {
     assert_eq!(0.0f32.asinh(), 0.0f32);
     assert_eq!((-0.0f32).asinh(), -0.0f32);
@@ -734,207 +251,3 @@ fn test_real_consts() {
     assert_approx_eq!(ln_2, 2f32.ln());
     assert_approx_eq!(ln_10, 10f32.ln());
 }
-
-#[test]
-fn test_float_bits_conv() {
-    assert_eq!((1f32).to_bits(), 0x3f800000);
-    assert_eq!((12.5f32).to_bits(), 0x41480000);
-    assert_eq!((1337f32).to_bits(), 0x44a72000);
-    assert_eq!((-14.25f32).to_bits(), 0xc1640000);
-    assert_approx_eq!(f32::from_bits(0x3f800000), 1.0);
-    assert_approx_eq!(f32::from_bits(0x41480000), 12.5);
-    assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
-    assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
-
-    // Check that NaNs roundtrip their bits regardless of signaling-ness
-    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
-    let masked_nan1 = f32::NAN.to_bits() ^ NAN_MASK1;
-    let masked_nan2 = f32::NAN.to_bits() ^ NAN_MASK2;
-    assert!(f32::from_bits(masked_nan1).is_nan());
-    assert!(f32::from_bits(masked_nan2).is_nan());
-
-    assert_eq!(f32::from_bits(masked_nan1).to_bits(), masked_nan1);
-    assert_eq!(f32::from_bits(masked_nan2).to_bits(), masked_nan2);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_greater_than_max() {
-    let _ = 1.0f32.clamp(3.0, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_is_nan() {
-    let _ = 1.0f32.clamp(f32::NAN, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_max_is_nan() {
-    let _ = 1.0f32.clamp(3.0, f32::NAN);
-}
-
-#[test]
-fn test_total_cmp() {
-    use core::cmp::Ordering;
-
-    fn quiet_bit_mask() -> u32 {
-        1 << (f32::MANTISSA_DIGITS - 2)
-    }
-
-    fn min_subnorm() -> f32 {
-        f32::MIN_POSITIVE / f32::powf(2.0, f32::MANTISSA_DIGITS as f32 - 1.0)
-    }
-
-    fn max_subnorm() -> f32 {
-        f32::MIN_POSITIVE - min_subnorm()
-    }
-
-    fn q_nan() -> f32 {
-        f32::from_bits(f32::NAN.to_bits() | quiet_bit_mask())
-    }
-
-    fn s_nan() -> f32 {
-        f32::from_bits((f32::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    }
-
-    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Equal, (-f32::INFINITY).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Equal, (-f32::MAX).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Equal, (-2.5_f32).total_cmp(&-2.5));
-    assert_eq!(Ordering::Equal, (-1.0_f32).total_cmp(&-1.0));
-    assert_eq!(Ordering::Equal, (-1.5_f32).total_cmp(&-1.5));
-    assert_eq!(Ordering::Equal, (-0.5_f32).total_cmp(&-0.5));
-    assert_eq!(Ordering::Equal, (-f32::MIN_POSITIVE).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Equal, (-0.0_f32).total_cmp(&-0.0));
-    assert_eq!(Ordering::Equal, 0.0_f32.total_cmp(&0.0));
-    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Equal, f32::MIN_POSITIVE.total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, 0.5_f32.total_cmp(&0.5));
-    assert_eq!(Ordering::Equal, 1.0_f32.total_cmp(&1.0));
-    assert_eq!(Ordering::Equal, 1.5_f32.total_cmp(&1.5));
-    assert_eq!(Ordering::Equal, 2.5_f32.total_cmp(&2.5));
-    assert_eq!(Ordering::Equal, f32::MAX.total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Equal, f32::INFINITY.total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
-    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Less, (-f32::INFINITY).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Less, (-f32::MAX).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-2.5_f32).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-1.5_f32).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-1.0_f32).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-0.5_f32).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-f32::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-0.0_f32).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, 0.0_f32.total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, f32::MIN_POSITIVE.total_cmp(&0.5));
-    assert_eq!(Ordering::Less, 0.5_f32.total_cmp(&1.0));
-    assert_eq!(Ordering::Less, 1.0_f32.total_cmp(&1.5));
-    assert_eq!(Ordering::Less, 1.5_f32.total_cmp(&2.5));
-    assert_eq!(Ordering::Less, 2.5_f32.total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Less, f32::MAX.total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Less, f32::INFINITY.total_cmp(&s_nan()));
-    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Greater, (-f32::INFINITY).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Greater, (-f32::MAX).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Greater, (-2.5_f32).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Greater, (-1.5_f32).total_cmp(&-2.5));
-    assert_eq!(Ordering::Greater, (-1.0_f32).total_cmp(&-1.5));
-    assert_eq!(Ordering::Greater, (-0.5_f32).total_cmp(&-1.0));
-    assert_eq!(Ordering::Greater, (-f32::MIN_POSITIVE).total_cmp(&-0.5));
-    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Greater, (-0.0_f32).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Greater, 0.0_f32.total_cmp(&-0.0));
-    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Greater, f32::MIN_POSITIVE.total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Greater, 0.5_f32.total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, 1.0_f32.total_cmp(&0.5));
-    assert_eq!(Ordering::Greater, 1.5_f32.total_cmp(&1.0));
-    assert_eq!(Ordering::Greater, 2.5_f32.total_cmp(&1.5));
-    assert_eq!(Ordering::Greater, f32::MAX.total_cmp(&2.5));
-    assert_eq!(Ordering::Greater, f32::INFINITY.total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
-}
-
-#[test]
-fn test_algebraic() {
-    let a: f32 = 123.0;
-    let b: f32 = 456.0;
-
-    // Check that individual operations match their primitive counterparts.
-    //
-    // This is a check of current implementations and does NOT imply any form of
-    // guarantee about future behavior. The compiler reserves the right to make
-    // these operations inexact matches in the future.
-    let eps_add = if cfg!(miri) { 1e-3 } else { 0.0 };
-    let eps_mul = if cfg!(miri) { 1e-1 } else { 0.0 };
-    let eps_div = if cfg!(miri) { 1e-4 } else { 0.0 };
-
-    assert_approx_eq!(a.algebraic_add(b), a + b, eps_add);
-    assert_approx_eq!(a.algebraic_sub(b), a - b, eps_add);
-    assert_approx_eq!(a.algebraic_mul(b), a * b, eps_mul);
-    assert_approx_eq!(a.algebraic_div(b), a / b, eps_div);
-    assert_approx_eq!(a.algebraic_rem(b), a % b, eps_div);
-}
diff --git a/library/std/tests/floats/f64.rs b/library/std/tests/floats/f64.rs
index de9c27eb33d..2d8dd1cf091 100644
--- a/library/std/tests/floats/f64.rs
+++ b/library/std/tests/floats/f64.rs
@@ -1,26 +1,4 @@
 use std::f64::consts;
-use std::num::FpCategory as Fp;
-
-/// Smallest number
-const TINY_BITS: u64 = 0x1;
-
-/// Next smallest number
-const TINY_UP_BITS: u64 = 0x2;
-
-/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
-const MAX_DOWN_BITS: u64 = 0x7fef_ffff_ffff_fffe;
-
-/// Zeroed exponent, full significant
-const LARGEST_SUBNORMAL_BITS: u64 = 0x000f_ffff_ffff_ffff;
-
-/// Exponent = 0b1, zeroed significand
-const SMALLEST_NORMAL_BITS: u64 = 0x0010_0000_0000_0000;
-
-/// First pattern over the mantissa
-const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa;
-
-/// Second pattern over the mantissa
-const NAN_MASK2: u64 = 0x0005_5555_5555_5555;
 
 #[allow(unused_macros)]
 macro_rules! assert_f64_biteq {
@@ -34,411 +12,6 @@ macro_rules! assert_f64_biteq {
 }
 
 #[test]
-fn test_num_f64() {
-    crate::test_num(10f64, 2f64);
-}
-
-#[test]
-fn test_min_nan() {
-    assert_eq!(f64::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f64.min(f64::NAN), 2.0);
-}
-
-#[test]
-fn test_max_nan() {
-    assert_eq!(f64::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f64.max(f64::NAN), 2.0);
-}
-
-#[test]
-fn test_nan() {
-    let nan: f64 = f64::NAN;
-    assert!(nan.is_nan());
-    assert!(!nan.is_infinite());
-    assert!(!nan.is_finite());
-    assert!(!nan.is_normal());
-    assert!(nan.is_sign_positive());
-    assert!(!nan.is_sign_negative());
-    assert_eq!(Fp::Nan, nan.classify());
-    // Ensure the quiet bit is set.
-    assert!(nan.to_bits() & (1 << (f64::MANTISSA_DIGITS - 2)) != 0);
-}
-
-#[test]
-fn test_infinity() {
-    let inf: f64 = f64::INFINITY;
-    assert!(inf.is_infinite());
-    assert!(!inf.is_finite());
-    assert!(inf.is_sign_positive());
-    assert!(!inf.is_sign_negative());
-    assert!(!inf.is_nan());
-    assert!(!inf.is_normal());
-    assert_eq!(Fp::Infinite, inf.classify());
-}
-
-#[test]
-fn test_neg_infinity() {
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert!(neg_inf.is_infinite());
-    assert!(!neg_inf.is_finite());
-    assert!(!neg_inf.is_sign_positive());
-    assert!(neg_inf.is_sign_negative());
-    assert!(!neg_inf.is_nan());
-    assert!(!neg_inf.is_normal());
-    assert_eq!(Fp::Infinite, neg_inf.classify());
-}
-
-#[test]
-fn test_zero() {
-    let zero: f64 = 0.0f64;
-    assert_eq!(0.0, zero);
-    assert!(!zero.is_infinite());
-    assert!(zero.is_finite());
-    assert!(zero.is_sign_positive());
-    assert!(!zero.is_sign_negative());
-    assert!(!zero.is_nan());
-    assert!(!zero.is_normal());
-    assert_eq!(Fp::Zero, zero.classify());
-}
-
-#[test]
-fn test_neg_zero() {
-    let neg_zero: f64 = -0.0;
-    assert_eq!(0.0, neg_zero);
-    assert!(!neg_zero.is_infinite());
-    assert!(neg_zero.is_finite());
-    assert!(!neg_zero.is_sign_positive());
-    assert!(neg_zero.is_sign_negative());
-    assert!(!neg_zero.is_nan());
-    assert!(!neg_zero.is_normal());
-    assert_eq!(Fp::Zero, neg_zero.classify());
-}
-
-#[test]
-fn test_one() {
-    let one: f64 = 1.0f64;
-    assert_eq!(1.0, one);
-    assert!(!one.is_infinite());
-    assert!(one.is_finite());
-    assert!(one.is_sign_positive());
-    assert!(!one.is_sign_negative());
-    assert!(!one.is_nan());
-    assert!(one.is_normal());
-    assert_eq!(Fp::Normal, one.classify());
-}
-
-#[test]
-fn test_is_nan() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert!(nan.is_nan());
-    assert!(!0.0f64.is_nan());
-    assert!(!5.3f64.is_nan());
-    assert!(!(-10.732f64).is_nan());
-    assert!(!inf.is_nan());
-    assert!(!neg_inf.is_nan());
-}
-
-#[test]
-fn test_is_infinite() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert!(!nan.is_infinite());
-    assert!(inf.is_infinite());
-    assert!(neg_inf.is_infinite());
-    assert!(!0.0f64.is_infinite());
-    assert!(!42.8f64.is_infinite());
-    assert!(!(-109.2f64).is_infinite());
-}
-
-#[test]
-fn test_is_finite() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert!(!nan.is_finite());
-    assert!(!inf.is_finite());
-    assert!(!neg_inf.is_finite());
-    assert!(0.0f64.is_finite());
-    assert!(42.8f64.is_finite());
-    assert!((-109.2f64).is_finite());
-}
-
-#[test]
-fn test_is_normal() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    let zero: f64 = 0.0f64;
-    let neg_zero: f64 = -0.0;
-    assert!(!nan.is_normal());
-    assert!(!inf.is_normal());
-    assert!(!neg_inf.is_normal());
-    assert!(!zero.is_normal());
-    assert!(!neg_zero.is_normal());
-    assert!(1f64.is_normal());
-    assert!(1e-307f64.is_normal());
-    assert!(!1e-308f64.is_normal());
-}
-
-#[test]
-fn test_classify() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    let zero: f64 = 0.0f64;
-    let neg_zero: f64 = -0.0;
-    assert_eq!(nan.classify(), Fp::Nan);
-    assert_eq!(inf.classify(), Fp::Infinite);
-    assert_eq!(neg_inf.classify(), Fp::Infinite);
-    assert_eq!(zero.classify(), Fp::Zero);
-    assert_eq!(neg_zero.classify(), Fp::Zero);
-    assert_eq!(1e-307f64.classify(), Fp::Normal);
-    assert_eq!(1e-308f64.classify(), Fp::Subnormal);
-}
-
-#[test]
-fn test_floor() {
-    assert_approx_eq!(1.0f64.floor(), 1.0f64);
-    assert_approx_eq!(1.3f64.floor(), 1.0f64);
-    assert_approx_eq!(1.5f64.floor(), 1.0f64);
-    assert_approx_eq!(1.7f64.floor(), 1.0f64);
-    assert_approx_eq!(0.0f64.floor(), 0.0f64);
-    assert_approx_eq!((-0.0f64).floor(), -0.0f64);
-    assert_approx_eq!((-1.0f64).floor(), -1.0f64);
-    assert_approx_eq!((-1.3f64).floor(), -2.0f64);
-    assert_approx_eq!((-1.5f64).floor(), -2.0f64);
-    assert_approx_eq!((-1.7f64).floor(), -2.0f64);
-}
-
-#[test]
-fn test_ceil() {
-    assert_approx_eq!(1.0f64.ceil(), 1.0f64);
-    assert_approx_eq!(1.3f64.ceil(), 2.0f64);
-    assert_approx_eq!(1.5f64.ceil(), 2.0f64);
-    assert_approx_eq!(1.7f64.ceil(), 2.0f64);
-    assert_approx_eq!(0.0f64.ceil(), 0.0f64);
-    assert_approx_eq!((-0.0f64).ceil(), -0.0f64);
-    assert_approx_eq!((-1.0f64).ceil(), -1.0f64);
-    assert_approx_eq!((-1.3f64).ceil(), -1.0f64);
-    assert_approx_eq!((-1.5f64).ceil(), -1.0f64);
-    assert_approx_eq!((-1.7f64).ceil(), -1.0f64);
-}
-
-#[test]
-fn test_round() {
-    assert_approx_eq!(2.5f64.round(), 3.0f64);
-    assert_approx_eq!(1.0f64.round(), 1.0f64);
-    assert_approx_eq!(1.3f64.round(), 1.0f64);
-    assert_approx_eq!(1.5f64.round(), 2.0f64);
-    assert_approx_eq!(1.7f64.round(), 2.0f64);
-    assert_approx_eq!(0.0f64.round(), 0.0f64);
-    assert_approx_eq!((-0.0f64).round(), -0.0f64);
-    assert_approx_eq!((-1.0f64).round(), -1.0f64);
-    assert_approx_eq!((-1.3f64).round(), -1.0f64);
-    assert_approx_eq!((-1.5f64).round(), -2.0f64);
-    assert_approx_eq!((-1.7f64).round(), -2.0f64);
-}
-
-#[test]
-fn test_round_ties_even() {
-    assert_approx_eq!(2.5f64.round_ties_even(), 2.0f64);
-    assert_approx_eq!(1.0f64.round_ties_even(), 1.0f64);
-    assert_approx_eq!(1.3f64.round_ties_even(), 1.0f64);
-    assert_approx_eq!(1.5f64.round_ties_even(), 2.0f64);
-    assert_approx_eq!(1.7f64.round_ties_even(), 2.0f64);
-    assert_approx_eq!(0.0f64.round_ties_even(), 0.0f64);
-    assert_approx_eq!((-0.0f64).round_ties_even(), -0.0f64);
-    assert_approx_eq!((-1.0f64).round_ties_even(), -1.0f64);
-    assert_approx_eq!((-1.3f64).round_ties_even(), -1.0f64);
-    assert_approx_eq!((-1.5f64).round_ties_even(), -2.0f64);
-    assert_approx_eq!((-1.7f64).round_ties_even(), -2.0f64);
-}
-
-#[test]
-fn test_trunc() {
-    assert_approx_eq!(1.0f64.trunc(), 1.0f64);
-    assert_approx_eq!(1.3f64.trunc(), 1.0f64);
-    assert_approx_eq!(1.5f64.trunc(), 1.0f64);
-    assert_approx_eq!(1.7f64.trunc(), 1.0f64);
-    assert_approx_eq!(0.0f64.trunc(), 0.0f64);
-    assert_approx_eq!((-0.0f64).trunc(), -0.0f64);
-    assert_approx_eq!((-1.0f64).trunc(), -1.0f64);
-    assert_approx_eq!((-1.3f64).trunc(), -1.0f64);
-    assert_approx_eq!((-1.5f64).trunc(), -1.0f64);
-    assert_approx_eq!((-1.7f64).trunc(), -1.0f64);
-}
-
-#[test]
-fn test_fract() {
-    assert_approx_eq!(1.0f64.fract(), 0.0f64);
-    assert_approx_eq!(1.3f64.fract(), 0.3f64);
-    assert_approx_eq!(1.5f64.fract(), 0.5f64);
-    assert_approx_eq!(1.7f64.fract(), 0.7f64);
-    assert_approx_eq!(0.0f64.fract(), 0.0f64);
-    assert_approx_eq!((-0.0f64).fract(), -0.0f64);
-    assert_approx_eq!((-1.0f64).fract(), -0.0f64);
-    assert_approx_eq!((-1.3f64).fract(), -0.3f64);
-    assert_approx_eq!((-1.5f64).fract(), -0.5f64);
-    assert_approx_eq!((-1.7f64).fract(), -0.7f64);
-}
-
-#[test]
-fn test_abs() {
-    assert_eq!(f64::INFINITY.abs(), f64::INFINITY);
-    assert_eq!(1f64.abs(), 1f64);
-    assert_eq!(0f64.abs(), 0f64);
-    assert_eq!((-0f64).abs(), 0f64);
-    assert_eq!((-1f64).abs(), 1f64);
-    assert_eq!(f64::NEG_INFINITY.abs(), f64::INFINITY);
-    assert_eq!((1f64 / f64::NEG_INFINITY).abs(), 0f64);
-    assert!(f64::NAN.abs().is_nan());
-}
-
-#[test]
-fn test_signum() {
-    assert_eq!(f64::INFINITY.signum(), 1f64);
-    assert_eq!(1f64.signum(), 1f64);
-    assert_eq!(0f64.signum(), 1f64);
-    assert_eq!((-0f64).signum(), -1f64);
-    assert_eq!((-1f64).signum(), -1f64);
-    assert_eq!(f64::NEG_INFINITY.signum(), -1f64);
-    assert_eq!((1f64 / f64::NEG_INFINITY).signum(), -1f64);
-    assert!(f64::NAN.signum().is_nan());
-}
-
-#[test]
-fn test_is_sign_positive() {
-    assert!(f64::INFINITY.is_sign_positive());
-    assert!(1f64.is_sign_positive());
-    assert!(0f64.is_sign_positive());
-    assert!(!(-0f64).is_sign_positive());
-    assert!(!(-1f64).is_sign_positive());
-    assert!(!f64::NEG_INFINITY.is_sign_positive());
-    assert!(!(1f64 / f64::NEG_INFINITY).is_sign_positive());
-    assert!(f64::NAN.is_sign_positive());
-    assert!(!(-f64::NAN).is_sign_positive());
-}
-
-#[test]
-fn test_is_sign_negative() {
-    assert!(!f64::INFINITY.is_sign_negative());
-    assert!(!1f64.is_sign_negative());
-    assert!(!0f64.is_sign_negative());
-    assert!((-0f64).is_sign_negative());
-    assert!((-1f64).is_sign_negative());
-    assert!(f64::NEG_INFINITY.is_sign_negative());
-    assert!((1f64 / f64::NEG_INFINITY).is_sign_negative());
-    assert!(!f64::NAN.is_sign_negative());
-    assert!((-f64::NAN).is_sign_negative());
-}
-
-#[test]
-fn test_next_up() {
-    let tiny = f64::from_bits(TINY_BITS);
-    let tiny_up = f64::from_bits(TINY_UP_BITS);
-    let max_down = f64::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f64_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN);
-    assert_f64_biteq!(f64::MIN.next_up(), -max_down);
-    assert_f64_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0);
-    assert_f64_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f64_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f64_biteq!((-tiny).next_up(), -0.0f64);
-    assert_f64_biteq!((-0.0f64).next_up(), tiny);
-    assert_f64_biteq!(0.0f64.next_up(), tiny);
-    assert_f64_biteq!(tiny.next_up(), tiny_up);
-    assert_f64_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f64_biteq!(1.0f64.next_up(), 1.0 + f64::EPSILON);
-    assert_f64_biteq!(f64::MAX.next_up(), f64::INFINITY);
-    assert_f64_biteq!(f64::INFINITY.next_up(), f64::INFINITY);
-
-    let nan0 = f64::NAN;
-    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
-    assert_f64_biteq!(nan0.next_up(), nan0);
-    assert_f64_biteq!(nan1.next_up(), nan1);
-    assert_f64_biteq!(nan2.next_up(), nan2);
-}
-
-#[test]
-fn test_next_down() {
-    let tiny = f64::from_bits(TINY_BITS);
-    let tiny_up = f64::from_bits(TINY_UP_BITS);
-    let max_down = f64::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f64_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
-    assert_f64_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY);
-    assert_f64_biteq!((-max_down).next_down(), f64::MIN);
-    assert_f64_biteq!((-1.0f64).next_down(), -1.0 - f64::EPSILON);
-    assert_f64_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f64_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f64_biteq!((-0.0f64).next_down(), -tiny);
-    assert_f64_biteq!((0.0f64).next_down(), -tiny);
-    assert_f64_biteq!(tiny.next_down(), 0.0f64);
-    assert_f64_biteq!(tiny_up.next_down(), tiny);
-    assert_f64_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f64_biteq!((1.0 + f64::EPSILON).next_down(), 1.0f64);
-    assert_f64_biteq!(f64::MAX.next_down(), max_down);
-    assert_f64_biteq!(f64::INFINITY.next_down(), f64::MAX);
-
-    let nan0 = f64::NAN;
-    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
-    assert_f64_biteq!(nan0.next_down(), nan0);
-    assert_f64_biteq!(nan1.next_down(), nan1);
-    assert_f64_biteq!(nan2.next_down(), nan2);
-}
-
-#[test]
-fn test_mul_add() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05);
-    assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65);
-    assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2);
-    assert_approx_eq!(3.4f64.mul_add(-0.0, 5.6), 5.6);
-    assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f64.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf);
-}
-
-#[test]
-fn test_recip() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(1.0f64.recip(), 1.0);
-    assert_eq!(2.0f64.recip(), 0.5);
-    assert_eq!((-0.4f64).recip(), -2.5);
-    assert_eq!(0.0f64.recip(), inf);
-    assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
-}
-
-#[test]
-fn test_powi() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(1.0f64.powi(1), 1.0);
-    assert_approx_eq!((-3.1f64).powi(2), 9.61);
-    assert_approx_eq!(5.9f64.powi(-2), 0.028727);
-    assert_eq!(8.3f64.powi(0), 1.0);
-    assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
-}
-
-#[test]
 fn test_powf() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
@@ -455,17 +28,6 @@ fn test_powf() {
 }
 
 #[test]
-fn test_sqrt_domain() {
-    assert!(f64::NAN.sqrt().is_nan());
-    assert!(f64::NEG_INFINITY.sqrt().is_nan());
-    assert!((-1.0f64).sqrt().is_nan());
-    assert_eq!((-0.0f64).sqrt(), -0.0);
-    assert_eq!(0.0f64.sqrt(), 0.0);
-    assert_eq!(1.0f64.sqrt(), 1.0);
-    assert_eq!(f64::INFINITY.sqrt(), f64::INFINITY);
-}
-
-#[test]
 fn test_exp() {
     assert_eq!(1.0, 0.0f64.exp());
     assert_approx_eq!(2.718282, 1.0f64.exp());
@@ -559,35 +121,6 @@ fn test_log10() {
 }
 
 #[test]
-fn test_to_degrees() {
-    let pi: f64 = consts::PI;
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(0.0f64.to_degrees(), 0.0);
-    assert_approx_eq!((-5.8f64).to_degrees(), -332.315521);
-    assert_eq!(pi.to_degrees(), 180.0);
-    assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-}
-
-#[test]
-fn test_to_radians() {
-    let pi: f64 = consts::PI;
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(0.0f64.to_radians(), 0.0);
-    assert_approx_eq!(154.6f64.to_radians(), 2.698279);
-    assert_approx_eq!((-332.31f64).to_radians(), -5.799903);
-    assert_eq!(180.0f64.to_radians(), pi);
-    assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
-}
-
-#[test]
 fn test_asinh() {
     assert_eq!(0.0f64.asinh(), 0.0f64);
     assert_eq!((-0.0f64).asinh(), -0.0f64);
@@ -714,204 +247,3 @@ fn test_real_consts() {
     assert_approx_eq!(ln_2, 2f64.ln());
     assert_approx_eq!(ln_10, 10f64.ln());
 }
-
-#[test]
-fn test_float_bits_conv() {
-    assert_eq!((1f64).to_bits(), 0x3ff0000000000000);
-    assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
-    assert_eq!((1337f64).to_bits(), 0x4094e40000000000);
-    assert_eq!((-14.25f64).to_bits(), 0xc02c800000000000);
-    assert_approx_eq!(f64::from_bits(0x3ff0000000000000), 1.0);
-    assert_approx_eq!(f64::from_bits(0x4029000000000000), 12.5);
-    assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
-    assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
-
-    // Check that NaNs roundtrip their bits regardless of signaling-ness
-    let masked_nan1 = f64::NAN.to_bits() ^ NAN_MASK1;
-    let masked_nan2 = f64::NAN.to_bits() ^ NAN_MASK2;
-    assert!(f64::from_bits(masked_nan1).is_nan());
-    assert!(f64::from_bits(masked_nan2).is_nan());
-
-    assert_eq!(f64::from_bits(masked_nan1).to_bits(), masked_nan1);
-    assert_eq!(f64::from_bits(masked_nan2).to_bits(), masked_nan2);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_greater_than_max() {
-    let _ = 1.0f64.clamp(3.0, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_is_nan() {
-    let _ = 1.0f64.clamp(f64::NAN, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_max_is_nan() {
-    let _ = 1.0f64.clamp(3.0, f64::NAN);
-}
-
-#[test]
-fn test_total_cmp() {
-    use core::cmp::Ordering;
-
-    fn quiet_bit_mask() -> u64 {
-        1 << (f64::MANTISSA_DIGITS - 2)
-    }
-
-    fn min_subnorm() -> f64 {
-        f64::MIN_POSITIVE / f64::powf(2.0, f64::MANTISSA_DIGITS as f64 - 1.0)
-    }
-
-    fn max_subnorm() -> f64 {
-        f64::MIN_POSITIVE - min_subnorm()
-    }
-
-    fn q_nan() -> f64 {
-        f64::from_bits(f64::NAN.to_bits() | quiet_bit_mask())
-    }
-
-    fn s_nan() -> f64 {
-        f64::from_bits((f64::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    }
-
-    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Equal, (-f64::INFINITY).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Equal, (-f64::MAX).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Equal, (-2.5_f64).total_cmp(&-2.5));
-    assert_eq!(Ordering::Equal, (-1.0_f64).total_cmp(&-1.0));
-    assert_eq!(Ordering::Equal, (-1.5_f64).total_cmp(&-1.5));
-    assert_eq!(Ordering::Equal, (-0.5_f64).total_cmp(&-0.5));
-    assert_eq!(Ordering::Equal, (-f64::MIN_POSITIVE).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Equal, (-0.0_f64).total_cmp(&-0.0));
-    assert_eq!(Ordering::Equal, 0.0_f64.total_cmp(&0.0));
-    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Equal, f64::MIN_POSITIVE.total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, 0.5_f64.total_cmp(&0.5));
-    assert_eq!(Ordering::Equal, 1.0_f64.total_cmp(&1.0));
-    assert_eq!(Ordering::Equal, 1.5_f64.total_cmp(&1.5));
-    assert_eq!(Ordering::Equal, 2.5_f64.total_cmp(&2.5));
-    assert_eq!(Ordering::Equal, f64::MAX.total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Equal, f64::INFINITY.total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
-    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Less, (-f64::INFINITY).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Less, (-f64::MAX).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-2.5_f64).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-1.5_f64).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-1.0_f64).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-0.5_f64).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-f64::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-0.0_f64).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, 0.0_f64.total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, f64::MIN_POSITIVE.total_cmp(&0.5));
-    assert_eq!(Ordering::Less, 0.5_f64.total_cmp(&1.0));
-    assert_eq!(Ordering::Less, 1.0_f64.total_cmp(&1.5));
-    assert_eq!(Ordering::Less, 1.5_f64.total_cmp(&2.5));
-    assert_eq!(Ordering::Less, 2.5_f64.total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Less, f64::MAX.total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Less, f64::INFINITY.total_cmp(&s_nan()));
-    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Greater, (-f64::INFINITY).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Greater, (-f64::MAX).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Greater, (-2.5_f64).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Greater, (-1.5_f64).total_cmp(&-2.5));
-    assert_eq!(Ordering::Greater, (-1.0_f64).total_cmp(&-1.5));
-    assert_eq!(Ordering::Greater, (-0.5_f64).total_cmp(&-1.0));
-    assert_eq!(Ordering::Greater, (-f64::MIN_POSITIVE).total_cmp(&-0.5));
-    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Greater, (-0.0_f64).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Greater, 0.0_f64.total_cmp(&-0.0));
-    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Greater, f64::MIN_POSITIVE.total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Greater, 0.5_f64.total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, 1.0_f64.total_cmp(&0.5));
-    assert_eq!(Ordering::Greater, 1.5_f64.total_cmp(&1.0));
-    assert_eq!(Ordering::Greater, 2.5_f64.total_cmp(&1.5));
-    assert_eq!(Ordering::Greater, f64::MAX.total_cmp(&2.5));
-    assert_eq!(Ordering::Greater, f64::INFINITY.total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
-}
-
-#[test]
-fn test_algebraic() {
-    let a: f64 = 123.0;
-    let b: f64 = 456.0;
-
-    // Check that individual operations match their primitive counterparts.
-    //
-    // This is a check of current implementations and does NOT imply any form of
-    // guarantee about future behavior. The compiler reserves the right to make
-    // these operations inexact matches in the future.
-    let eps = if cfg!(miri) { 1e-6 } else { 0.0 };
-
-    assert_approx_eq!(a.algebraic_add(b), a + b, eps);
-    assert_approx_eq!(a.algebraic_sub(b), a - b, eps);
-    assert_approx_eq!(a.algebraic_mul(b), a * b, eps);
-    assert_approx_eq!(a.algebraic_div(b), a / b, eps);
-    assert_approx_eq!(a.algebraic_rem(b), a % b, eps);
-}
diff --git a/library/std/tests/floats/lib.rs b/library/std/tests/floats/lib.rs
index 453a2d533ab..8bb8eb4bfc1 100644
--- a/library/std/tests/floats/lib.rs
+++ b/library/std/tests/floats/lib.rs
@@ -1,5 +1,4 @@
-#![feature(f16, f128, float_algebraic, float_gamma, float_minimum_maximum)]
-#![feature(cfg_target_has_reliable_f16_f128)]
+#![feature(f16, f128, float_gamma, float_minimum_maximum, cfg_target_has_reliable_f16_f128)]
 #![expect(internal_features)] // for reliable_f16_f128
 
 use std::fmt;
diff --git a/library/stdarch b/library/stdarch
-Subproject f1c1839c0deb985a9f98cbd6b38a6d43f2df615
+Subproject 1dfaa4db2479753a46a3e90f2c3c89d89d0b21f