about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs22
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs5
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_macros/src/query.rs14
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs3
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs32
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs10
-rw-r--r--compiler/rustc_ty_utils/src/layout/invariant.rs22
-rw-r--r--library/Cargo.lock1
-rw-r--r--library/core/Cargo.toml6
-rw-r--r--library/core/src/char/methods.rs21
-rw-r--r--library/core/src/lib.rs1
-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/libm.rs11
-rw-r--r--library/core/src/num/mod.rs21
-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/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/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/rt.rs9
-rw-r--r--library/std/src/sys/cmath.rs4
-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/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/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
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh2
-rw-r--r--src/doc/rustc/book.toml2
-rw-r--r--src/doc/rustc/theme/pagetoc.css84
-rw-r--r--src/doc/rustc/theme/pagetoc.js104
-rw-r--r--src/librustdoc/clean/cfg.rs64
-rw-r--r--src/librustdoc/clean/mod.rs22
-rw-r--r--src/librustdoc/clean/types.rs20
-rw-r--r--src/librustdoc/formats/item_type.rs33
-rw-r--r--src/librustdoc/html/format.rs81
-rw-r--r--src/librustdoc/lib.rs1
m---------src/llvm-project0
-rw-r--r--src/tools/miri/Cargo.toml2
-rw-r--r--src/tools/miri/cargo-miri/Cargo.toml2
-rw-r--r--src/tools/miri/cargo-miri/src/main.rs34
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs11
-rw-r--r--src/tools/miri/cargo-miri/src/setup.rs8
-rw-r--r--src/tools/miri/miri-script/Cargo.toml2
-rw-r--r--src/tools/miri/miri-script/src/commands.rs14
-rw-r--r--src/tools/miri/miri-script/src/util.rs2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs2
-rw-r--r--src/tools/miri/src/diagnostics.rs3
-rw-r--r--src/tools/miri/src/helpers.rs9
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/shims/panic.rs1
-rwxr-xr-xsrc/tools/miri/test-cargo-miri/run-test.py17
-rw-r--r--src/tools/miri/test-cargo-miri/test.filter.cross-target.stdout.ref12
-rw-r--r--src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref10
-rw-r--r--src/tools/miri/test-cargo-miri/test.no-doc.stdout.ref (renamed from src/tools/miri/test-cargo-miri/test.cross-target.stdout.ref)0
-rw-r--r--src/tools/miri/test-cargo-miri/test.subcrate.cross-target.stdout.ref11
-rw-r--r--src/tools/miri/tests/fail/alloc/alloc_error_handler.rs2
-rw-r--r--src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_arg_abi.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_callback_abi.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.rs6
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/abort_unwind.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/abort_unwind.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort1.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort1.stderr8
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort2.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort2.stderr8
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort3.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort3.stderr8
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort4.rs2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort4.stderr8
-rw-r--r--src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs2
-rw-r--r--src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr2
-rw-r--r--src/tools/miri/tests/fail/tail_calls/cc-mismatch.rs2
-rw-r--r--src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr4
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.rs2
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.stderr2
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.rs2
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.stderr2
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr22
-rw-r--r--src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs1
-rw-r--r--src/tools/miri/tests/pass/coroutine.rs8
-rw-r--r--src/tools/miri/tests/ui.rs13
-rw-r--r--tests/run-make/core-no-oom-handling/rmake.rs2
-rw-r--r--tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs7
-rw-r--r--tests/ui/consts/miri_unleashed/abi-mismatch.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/abi-mismatch.stderr2
-rw-r--r--tests/ui/coroutine/delayed-obligations-emit.next.stderr15
-rw-r--r--tests/ui/coroutine/delayed-obligations-emit.rs33
-rw-r--r--tests/ui/imports/issue-99695-b.fixed2
-rw-r--r--tests/ui/imports/issue-99695-b.stderr2
-rw-r--r--tests/ui/imports/issue-99695.edition_2015.fixed (renamed from tests/ui/imports/issue-99695.fixed)6
-rw-r--r--tests/ui/imports/issue-99695.edition_2015.stderr (renamed from tests/ui/imports/issue-99695.stderr)4
-rw-r--r--tests/ui/imports/issue-99695.edition_2018.fixed21
-rw-r--r--tests/ui/imports/issue-99695.edition_2018.stderr16
-rw-r--r--tests/ui/imports/issue-99695.rs4
-rw-r--r--tests/ui/traits/object/ambiguity-vtable-segfault.rs37
-rw-r--r--triagebot.toml3
143 files changed, 5682 insertions, 4321 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 159c17b0af7..c5792da2678 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -768,7 +768,7 @@ fn link_natively(
             && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-fuse-ld=lld")
         {
             info!("linker output: {:?}", out);
-            warn!("The linker driver does not support `-fuse-ld=lld`. Retrying without it.");
+            info!("The linker driver does not support `-fuse-ld=lld`. Retrying without it.");
             for arg in cmd.take_args() {
                 if arg.to_string_lossy() != "-fuse-ld=lld" {
                     cmd.arg(arg);
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 216800717fd..405208e94f4 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -353,8 +353,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         if caller_fn_abi.conv != callee_fn_abi.conv {
             throw_ub_custom!(
                 fluent::const_eval_incompatible_calling_conventions,
-                callee_conv = format!("{:?}", callee_fn_abi.conv),
-                caller_conv = format!("{:?}", caller_fn_abi.conv),
+                callee_conv = format!("{}", callee_fn_abi.conv),
+                caller_conv = format!("{}", caller_fn_abi.conv),
             )
         }
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index f92b2aea160..da94331aa26 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1754,17 +1754,19 @@ pub(super) fn check_coroutine_obligations(
     debug!(?typeck_results.coroutine_stalled_predicates);
 
     let mode = if tcx.next_trait_solver_globally() {
-        TypingMode::post_borrowck_analysis(tcx, def_id)
+        // This query is conceptually between HIR typeck and
+        // MIR borrowck. We use the opaque types defined by HIR
+        // and ignore region constraints.
+        TypingMode::borrowck(tcx, def_id)
     } else {
         TypingMode::analysis_in_body(tcx, def_id)
     };
 
-    let infcx = tcx
-        .infer_ctxt()
-        // typeck writeback gives us predicates with their regions erased.
-        // As borrowck already has checked lifetimes, we do not need to do it again.
-        .ignoring_regions()
-        .build(mode);
+    // Typeck writeback gives us predicates with their regions erased.
+    // We only need to check the goals while ignoring lifetimes to give good
+    // error message and to avoid breaking the assumption of `mir_borrowck`
+    // that all obligations already hold modulo regions.
+    let infcx = tcx.infer_ctxt().ignoring_regions().build(mode);
 
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
     for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
@@ -1785,6 +1787,10 @@ pub(super) fn check_coroutine_obligations(
             let key = infcx.resolve_vars_if_possible(key);
             sanity_check_found_hidden_type(tcx, key, hidden_type)?;
         }
+    } else {
+        // We're not checking region constraints here, so we can simply drop the
+        // added opaque type uses in `TypingMode::Borrowck`.
+        let _ = infcx.take_opaque_types();
     }
 
     Ok(())
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 52656fc2d90..b92d1d7104f 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -214,11 +214,9 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
     let span = tcx.def_span(impl_did);
     let trait_name = "DispatchFromDyn";
 
-    let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
-
     let source = trait_ref.self_ty();
     let target = {
-        assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
+        assert!(tcx.is_lang_item(trait_ref.def_id, LangItem::DispatchFromDyn));
 
         trait_ref.args.type_at(1)
     };
@@ -339,7 +337,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
                     tcx,
                     cause.clone(),
                     param_env,
-                    ty::TraitRef::new(tcx, dispatch_from_dyn_trait, [ty_a, ty_b]),
+                    ty::TraitRef::new(tcx, trait_ref.def_id, [ty_a, ty_b]),
                 ));
                 let errors = ocx.select_all_or_error();
                 if !errors.is_empty() {
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 4937eb73a8b..010c6c376fe 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -194,17 +194,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
         let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(());
     });
 
-    if tcx.features().rustc_attrs() {
-        tcx.sess.time("dumping_rustc_attr_data", || {
-            outlives::dump::inferred_outlives(tcx);
-            variance::dump::variances(tcx);
-            collect::dump::opaque_hidden_types(tcx);
-            collect::dump::predicates_and_item_bounds(tcx);
-            collect::dump::def_parents(tcx);
-            collect::dump::vtables(tcx);
-        });
-    }
-
     // Make sure we evaluate all static and (non-associated) const items, even if unused.
     // If any of these fail to evaluate, we do not want this crate to pass compilation.
     tcx.par_hir_body_owners(|item_def_id| {
@@ -228,6 +217,17 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
         }
     });
 
+    if tcx.features().rustc_attrs() {
+        tcx.sess.time("dumping_rustc_attr_data", || {
+            outlives::dump::inferred_outlives(tcx);
+            variance::dump::variances(tcx);
+            collect::dump::opaque_hidden_types(tcx);
+            collect::dump::predicates_and_item_bounds(tcx);
+            collect::dump::def_parents(tcx);
+            collect::dump::vtables(tcx);
+        });
+    }
+
     tcx.ensure_ok().check_unused_traits(());
 }
 
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 8fd59999fce..b1cb3ef4d79 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -1080,15 +1080,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Check that this is a projection from the `Future` trait.
         let trait_def_id = predicate.projection_term.trait_def_id(self.tcx);
-        let future_trait = self.tcx.require_lang_item(LangItem::Future, Some(cause_span));
-        if trait_def_id != future_trait {
+        if !self.tcx.is_lang_item(trait_def_id, LangItem::Future) {
             debug!("deduce_future_output_from_projection: not a future");
             return None;
         }
 
         // The `Future` trait has only one associated item, `Output`,
         // so check that this is what we see.
-        let output_assoc_item = self.tcx.associated_item_def_ids(future_trait)[0];
+        let output_assoc_item = self.tcx.associated_item_def_ids(trait_def_id)[0];
         if output_assoc_item != predicate.projection_term.def_id {
             span_bug!(
                 cause_span,
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index b554cc715fe..e28639576f0 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1001,10 +1001,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
                 tcx.ensure_ok().check_unsafety(def_id);
                 tcx.ensure_ok().mir_borrowck(def_id)
             }
-        });
-    });
-    sess.time("MIR_effect_checking", || {
-        tcx.par_hir_body_owners(|def_id| {
             tcx.ensure_ok().has_ffi_unwind_calls(def_id);
 
             // If we need to codegen, ensure that we emit all errors from
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 33fb13e23bf..ee377277017 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -267,6 +267,18 @@ fn add_query_desc_cached_impl(
 ) {
     let Query { name, key, modifiers, .. } = &query;
 
+    // This dead code exists to instruct rust-analyzer about the link between the `rustc_queries`
+    // query names and the corresponding produced provider. The issue is that by nature of this
+    // macro producing a higher order macro that has all its token in the macro declaration we lose
+    // any meaningful spans, resulting in rust-analyzer being unable to make the connection between
+    // the query name and the corresponding providers field. The trick to fix this is to have
+    // `rustc_queries` emit a field access with the given name's span which allows it to succesfully
+    // show references / go to definition to the correspondig provider assignment which is usually
+    // the more interesting place.
+    let ra_hint = quote! {
+        let crate::query::Providers { #name: _, .. };
+    };
+
     // Find out if we should cache the query on disk
     let cache = if let Some((args, expr)) = modifiers.cache.as_ref() {
         let tcx = args.as_ref().map(|t| quote! { #t }).unwrap_or_else(|| quote! { _ });
@@ -277,6 +289,7 @@ fn add_query_desc_cached_impl(
             #[allow(unused_variables, unused_braces, rustc::pass_by_value)]
             #[inline]
             pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool {
+                #ra_hint
                 #expr
             }
         }
@@ -286,6 +299,7 @@ fn add_query_desc_cached_impl(
             #[allow(rustc::pass_by_value)]
             #[inline]
             pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::queries::#name::Key<'tcx>) -> bool {
+                #ra_hint
                 false
             }
         }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index c31ce1bc630..ab1f3d6099f 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1260,8 +1260,7 @@ impl<'tcx> Ty<'tcx> {
                     return true;
                 };
                 alloc.expect_ty().ty_adt_def().is_some_and(|alloc_adt| {
-                    let global_alloc = tcx.require_lang_item(LangItem::GlobalAlloc, None);
-                    alloc_adt.did() == global_alloc
+                    tcx.is_lang_item(alloc_adt.did(), LangItem::GlobalAlloc)
                 })
             }
             _ => false,
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index f63d8b2d79f..2b85d7b26ce 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -6,7 +6,6 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
 #![allow(unused_crate_dependencies)]
-#![cfg_attr(all(feature = "rustc", bootstrap), feature(let_chains))]
 // tidy-alphabetical-end
 
 pub mod constructor;
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 0b16983c2c7..d09750fa281 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2493,7 +2493,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else {
             return None;
         };
-        let module_name = crate_module.kind.name().unwrap_or(kw::Empty);
+        let module_name = crate_module.kind.name().unwrap_or(kw::Crate);
         let import_snippet = match import.kind {
             ImportKind::Single { source, target, .. } if source != target => {
                 format!("{source} as {target}")
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index ae366e29e32..907614520a2 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -1,3 +1,4 @@
+use std::fmt::Display;
 use std::str::FromStr;
 use std::{fmt, iter};
 
@@ -895,6 +896,37 @@ impl FromStr for Conv {
     }
 }
 
+fn conv_to_externabi(conv: &Conv) -> ExternAbi {
+    match conv {
+        Conv::C => ExternAbi::C { unwind: false },
+        Conv::Rust => ExternAbi::Rust,
+        Conv::PreserveMost => ExternAbi::RustCold,
+        Conv::ArmAapcs => ExternAbi::Aapcs { unwind: false },
+        Conv::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall,
+        Conv::CCmseNonSecureEntry => ExternAbi::CCmseNonSecureEntry,
+        Conv::Msp430Intr => ExternAbi::Msp430Interrupt,
+        Conv::GpuKernel => ExternAbi::GpuKernel,
+        Conv::X86Fastcall => ExternAbi::Fastcall { unwind: false },
+        Conv::X86Intr => ExternAbi::X86Interrupt,
+        Conv::X86Stdcall => ExternAbi::Stdcall { unwind: false },
+        Conv::X86ThisCall => ExternAbi::Thiscall { unwind: false },
+        Conv::X86VectorCall => ExternAbi::Vectorcall { unwind: false },
+        Conv::X86_64SysV => ExternAbi::SysV64 { unwind: false },
+        Conv::X86_64Win64 => ExternAbi::Win64 { unwind: false },
+        Conv::AvrInterrupt => ExternAbi::AvrInterrupt,
+        Conv::AvrNonBlockingInterrupt => ExternAbi::AvrNonBlockingInterrupt,
+        Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine } => ExternAbi::RiscvInterruptM,
+        Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor } => ExternAbi::RiscvInterruptS,
+        Conv::Cold | Conv::PreserveAll => unreachable!(),
+    }
+}
+
+impl Display for Conv {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", conv_to_externabi(self))
+    }
+}
+
 // Some types are used a lot. Make sure they don't unintentionally get bigger.
 #[cfg(target_pointer_width = "64")]
 mod size_asserts {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
index c5704c57448..f1b6fa123de 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FramePointer, LinkerFlavor, Lld, Target, TargetMetadata, base};
+use crate::spec::{FramePointer, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -11,11 +11,6 @@ pub(crate) fn target() -> Target {
     // and other services. It must point to the previous {x29, x30} pair on the stack."
     base.frame_pointer = FramePointer::NonLeaf;
 
-    // MSVC emits a warning about code that may trip "Cortex-A53 MPCore processor bug #843419" (see
-    // https://developer.arm.com/documentation/epm048406/latest) which is sometimes emitted by LLVM.
-    // Since Arm64 Windows 10+ isn't supported on that processor, it's safe to disable the warning.
-    base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/arm64hazardfree"]);
-
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
         metadata: TargetMetadata {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 4738a538b29..31b075db04b 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -701,9 +701,15 @@ pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause
         let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
         ocx.register_obligation(obligation);
     }
-    let errors = ocx.select_all_or_error();
 
-    if !errors.is_empty() {
+    // Use `select_where_possible` to only return impossible for true errors,
+    // and not ambiguities or overflows. Since the new trait solver forces
+    // some currently undetected overlap between `dyn Trait: Trait` built-in
+    // vs user-written impls to AMBIGUOUS, this may return ambiguity even
+    // with no infer vars. There may also be ways to encounter ambiguity due
+    // to post-mono overflow.
+    let true_errors = ocx.select_where_possible();
+    if !true_errors.is_empty() {
         return true;
     }
 
diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs
index 7423a156a21..c929de11624 100644
--- a/compiler/rustc_ty_utils/src/layout/invariant.rs
+++ b/compiler/rustc_ty_utils/src/layout/invariant.rs
@@ -8,15 +8,6 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout};
 pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
     let tcx = cx.tcx();
 
-    // Type-level uninhabitedness should always imply ABI uninhabitedness.
-    if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) {
-        assert!(
-            layout.is_uninhabited(),
-            "{:?} is type-level uninhabited but not ABI-uninhabited?",
-            layout.ty
-        );
-    }
-
     if layout.size.bytes() % layout.align.abi.bytes() != 0 {
         bug!("size is not a multiple of align, in the following layout:\n{layout:#?}");
     }
@@ -29,6 +20,19 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
         return;
     }
 
+    // Type-level uninhabitedness should always imply ABI uninhabitedness. This can be expensive on
+    // big non-exhaustive types, and is [hard to
+    // fix](https://github.com/rust-lang/rust/issues/141006#issuecomment-2883415000) in general.
+    // Only doing this sanity check when debug assertions are turned on avoids the issue for the
+    // very specific case of #140944.
+    if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) {
+        assert!(
+            layout.is_uninhabited(),
+            "{:?} is type-level uninhabited but not ABI-uninhabited?",
+            layout.ty
+        );
+    }
+
     /// Yields non-ZST fields of the type
     fn non_zst_fields<'tcx, 'a>(
         cx: &'a LayoutCx<'tcx>,
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/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/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/lib.rs b/library/core/src/lib.rs
index 64a7ec8906b..4e8d1dc1152 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -111,7 +111,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)]
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/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/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/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/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/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/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/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/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/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
index 9ed5b519b6e..9222710b843 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
@@ -47,7 +47,7 @@ fi
 # we only ensure that all assertions still pass.
 MIRIFLAGS="-Zmiri-force-intrinsic-fallback --cfg force_intrinsic_fallback -O -Zmir-opt-level=4 -Cdebug-assertions=yes" \
   MIRI_SKIP_UI_CHECKS=1 \
-  python3 "$X_PY" test --stage 2 src/tools/miri -- tests/{pass,panic}
+  python3 "$X_PY" test --stage 2 src/tools/miri -- tests/pass tests/panic
 # We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc.
 # Also cover some other targets via cross-testing, in particular all tier 1 targets.
 case $HOST_TARGET in
diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
index 167aece0ed6..01f127ad390 100644
--- a/src/doc/rustc/book.toml
+++ b/src/doc/rustc/book.toml
@@ -6,6 +6,8 @@ title = "The rustc book"
 [output.html]
 git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc"
 edit-url-template = "https://github.com/rust-lang/rust/edit/master/src/doc/rustc/{path}"
+additional-css = ["theme/pagetoc.css"]
+additional-js = ["theme/pagetoc.js"]
 
 [output.html.search]
 use-boolean-and = true
diff --git a/src/doc/rustc/theme/pagetoc.css b/src/doc/rustc/theme/pagetoc.css
new file mode 100644
index 00000000000..58ca1f8b26f
--- /dev/null
+++ b/src/doc/rustc/theme/pagetoc.css
@@ -0,0 +1,84 @@
+/* Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) */
+
+:root {
+    --toc-width: 270px;
+    --center-content-toc-shift: calc(-1 * var(--toc-width) / 2);
+}
+
+.nav-chapters {
+    /* adjust width of buttons that bring to the previous or the next page */
+    min-width: 50px;
+}
+
+@media only screen {
+    @media (max-width: 1179px) {
+        .sidebar-hidden #sidetoc {
+            display: none;
+        }
+    }
+
+    @media (max-width: 1439px) {
+        .sidebar-visible #sidetoc {
+            display: none;
+        }
+    }
+
+    @media (1180px <= width <= 1439px) {
+        .sidebar-hidden main {
+            position: relative;
+            left: var(--center-content-toc-shift);
+        }
+    }
+
+    @media (1440px <= width <= 1700px) {
+        .sidebar-visible main {
+            position: relative;
+            left: var(--center-content-toc-shift);
+        }
+    }
+
+    #sidetoc {
+        margin-left: calc(100% + 20px);
+    }
+    #pagetoc {
+        position: fixed;
+        /* adjust TOC width */
+        width: var(--toc-width);
+        height: calc(100vh - var(--menu-bar-height) - 0.67em * 4);
+        overflow: auto;
+    }
+    #pagetoc a {
+        border-left: 1px solid var(--sidebar-bg);
+        color: var(--sidebar-fg) !important;
+        display: block;
+        padding-bottom: 5px;
+        padding-top: 5px;
+        padding-left: 10px;
+        text-align: left;
+        text-decoration: none;
+    }
+    #pagetoc a:hover,
+    #pagetoc a.active {
+        background: var(--sidebar-bg);
+        color: var(--sidebar-active) !important;
+    }
+    #pagetoc .active {
+        background: var(--sidebar-bg);
+        color: var(--sidebar-active);
+    }
+    #pagetoc .pagetoc-H2 {
+        padding-left: 20px;
+    }
+    #pagetoc .pagetoc-H3 {
+        padding-left: 40px;
+    }
+    #pagetoc .pagetoc-H4 {
+        padding-left: 60px;
+    }
+}
+
+@media print {
+    #sidetoc {
+        display: none;
+    }
+}
diff --git a/src/doc/rustc/theme/pagetoc.js b/src/doc/rustc/theme/pagetoc.js
new file mode 100644
index 00000000000..927a5b10749
--- /dev/null
+++ b/src/doc/rustc/theme/pagetoc.js
@@ -0,0 +1,104 @@
+// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL)
+
+let activeHref = location.href;
+function updatePageToc(elem = undefined) {
+    let selectedPageTocElem = elem;
+    const pagetoc = document.getElementById("pagetoc");
+
+    function getRect(element) {
+        return element.getBoundingClientRect();
+    }
+
+    function overflowTop(container, element) {
+        return getRect(container).top - getRect(element).top;
+    }
+
+    function overflowBottom(container, element) {
+        return getRect(container).bottom - getRect(element).bottom;
+    }
+
+    // We've not selected a heading to highlight, and the URL needs updating
+    // so we need to find a heading based on the URL
+    if (selectedPageTocElem === undefined && location.href !== activeHref) {
+        activeHref = location.href;
+        for (const pageTocElement of pagetoc.children) {
+            if (pageTocElement.href === activeHref) {
+                selectedPageTocElem = pageTocElement;
+            }
+        }
+    }
+
+    // We still don't have a selected heading, let's try and find the most
+    // suitable heading based on the scroll position
+    if (selectedPageTocElem === undefined) {
+        const margin = window.innerHeight / 3;
+
+        const headers = document.getElementsByClassName("header");
+        for (let i = 0; i < headers.length; i++) {
+            const header = headers[i];
+            if (selectedPageTocElem === undefined && getRect(header).top >= 0) {
+                if (getRect(header).top < margin) {
+                    selectedPageTocElem = header;
+                } else {
+                    selectedPageTocElem = headers[Math.max(0, i - 1)];
+                }
+            }
+            // a very long last section's heading is over the screen
+            if (selectedPageTocElem === undefined && i === headers.length - 1) {
+                selectedPageTocElem = header;
+            }
+        }
+    }
+
+    // Remove the active flag from all pagetoc elements
+    for (const pageTocElement of pagetoc.children) {
+        pageTocElement.classList.remove("active");
+    }
+
+    // If we have a selected heading, set it to active and scroll to it
+    if (selectedPageTocElem !== undefined) {
+        for (const pageTocElement of pagetoc.children) {
+            if (selectedPageTocElem.href.localeCompare(pageTocElement.href) === 0) {
+                pageTocElement.classList.add("active");
+                if (overflowTop(pagetoc, pageTocElement) > 0) {
+                    pagetoc.scrollTop = pageTocElement.offsetTop;
+                }
+                if (overflowBottom(pagetoc, pageTocElement) < 0) {
+                    pagetoc.scrollTop -= overflowBottom(pagetoc, pageTocElement);
+                }
+            }
+        }
+    }
+}
+
+if (document.getElementById("sidetoc") === null &&
+    document.getElementsByClassName("header").length > 0) {
+    // The sidetoc element doesn't exist yet, let's create it
+
+    // Create the empty sidetoc and pagetoc elements
+    const sidetoc = document.createElement("div");
+    const pagetoc = document.createElement("div");
+    sidetoc.id = "sidetoc";
+    pagetoc.id = "pagetoc";
+    sidetoc.appendChild(pagetoc);
+
+    // And append them to the current DOM
+    const main = document.querySelector('main');
+    main.insertBefore(sidetoc, main.firstChild);
+
+    // Populate sidebar on load
+    window.addEventListener("load", () => {
+        for (const header of document.getElementsByClassName("header")) {
+            const link = document.createElement("a");
+            link.innerHTML = header.innerHTML;
+            link.href = header.hash;
+            link.classList.add("pagetoc-" + header.parentElement.tagName);
+            document.getElementById("pagetoc").appendChild(link);
+            link.onclick = () => updatePageToc(link);
+        }
+        updatePageToc();
+    });
+
+    // Update page table of contents selected heading on scroll
+    window.addEventListener("scroll", () => updatePageToc());
+}
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 1541e7201ce..439777843fb 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -144,7 +144,7 @@ impl Cfg {
 
     /// Whether the configuration consists of just `Cfg` or `Not`.
     fn is_simple(&self) -> bool {
-        match *self {
+        match self {
             Cfg::False | Cfg::True | Cfg::Cfg(..) | Cfg::Not(..) => true,
             Cfg::All(..) | Cfg::Any(..) => false,
         }
@@ -152,7 +152,7 @@ impl Cfg {
 
     /// Whether the configuration consists of just `Cfg`, `Not` or `All`.
     fn is_all(&self) -> bool {
-        match *self {
+        match self {
             Cfg::False | Cfg::True | Cfg::Cfg(..) | Cfg::Not(..) | Cfg::All(..) => true,
             Cfg::Any(..) => false,
         }
@@ -204,7 +204,7 @@ impl Cfg {
     }
 
     fn should_append_only_to_description(&self) -> bool {
-        match *self {
+        match self {
             Cfg::False | Cfg::True => false,
             Cfg::Any(..) | Cfg::All(..) | Cfg::Cfg(..) => true,
             Cfg::Not(box Cfg::Cfg(..)) => true,
@@ -261,17 +261,17 @@ impl ops::Not for Cfg {
 impl ops::BitAndAssign for Cfg {
     fn bitand_assign(&mut self, other: Cfg) {
         match (self, other) {
-            (&mut Cfg::False, _) | (_, Cfg::True) => {}
+            (Cfg::False, _) | (_, Cfg::True) => {}
             (s, Cfg::False) => *s = Cfg::False,
-            (s @ &mut Cfg::True, b) => *s = b,
-            (&mut Cfg::All(ref mut a), Cfg::All(ref mut b)) => {
+            (s @ Cfg::True, b) => *s = b,
+            (Cfg::All(a), Cfg::All(ref mut b)) => {
                 for c in b.drain(..) {
                     if !a.contains(&c) {
                         a.push(c);
                     }
                 }
             }
-            (&mut Cfg::All(ref mut a), ref mut b) => {
+            (Cfg::All(a), ref mut b) => {
                 if !a.contains(b) {
                     a.push(mem::replace(b, Cfg::True));
                 }
@@ -305,15 +305,15 @@ impl ops::BitOrAssign for Cfg {
     fn bitor_assign(&mut self, other: Cfg) {
         match (self, other) {
             (Cfg::True, _) | (_, Cfg::False) | (_, Cfg::True) => {}
-            (s @ &mut Cfg::False, b) => *s = b,
-            (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => {
+            (s @ Cfg::False, b) => *s = b,
+            (Cfg::Any(a), Cfg::Any(ref mut b)) => {
                 for c in b.drain(..) {
                     if !a.contains(&c) {
                         a.push(c);
                     }
                 }
             }
-            (&mut Cfg::Any(ref mut a), ref mut b) => {
+            (Cfg::Any(a), ref mut b) => {
                 if !a.contains(b) {
                     a.push(mem::replace(b, Cfg::True));
                 }
@@ -440,40 +440,34 @@ impl Display<'_> {
 
 impl fmt::Display for Display<'_> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self.0 {
-            Cfg::Not(ref child) => match **child {
-                Cfg::Any(ref sub_cfgs) => {
-                    let separator =
-                        if sub_cfgs.iter().all(Cfg::is_simple) { " nor " } else { ", nor " };
-                    fmt.write_str("neither ")?;
-
-                    sub_cfgs
-                        .iter()
-                        .map(|sub_cfg| {
-                            fmt::from_fn(|fmt| {
-                                write_with_opt_paren(
-                                    fmt,
-                                    !sub_cfg.is_all(),
-                                    Display(sub_cfg, self.1),
-                                )
-                            })
+        match self.0 {
+            Cfg::Not(box Cfg::Any(sub_cfgs)) => {
+                let separator =
+                    if sub_cfgs.iter().all(Cfg::is_simple) { " nor " } else { ", nor " };
+                fmt.write_str("neither ")?;
+
+                sub_cfgs
+                    .iter()
+                    .map(|sub_cfg| {
+                        fmt::from_fn(|fmt| {
+                            write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))
                         })
-                        .joined(separator, fmt)
-                }
-                ref simple @ Cfg::Cfg(..) => write!(fmt, "non-{}", Display(simple, self.1)),
-                ref c => write!(fmt, "not ({})", Display(c, self.1)),
-            },
+                    })
+                    .joined(separator, fmt)
+            }
+            Cfg::Not(box simple @ Cfg::Cfg(..)) => write!(fmt, "non-{}", Display(simple, self.1)),
+            Cfg::Not(box c) => write!(fmt, "not ({})", Display(c, self.1)),
 
-            Cfg::Any(ref sub_cfgs) => {
+            Cfg::Any(sub_cfgs) => {
                 let separator = if sub_cfgs.iter().all(Cfg::is_simple) { " or " } else { ", or " };
                 self.display_sub_cfgs(fmt, sub_cfgs, separator)
             }
-            Cfg::All(ref sub_cfgs) => self.display_sub_cfgs(fmt, sub_cfgs, " and "),
+            Cfg::All(sub_cfgs) => self.display_sub_cfgs(fmt, sub_cfgs, " and "),
 
             Cfg::True => fmt.write_str("everywhere"),
             Cfg::False => fmt.write_str("nowhere"),
 
-            Cfg::Cfg(name, value) => {
+            &Cfg::Cfg(name, value) => {
                 let human_readable = match (name, value) {
                     (sym::unix, None) => "Unix",
                     (sym::windows, None) => "Windows",
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 622a410837b..28dfa01534e 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -224,9 +224,9 @@ fn clean_generic_bound<'tcx>(
     bound: &hir::GenericBound<'tcx>,
     cx: &mut DocContext<'tcx>,
 ) -> Option<GenericBound> {
-    Some(match *bound {
+    Some(match bound {
         hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
-        hir::GenericBound::Trait(ref t) => {
+        hir::GenericBound::Trait(t) => {
             // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
             if let hir::BoundConstness::Maybe(_) = t.modifiers.constness
                 && cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap())
@@ -352,8 +352,8 @@ fn clean_where_predicate<'tcx>(
     if !predicate.kind.in_where_clause() {
         return None;
     }
-    Some(match *predicate.kind {
-        hir::WherePredicateKind::BoundPredicate(ref wbp) => {
+    Some(match predicate.kind {
+        hir::WherePredicateKind::BoundPredicate(wbp) => {
             let bound_params = wbp
                 .bound_generic_params
                 .iter()
@@ -366,12 +366,12 @@ fn clean_where_predicate<'tcx>(
             }
         }
 
-        hir::WherePredicateKind::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
+        hir::WherePredicateKind::RegionPredicate(wrp) => WherePredicate::RegionPredicate {
             lifetime: clean_lifetime(wrp.lifetime, cx),
             bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
         },
 
-        hir::WherePredicateKind::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
+        hir::WherePredicateKind::EqPredicate(wrp) => WherePredicate::EqPredicate {
             lhs: clean_ty(wrp.lhs_ty, cx),
             rhs: clean_ty(wrp.rhs_ty, cx).into(),
         },
@@ -2112,7 +2112,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
             );
             Type::Path { path }
         }
-        ty::Dynamic(obj, ref reg, _) => {
+        ty::Dynamic(obj, reg, _) => {
             // HACK: pick the first `did` as the `did` of the trait object. Someone
             // might want to implement "native" support for marker-trait-only
             // trait objects.
@@ -2129,7 +2129,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
             inline::record_extern_fqn(cx, did, ItemType::Trait);
 
-            let lifetime = clean_trait_object_lifetime_bound(*reg, container, obj, cx.tcx);
+            let lifetime = clean_trait_object_lifetime_bound(reg, container, obj, cx.tcx);
 
             let mut bounds = dids
                 .map(|did| {
@@ -2846,7 +2846,7 @@ fn clean_maybe_renamed_item<'tcx>(
                 ));
                 return ret;
             }
-            ItemKind::Enum(_, ref def, generics) => EnumItem(Enum {
+            ItemKind::Enum(_, def, generics) => EnumItem(Enum {
                 variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
                 generics: clean_generics(generics, cx),
             }),
@@ -2854,11 +2854,11 @@ fn clean_maybe_renamed_item<'tcx>(
                 generics: clean_generics(generics, cx),
                 bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
             }),
-            ItemKind::Union(_, ref variant_data, generics) => UnionItem(Union {
+            ItemKind::Union(_, variant_data, generics) => UnionItem(Union {
                 generics: clean_generics(generics, cx),
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
             }),
-            ItemKind::Struct(_, ref variant_data, generics) => StructItem(Struct {
+            ItemKind::Struct(_, variant_data, generics) => StructItem(Struct {
                 ctor_kind: variant_data.ctor_kind(),
                 generics: clean_generics(generics, cx),
                 fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 15890fff0c3..75f1bc9549c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1337,9 +1337,9 @@ pub(crate) enum WherePredicate {
 
 impl WherePredicate {
     pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
-        match *self {
-            WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
-            WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
+        match self {
+            WherePredicate::BoundPredicate { bounds, .. } => Some(bounds),
+            WherePredicate::RegionPredicate { bounds, .. } => Some(bounds),
             _ => None,
         }
     }
@@ -1709,13 +1709,13 @@ impl Type {
     ///
     /// [clean]: crate::clean
     pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
-        let t: PrimitiveType = match *self {
-            Type::Path { ref path } => return Some(path.def_id()),
-            DynTrait(ref bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
-            Primitive(p) => return cache.primitive_locations.get(&p).cloned(),
+        let t: PrimitiveType = match self {
+            Type::Path { path } => return Some(path.def_id()),
+            DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
+            Primitive(p) => return cache.primitive_locations.get(p).cloned(),
             BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
-            BorrowedRef { ref type_, .. } => return type_.def_id(cache),
-            Tuple(ref tys) => {
+            BorrowedRef { type_, .. } => return type_.def_id(cache),
+            Tuple(tys) => {
                 if tys.is_empty() {
                     PrimitiveType::Unit
                 } else {
@@ -1727,7 +1727,7 @@ impl Type {
             Array(..) => PrimitiveType::Array,
             Type::Pat(..) => PrimitiveType::Pat,
             RawPointer(..) => PrimitiveType::RawPointer,
-            QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache),
+            QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
             Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
         };
         Primitive(t).def_id(cache)
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index de6537e992f..3aba7a370ad 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -70,12 +70,12 @@ impl Serialize for ItemType {
 
 impl<'a> From<&'a clean::Item> for ItemType {
     fn from(item: &'a clean::Item) -> ItemType {
-        let kind = match item.kind {
-            clean::StrippedItem(box ref item) => item,
-            ref kind => kind,
+        let kind = match &item.kind {
+            clean::StrippedItem(box item) => item,
+            kind => kind,
         };
 
-        match *kind {
+        match kind {
             clean::ModuleItem(..) => ItemType::Module,
             clean::ExternCrateItem { .. } => ItemType::ExternCrate,
             clean::ImportItem(..) => ItemType::Import,
@@ -103,7 +103,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
             clean::ForeignTypeItem => ItemType::ForeignType,
             clean::KeywordItem => ItemType::Keyword,
             clean::TraitAliasItem(..) => ItemType::TraitAlias,
-            clean::ProcMacroItem(ref mac) => match mac.kind {
+            clean::ProcMacroItem(mac) => match mac.kind {
                 MacroKind::Bang => ItemType::Macro,
                 MacroKind::Attr => ItemType::ProcAttribute,
                 MacroKind::Derive => ItemType::ProcDerive,
@@ -134,22 +134,15 @@ impl ItemType {
             DefKind::Trait => Self::Trait,
             DefKind::TyAlias => Self::TypeAlias,
             DefKind::TraitAlias => Self::TraitAlias,
-            DefKind::Macro(kind) => match kind {
-                MacroKind::Bang => ItemType::Macro,
-                MacroKind::Attr => ItemType::ProcAttribute,
-                MacroKind::Derive => ItemType::ProcDerive,
-            },
+            DefKind::Macro(MacroKind::Bang) => ItemType::Macro,
+            DefKind::Macro(MacroKind::Attr) => ItemType::ProcAttribute,
+            DefKind::Macro(MacroKind::Derive) => ItemType::ProcDerive,
             DefKind::ForeignTy => Self::ForeignType,
             DefKind::Variant => Self::Variant,
             DefKind::Field => Self::StructField,
             DefKind::AssocTy => Self::AssocType,
-            DefKind::AssocFn => {
-                if let Some(DefKind::Trait) = parent_kind {
-                    Self::TyMethod
-                } else {
-                    Self::Method
-                }
-            }
+            DefKind::AssocFn if let Some(DefKind::Trait) = parent_kind => Self::TyMethod,
+            DefKind::AssocFn => Self::Method,
             DefKind::Ctor(CtorOf::Struct, _) => Self::Struct,
             DefKind::Ctor(CtorOf::Variant, _) => Self::Variant,
             DefKind::AssocConst => Self::AssocConst,
@@ -170,7 +163,7 @@ impl ItemType {
     }
 
     pub(crate) fn as_str(&self) -> &'static str {
-        match *self {
+        match self {
             ItemType::Module => "mod",
             ItemType::ExternCrate => "externcrate",
             ItemType::Import => "import",
@@ -199,10 +192,10 @@ impl ItemType {
         }
     }
     pub(crate) fn is_method(&self) -> bool {
-        matches!(*self, ItemType::Method | ItemType::TyMethod)
+        matches!(self, ItemType::Method | ItemType::TyMethod)
     }
     pub(crate) fn is_adt(&self) -> bool {
-        matches!(*self, ItemType::Struct | ItemType::Union | ItemType::Enum)
+        matches!(self, ItemType::Struct | ItemType::Union | ItemType::Enum)
     }
 }
 
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 299fd6b9adb..8c7ab640bed 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -856,15 +856,15 @@ fn fmt_type(
 ) -> fmt::Result {
     trace!("fmt_type(t = {t:?})");
 
-    match *t {
+    match t {
         clean::Generic(name) => f.write_str(name.as_str()),
         clean::SelfTy => f.write_str("Self"),
-        clean::Type::Path { ref path } => {
+        clean::Type::Path { path } => {
             // Paths like `T::Output` and `Self::Output` should be rendered with all segments.
             let did = path.def_id();
             resolved_path(f, did, path, path.is_assoc_ty(), use_absolute, cx)
         }
-        clean::DynTrait(ref bounds, ref lt) => {
+        clean::DynTrait(bounds, lt) => {
             f.write_str("dyn ")?;
             tybounds(bounds, lt, cx).fmt(f)
         }
@@ -872,8 +872,8 @@ fn fmt_type(
         clean::Primitive(clean::PrimitiveType::Never) => {
             primitive_link(f, PrimitiveType::Never, format_args!("!"), cx)
         }
-        clean::Primitive(prim) => primitive_link(f, prim, format_args!("{}", prim.as_sym()), cx),
-        clean::BareFunction(ref decl) => {
+        &clean::Primitive(prim) => primitive_link(f, prim, format_args!("{}", prim.as_sym()), cx),
+        clean::BareFunction(decl) => {
             print_higher_ranked_params_with_space(&decl.generic_params, cx, "for").fmt(f)?;
             decl.safety.print_with_space().fmt(f)?;
             print_abi_with_space(decl.abi).fmt(f)?;
@@ -884,11 +884,11 @@ fn fmt_type(
             }
             decl.decl.print(cx).fmt(f)
         }
-        clean::UnsafeBinder(ref binder) => {
+        clean::UnsafeBinder(binder) => {
             print_higher_ranked_params_with_space(&binder.generic_params, cx, "unsafe").fmt(f)?;
             binder.ty.print(cx).fmt(f)
         }
-        clean::Tuple(ref typs) => match &typs[..] {
+        clean::Tuple(typs) => match &typs[..] {
             &[] => primitive_link(f, PrimitiveType::Unit, format_args!("()"), cx),
             [one] => {
                 if let clean::Generic(name) = one {
@@ -925,45 +925,36 @@ fn fmt_type(
                 }
             }
         },
-        clean::Slice(ref t) => match **t {
-            clean::Generic(name) => {
-                primitive_link(f, PrimitiveType::Slice, format_args!("[{name}]"), cx)
-            }
-            _ => {
-                write!(f, "[")?;
-                t.print(cx).fmt(f)?;
-                write!(f, "]")
-            }
-        },
-        clean::Type::Pat(ref t, ref pat) => {
+        clean::Slice(box clean::Generic(name)) => {
+            primitive_link(f, PrimitiveType::Slice, format_args!("[{name}]"), cx)
+        }
+        clean::Slice(t) => {
+            write!(f, "[")?;
+            t.print(cx).fmt(f)?;
+            write!(f, "]")
+        }
+        clean::Type::Pat(t, pat) => {
             fmt::Display::fmt(&t.print(cx), f)?;
             write!(f, " is {pat}")
         }
-        clean::Array(ref t, ref n) => match **t {
-            clean::Generic(name) if !f.alternate() => primitive_link(
-                f,
-                PrimitiveType::Array,
-                format_args!("[{name}; {n}]", n = Escape(n)),
-                cx,
-            ),
-            _ => {
-                write!(f, "[")?;
-                t.print(cx).fmt(f)?;
-                if f.alternate() {
-                    write!(f, "; {n}")?;
-                } else {
-                    write!(f, "; ")?;
-                    primitive_link(
-                        f,
-                        PrimitiveType::Array,
-                        format_args!("{n}", n = Escape(n)),
-                        cx,
-                    )?;
-                }
-                write!(f, "]")
+        clean::Array(box clean::Generic(name), n) if !f.alternate() => primitive_link(
+            f,
+            PrimitiveType::Array,
+            format_args!("[{name}; {n}]", n = Escape(n)),
+            cx,
+        ),
+        clean::Array(t, n) => {
+            write!(f, "[")?;
+            t.print(cx).fmt(f)?;
+            if f.alternate() {
+                write!(f, "; {n}")?;
+            } else {
+                write!(f, "; ")?;
+                primitive_link(f, PrimitiveType::Array, format_args!("{n}", n = Escape(n)), cx)?;
             }
-        },
-        clean::RawPointer(m, ref t) => {
+            write!(f, "]")
+        }
+        clean::RawPointer(m, t) => {
             let m = match m {
                 hir::Mutability::Mut => "mut",
                 hir::Mutability::Not => "const",
@@ -991,7 +982,7 @@ fn fmt_type(
                 t.print(cx).fmt(f)
             }
         }
-        clean::BorrowedRef { lifetime: ref l, mutability, type_: ref ty } => {
+        clean::BorrowedRef { lifetime: l, mutability, type_: ty } => {
             let lt = fmt::from_fn(|f| match l {
                 Some(l) => write!(f, "{} ", l.print()),
                 _ => Ok(()),
@@ -1028,11 +1019,11 @@ fn fmt_type(
             }
             Ok(())
         }
-        clean::ImplTrait(ref bounds) => {
+        clean::ImplTrait(bounds) => {
             f.write_str("impl ")?;
             print_generic_bounds(bounds, cx).fmt(f)
         }
-        clean::QPath(box clean::QPathData {
+        &clean::QPath(box clean::QPathData {
             ref assoc,
             ref self_type,
             ref trait_,
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b4210e7b518..b4003044e20 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -11,7 +11,6 @@
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(round_char_boundary)]
 #![feature(test)]
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 8448283b4bd34ea00d76fd4f18ec730b549d6e1
+Subproject c1118fdbb3024157df7f4cfe765f2b0b4339e8a
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 7b7be97aa51..e4d7abdb0f7 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -6,7 +6,7 @@ name = "miri"
 repository = "https://github.com/rust-lang/miri"
 version = "0.1.0"
 default-run = "miri"
-edition = "2021"
+edition = "2024"
 
 [lib]
 test = true     # we have unit tests
diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml
index ed142b0e211..23048914af1 100644
--- a/src/tools/miri/cargo-miri/Cargo.toml
+++ b/src/tools/miri/cargo-miri/Cargo.toml
@@ -5,7 +5,7 @@ license = "MIT OR Apache-2.0"
 name = "cargo-miri"
 repository = "https://github.com/rust-lang/miri"
 version = "0.1.0"
-edition = "2021"
+edition = "2024"
 
 [[bin]]
 name = "cargo-miri"
diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs
index 322ef0a6c2a..4c01a81fdfd 100644
--- a/src/tools/miri/cargo-miri/src/main.rs
+++ b/src/tools/miri/cargo-miri/src/main.rs
@@ -63,27 +63,37 @@ fn main() {
         return;
     }
 
+    let Some(first) = args.next() else {
+        show_error!(
+            "`cargo-miri` called without first argument; please only invoke this binary through `cargo miri`"
+        )
+    };
+
     // The way rustdoc invokes rustc is indistinguishable from the way cargo invokes rustdoc by the
     // arguments alone. `phase_cargo_rustdoc` sets this environment variable to let us disambiguate.
     if env::var_os("MIRI_CALLED_FROM_RUSTDOC").is_some() {
         // ...however, we then also see this variable when rustdoc invokes us as the testrunner!
-        // The runner is invoked as `$runtool ($runtool-arg)* output_file`;
-        // since we don't specify any runtool-args, and rustdoc supplies multiple arguments to
-        // the test-builder unconditionally, we can just check the number of remaining arguments:
-        if args.len() == 1 {
-            phase_runner(args, RunnerPhase::Rustdoc);
-        } else {
-            phase_rustc(args, RustcPhase::Rustdoc);
+        // In that case the first argument is `runner` and there are no more arguments.
+        match first.as_str() {
+            "runner" => phase_runner(args, RunnerPhase::Rustdoc),
+            flag if flag.starts_with("--") || flag.starts_with("@") => {
+                // This is probably rustdoc invoking us to build the test. But we need to get `first`
+                // "back onto the iterator", it is some part of the rustc invocation.
+                phase_rustc(iter::once(first).chain(args), RustcPhase::Rustdoc);
+            }
+            _ => {
+                show_error!(
+                    "`cargo-miri` failed to recognize which phase of the build process this is, please report a bug.\n\
+                    We are inside MIRI_CALLED_FROM_RUSTDOC.\n\
+                    The command-line arguments were: {:#?}",
+                    Vec::from_iter(env::args()),
+                );
+            }
         }
 
         return;
     }
 
-    let Some(first) = args.next() else {
-        show_error!(
-            "`cargo-miri` called without first argument; please only invoke this binary through `cargo miri`"
-        )
-    };
     match first.as_str() {
         "miri" => phase_cargo_miri(args),
         "runner" => phase_runner(args, RunnerPhase::Cargo),
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index cb62e12413c..171e157789d 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -176,6 +176,8 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     // Set `--target-dir` to `miri` inside the original target directory.
     let target_dir = get_target_dir(&metadata);
     cmd.arg("--target-dir").arg(target_dir);
+    // Enable cross-target doctests (for consistency between different cargo versions).
+    cmd.arg("-Zdoctest-xcompile");
 
     // *After* we set all the flags that need setting, forward everything else. Make sure to skip
     // `--target-dir` (which would otherwise be set twice).
@@ -666,11 +668,6 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
         if arg == "--extern" {
             // Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
             forward_patched_extern_arg(&mut args, &mut cmd);
-        } else if arg == "--test-runtool" {
-            // An existing --test-runtool flag indicates cargo is running in cross-target mode, which we don't support.
-            // Note that this is only passed when cargo is run with the unstable -Zdoctest-xcompile flag;
-            // otherwise, we won't be called as rustdoc at all.
-            show_error!("cross-interpreting doctests is not currently supported by Miri.");
         } else {
             cmd.arg(arg);
         }
@@ -702,10 +699,10 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
     // make sure the 'miri' flag is set for rustdoc
     cmd.arg("--cfg").arg("miri");
 
-    // Make rustdoc call us back.
+    // Make rustdoc call us back for the build.
+    // (cargo already sets `--test-runtool` to us since we are the cargo test runner.)
     let cargo_miri_path = env::current_exe().expect("current executable path invalid");
     cmd.arg("--test-builder").arg(&cargo_miri_path); // invoked by forwarding most arguments
-    cmd.arg("--test-runtool").arg(&cargo_miri_path); // invoked with just a single path argument
 
     debug_cmd("[cargo-miri rustdoc]", verbose, &cmd);
     exec(cmd)
diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs
index 7afc8481009..b9b58c04f9e 100644
--- a/src/tools/miri/cargo-miri/src/setup.rs
+++ b/src/tools/miri/cargo-miri/src/setup.rs
@@ -24,11 +24,9 @@ pub fn setup(
     let ask_user = !only_setup;
     let print_sysroot = only_setup && has_arg_flag("--print-sysroot"); // whether we just print the sysroot path
     let show_setup = only_setup && !print_sysroot;
-    if !only_setup {
-        if let Some(sysroot) = std::env::var_os("MIRI_SYSROOT") {
-            // Skip setup step if MIRI_SYSROOT is explicitly set, *unless* we are `cargo miri setup`.
-            return sysroot.into();
-        }
+    if !only_setup && let Some(sysroot) = std::env::var_os("MIRI_SYSROOT") {
+        // Skip setup step if MIRI_SYSROOT is explicitly set, *unless* we are `cargo miri setup`.
+        return sysroot.into();
     }
 
     // Determine where the rust sources are located.  The env var trumps auto-detection.
diff --git a/src/tools/miri/miri-script/Cargo.toml b/src/tools/miri/miri-script/Cargo.toml
index a04898de6ab..462a9cc62bf 100644
--- a/src/tools/miri/miri-script/Cargo.toml
+++ b/src/tools/miri/miri-script/Cargo.toml
@@ -6,7 +6,7 @@ name = "miri-script"
 repository = "https://github.com/rust-lang/miri"
 version = "0.1.0"
 default-run = "miri-script"
-edition = "2021"
+edition = "2024"
 
 [workspace]
 # We make this a workspace root so that cargo does not go looking in ../Cargo.toml for the workspace root.
diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs
index 1c9750e2cbd..3b7b159aeab 100644
--- a/src/tools/miri/miri-script/src/commands.rs
+++ b/src/tools/miri/miri-script/src/commands.rs
@@ -675,11 +675,9 @@ impl Command {
         let mut early_flags = Vec::<OsString>::new();
 
         // In `dep` mode, the target is already passed via `MIRI_TEST_TARGET`
-        if !dep {
-            if let Some(target) = &target {
-                early_flags.push("--target".into());
-                early_flags.push(target.into());
-            }
+        if !dep && let Some(target) = &target {
+            early_flags.push("--target".into());
+            early_flags.push(target.into());
         }
         early_flags.push("--edition".into());
         early_flags.push(edition.as_deref().unwrap_or("2021").into());
@@ -707,10 +705,8 @@ impl Command {
         // Add Miri flags
         let mut cmd = cmd.args(&miri_flags).args(&early_flags).args(&flags);
         // For `--dep` we also need to set the target in the env var.
-        if dep {
-            if let Some(target) = &target {
-                cmd = cmd.env("MIRI_TEST_TARGET", target);
-            }
+        if dep && let Some(target) = &target {
+            cmd = cmd.env("MIRI_TEST_TARGET", target);
         }
         // Finally, run the thing.
         Ok(cmd.run()?)
diff --git a/src/tools/miri/miri-script/src/util.rs b/src/tools/miri/miri-script/src/util.rs
index c039b4827ee..5c2a055990f 100644
--- a/src/tools/miri/miri-script/src/util.rs
+++ b/src/tools/miri/miri-script/src/util.rs
@@ -213,7 +213,7 @@ impl MiriEnv {
             let toolchain = &self.toolchain;
             let mut cmd = cmd!(
                 self.sh,
-                "rustfmt +{toolchain} --edition=2021 --config-path {config_path} --unstable-features --skip-children {flags...}"
+                "rustfmt +{toolchain} --edition=2024 --config-path {config_path} --unstable-features --skip-children {flags...}"
             );
             if first {
                 // Log an abbreviating command, and only once.
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 97bc826b57a..79abbfaeaf1 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-2ad5f8607d0e192b60b130e5cc416b477b351c18
+a69bc17fb8026bdc0d24bb1896ff95f0eba1da4e
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index f249b58aeb6..469fc264970 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -459,7 +459,7 @@ fn jemalloc_magic() {
     // linking, so we need to explicitly depend on the function.
     #[cfg(target_os = "macos")]
     {
-        extern "C" {
+        unsafe extern "C" {
             fn _rjem_je_zone_register();
         }
 
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
index b2fd9b2bf05..f5a0013047a 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
@@ -179,7 +179,7 @@ impl NodeDebugInfo {
     /// Add a name to the tag. If a same tag is associated to several pointers,
     /// it can have several names which will be separated by commas.
     pub fn add_name(&mut self, name: &str) {
-        if let Some(ref mut prev_name) = &mut self.name {
+        if let Some(prev_name) = &mut self.name {
             prev_name.push_str(", ");
             prev_name.push_str(name);
         } else {
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 89768077d87..10570a37e5d 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -648,8 +648,7 @@ impl<'tcx> MiriMachine<'tcx> {
             AccessedAlloc(AllocId(id), access_kind) =>
                 format!("{access_kind} to allocation with id {id}"),
             FreedAlloc(AllocId(id)) => format!("freed allocation with id {id}"),
-            RejectedIsolatedOp(ref op) =>
-                format!("{op} was made to return an error due to isolation"),
+            RejectedIsolatedOp(op) => format!("{op} was made to return an error due to isolation"),
             ProgressReport { .. } =>
                 format!("progress report: current operation being executed is here"),
             Int2Ptr { .. } => format!("integer-to-pointer cast"),
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index a3aa8bbbfb3..d2a73516623 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -932,12 +932,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         self.read_c_str_with_char_size(ptr, wchar_t.size, wchar_t.align.abi)
     }
 
-    /// Check that the ABI is what we expect.
-    fn check_abi<'a>(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, exp_abi: Conv) -> InterpResult<'a, ()> {
+    /// Check that the calling convention is what we expect.
+    fn check_callconv<'a>(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, exp_abi: Conv) -> InterpResult<'a, ()> {
         if fn_abi.conv != exp_abi {
             throw_ub_format!(
-                "calling a function with ABI {:?} using caller ABI {:?}",
-                exp_abi,
+                "calling a function with calling convention {exp_abi} using caller calling convention {}",
                 fn_abi.conv
             );
         }
@@ -973,7 +972,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         exp_abi: Conv,
         link_name: Symbol,
     ) -> InterpResult<'tcx, ()> {
-        self.check_abi(abi, exp_abi)?;
+        self.check_callconv(abi, exp_abi)?;
         if let Some((body, instance)) = self.eval_context_mut().lookup_exported_symbol(link_name)? {
             // If compiler-builtins is providing the symbol, then don't treat it as a clash.
             // We'll use our built-in implementation in `emulate_foreign_item_inner` for increased
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 58b93ae82a1..0b7a067058b 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -9,7 +9,6 @@
 #![feature(variant_count)]
 #![feature(yeet_expr)]
 #![feature(nonzero_ops)]
-#![feature(let_chains)]
 #![feature(strict_overflow_ops)]
 #![feature(pointer_is_aligned_to)]
 #![feature(unqualified_local_imports)]
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 18af8214876..b5ed5ea837b 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -85,6 +85,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         // Now we make a function call, and pass `data` as first and only argument.
         let f_instance = this.get_ptr_fn(try_fn)?.as_instance()?;
         trace!("try_fn: {:?}", f_instance);
+        #[allow(clippy::cloned_ref_to_slice_refs)] // the code is clearer as-is
         this.call_function(
             f_instance,
             ExternAbi::Rust,
diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py
index a9d09ac7a9d..40bfe7f845f 100755
--- a/src/tools/miri/test-cargo-miri/run-test.py
+++ b/src/tools/miri/test-cargo-miri/run-test.py
@@ -142,24 +142,19 @@ def test_cargo_miri_run():
     )
 
 def test_cargo_miri_test():
-    # rustdoc is not run on foreign targets
-    is_foreign = ARGS.target is not None
-    default_ref = "test.cross-target.stdout.ref" if is_foreign else "test.default.stdout.ref"
-    filter_ref = "test.filter.cross-target.stdout.ref" if is_foreign else "test.filter.stdout.ref"
-
     test("`cargo miri test`",
         cargo_miri("test"),
-        default_ref, "test.empty.ref",
+        "test.default.stdout.ref", "test.empty.ref",
         env={'MIRIFLAGS': "-Zmiri-seed=4242"},
     )
     test("`cargo miri test` (no isolation, no doctests)",
         cargo_miri("test") + ["--bins", "--tests"], # no `--lib`, we disabled that in `Cargo.toml`
-        "test.cross-target.stdout.ref", "test.empty.ref",
+        "test.no-doc.stdout.ref", "test.empty.ref",
         env={'MIRIFLAGS': "-Zmiri-disable-isolation"},
     )
     test("`cargo miri test` (with filter)",
         cargo_miri("test") + ["--", "--format=pretty", "pl"],
-        filter_ref, "test.empty.ref",
+        "test.filter.stdout.ref", "test.empty.ref",
     )
     test("`cargo miri test` (test target)",
         cargo_miri("test") + ["--test", "test", "--", "--format=pretty"],
@@ -171,7 +166,7 @@ def test_cargo_miri_test():
     )
     test("`cargo miri t` (subcrate, no isolation)",
         cargo_miri("t") + ["-p", "subcrate"],
-        "test.subcrate.cross-target.stdout.ref" if is_foreign else "test.subcrate.stdout.ref",
+        "test.subcrate.stdout.ref",
         "test.empty.ref",
         env={'MIRIFLAGS': "-Zmiri-disable-isolation"},
     )
@@ -181,12 +176,12 @@ def test_cargo_miri_test():
     )
     test("`cargo miri test` (custom target dir)",
         cargo_miri("test") + ["--target-dir=custom-test"],
-        default_ref, "test.empty.ref",
+        "test.default.stdout.ref", "test.empty.ref",
     )
     del os.environ["CARGO_TARGET_DIR"] # this overrides `build.target-dir` passed by `--config`, so unset it
     test("`cargo miri test` (config-cli)",
         cargo_miri("test") + ["--config=build.target-dir=\"config-cli\""],
-        default_ref, "test.empty.ref",
+        "test.default.stdout.ref", "test.empty.ref",
     )
     if ARGS.multi_target:
         test_cargo_miri_multi_target()
diff --git a/src/tools/miri/test-cargo-miri/test.filter.cross-target.stdout.ref b/src/tools/miri/test-cargo-miri/test.filter.cross-target.stdout.ref
deleted file mode 100644
index 59b4deb1ff3..00000000000
--- a/src/tools/miri/test-cargo-miri/test.filter.cross-target.stdout.ref
+++ /dev/null
@@ -1,12 +0,0 @@
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out; finished in $TIME
-
-imported main
-
-running 1 test
-test simple ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 5 filtered out; finished in $TIME
-
diff --git a/src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref b/src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref
index 567c5db07d0..a376530a8cf 100644
--- a/src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref
+++ b/src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref
@@ -20,3 +20,13 @@ running 6 tests
 ...i..
 test result: ok. 5 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
 
+
+running 5 tests
+.....
+test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
+
+running 5 tests
+.....
+test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/tools/miri/test-cargo-miri/test.cross-target.stdout.ref b/src/tools/miri/test-cargo-miri/test.no-doc.stdout.ref
index 2ef124e4de8..2ef124e4de8 100644
--- a/src/tools/miri/test-cargo-miri/test.cross-target.stdout.ref
+++ b/src/tools/miri/test-cargo-miri/test.no-doc.stdout.ref
diff --git a/src/tools/miri/test-cargo-miri/test.subcrate.cross-target.stdout.ref b/src/tools/miri/test-cargo-miri/test.subcrate.cross-target.stdout.ref
deleted file mode 100644
index 436e6e4fbbb..00000000000
--- a/src/tools/miri/test-cargo-miri/test.subcrate.cross-target.stdout.ref
+++ /dev/null
@@ -1,11 +0,0 @@
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
-
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
-
-subcrate testing
diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs
index 2097126e16b..4a87411d755 100644
--- a/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs
+++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs
@@ -1,5 +1,5 @@
 //@error-in-other-file: aborted
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 #![feature(allocator_api)]
 
diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr
index 3642f3f28ca..fa84da841fd 100644
--- a/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr
+++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr
@@ -2,7 +2,7 @@ memory allocation of 4 bytes failed
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_abi.rs b/src/tools/miri/tests/fail/function_calls/check_arg_abi.rs
index ffa0443ce50..0e916364169 100644
--- a/src/tools/miri/tests/fail/function_calls/check_arg_abi.rs
+++ b/src/tools/miri/tests/fail/function_calls/check_arg_abi.rs
@@ -4,6 +4,6 @@ fn main() {
     }
 
     unsafe {
-        let _ = malloc(0); //~ ERROR: calling a function with ABI C using caller ABI Rust
+        let _ = malloc(0); //~ ERROR: calling a function with calling convention "C" using caller calling convention "Rust"
     };
 }
diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr b/src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr
index bf1fbb7721f..78730182923 100644
--- a/src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr
+++ b/src/tools/miri/tests/fail/function_calls/check_arg_abi.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: calling a function with ABI C using caller ABI Rust
+error: Undefined Behavior: calling a function with calling convention "C" using caller calling convention "Rust"
   --> tests/fail/function_calls/check_arg_abi.rs:LL:CC
    |
 LL |         let _ = malloc(0);
-   |                 ^^^^^^^^^ calling a function with ABI C using caller ABI Rust
+   |                 ^^^^^^^^^ calling a function with calling convention "C" using caller calling convention "Rust"
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/check_callback_abi.rs b/src/tools/miri/tests/fail/function_calls/check_callback_abi.rs
index 6a7a26710d1..177e38105e6 100644
--- a/src/tools/miri/tests/fail/function_calls/check_callback_abi.rs
+++ b/src/tools/miri/tests/fail/function_calls/check_callback_abi.rs
@@ -9,7 +9,7 @@ fn main() {
         // Make sure we check the ABI when Miri itself invokes a function
         // as part of a shim implementation.
         std::intrinsics::catch_unwind(
-            //~^ ERROR: calling a function with calling convention C using calling convention Rust
+            //~^ ERROR: calling a function with calling convention "C" using calling convention "Rust"
             std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
             std::ptr::null_mut(),
             |_, _| unreachable!(),
diff --git a/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr b/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr
index 6b0692e1c6e..20182ac9236 100644
--- a/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr
+++ b/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: calling a function with calling convention C using calling convention Rust
+error: Undefined Behavior: calling a function with calling convention "C" using calling convention "Rust"
   --> tests/fail/function_calls/check_callback_abi.rs:LL:CC
    |
 LL | /         std::intrinsics::catch_unwind(
@@ -7,7 +7,7 @@ LL | |             std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
 LL | |             std::ptr::null_mut(),
 LL | |             |_, _| unreachable!(),
 LL | |         );
-   | |_________^ calling a function with calling convention C using calling convention Rust
+   | |_________^ calling a function with calling convention "C" using calling convention "Rust"
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr
index e4302ad1d3a..46a32d1487e 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.cache.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: calling a function with calling convention Rust using calling convention C
+error: Undefined Behavior: calling a function with calling convention "Rust" using calling convention "C"
   --> tests/fail/function_calls/exported_symbol_abi_mismatch.rs:LL:CC
    |
 LL |             foo();
-   |             ^^^^^ calling a function with calling convention Rust using calling convention C
+   |             ^^^^^ calling a function with calling convention "Rust" using calling convention "C"
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr
index 9f40c48b338..38725289919 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.fn_ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: calling a function with calling convention Rust using calling convention C
+error: Undefined Behavior: calling a function with calling convention "Rust" using calling convention "C"
   --> tests/fail/function_calls/exported_symbol_abi_mismatch.rs:LL:CC
    |
 LL |         std::mem::transmute::<unsafe fn(), unsafe extern "C" fn()>(foo)();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with calling convention Rust using calling convention C
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with calling convention "Rust" using calling convention "C"
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr
index e4302ad1d3a..46a32d1487e 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.no_cache.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: calling a function with calling convention Rust using calling convention C
+error: Undefined Behavior: calling a function with calling convention "Rust" using calling convention "C"
   --> tests/fail/function_calls/exported_symbol_abi_mismatch.rs:LL:CC
    |
 LL |             foo();
-   |             ^^^^^ calling a function with calling convention Rust using calling convention C
+   |             ^^^^^ calling a function with calling convention "Rust" using calling convention "C"
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.rs
index 50a0e8e6ede..1950e162c07 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.rs
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_abi_mismatch.rs
@@ -12,7 +12,7 @@ fn main() {
     #[cfg(fn_ptr)]
     unsafe {
         std::mem::transmute::<unsafe fn(), unsafe extern "C" fn()>(foo)();
-        //~[fn_ptr]^ ERROR: calling a function with calling convention Rust using calling convention C
+        //~[fn_ptr]^ ERROR: calling a function with calling convention "Rust" using calling convention "C"
     }
 
     // `Instance` caching should not suppress ABI check.
@@ -28,8 +28,8 @@ fn main() {
         }
         unsafe {
             foo();
-            //~[no_cache]^ ERROR: calling a function with calling convention Rust using calling convention C
-            //~[cache]| ERROR: calling a function with calling convention Rust using calling convention C
+            //~[no_cache]^ ERROR: calling a function with calling convention "Rust" using calling convention "C"
+            //~[cache]| ERROR: calling a function with calling convention "Rust" using calling convention "C"
         }
     }
 }
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
index b2a501db776..7cb2bf99678 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
@@ -11,7 +11,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
index b2a501db776..7cb2bf99678 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
@@ -11,7 +11,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
index 1382e9571f3..9d993786d57 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
@@ -1,5 +1,5 @@
 //@revisions: extern_block definition both
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
 //@normalize-stderr-test: "\n +at [^\n]+" -> ""
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
index 6e0e0ca9f53..dd3246d8120 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
@@ -1,4 +1,4 @@
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
 //@normalize-stderr-test: "\n +at [^\n]+" -> ""
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
index 2c9bea1724d..ba96e595bee 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
@@ -7,7 +7,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
index 0e8d3d08c12..3d355bad626 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
@@ -1,4 +1,4 @@
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
 //@normalize-stderr-test: "\n +at [^\n]+" -> ""
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
index 0634298a38f..7e1f4160cc0 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
@@ -7,7 +7,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/panic/abort_unwind.rs b/src/tools/miri/tests/fail/panic/abort_unwind.rs
index e313d9c11de..bd819362da4 100644
--- a/src/tools/miri/tests/fail/panic/abort_unwind.rs
+++ b/src/tools/miri/tests/fail/panic/abort_unwind.rs
@@ -1,5 +1,5 @@
 //@error-in-other-file: the program aborted execution
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
 //@normalize-stderr-test: "\n +at [^\n]+" -> ""
diff --git a/src/tools/miri/tests/fail/panic/abort_unwind.stderr b/src/tools/miri/tests/fail/panic/abort_unwind.stderr
index 3a63cb38ad0..e6668b09f66 100644
--- a/src/tools/miri/tests/fail/panic/abort_unwind.stderr
+++ b/src/tools/miri/tests/fail/panic/abort_unwind.stderr
@@ -11,7 +11,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/panic/double_panic.rs b/src/tools/miri/tests/fail/panic/double_panic.rs
index ddc75521eca..4d8f4cb6fb7 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.rs
+++ b/src/tools/miri/tests/fail/panic/double_panic.rs
@@ -1,4 +1,4 @@
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
 //@normalize-stderr-test: "\n +at [^\n]+" -> ""
diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr
index 16e933be434..67f88955def 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/double_panic.stderr
@@ -14,7 +14,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.rs b/src/tools/miri/tests/fail/panic/panic_abort1.rs
index 7552c7b7e80..06cb673778a 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort1.rs
+++ b/src/tools/miri/tests/fail/panic/panic_abort1.rs
@@ -1,6 +1,6 @@
 //@error-in-other-file: the program aborted execution
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\); \}|core::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@compile-flags: -C panic=abort
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr
index c950b2b4ea6..6d56874ebde 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr
@@ -4,13 +4,15 @@ panicking from libstd
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 error: abnormal termination: the program aborted execution
-  --> RUSTLIB/panic_abort/src/lib.rs:LL:CC
+  --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |                 ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
-   = note: inside `panic_abort::__rust_start_panic::abort` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
+   = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC
+   = note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC
    = note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.rs b/src/tools/miri/tests/fail/panic/panic_abort2.rs
index 624f9933545..c011b3ee7eb 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort2.rs
+++ b/src/tools/miri/tests/fail/panic/panic_abort2.rs
@@ -1,6 +1,6 @@
 //@error-in-other-file: the program aborted execution
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\); \}|core::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@compile-flags: -C panic=abort
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr
index 9a9266ec493..dbb56f13f48 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr
@@ -4,13 +4,15 @@ thread 'main' panicked at tests/fail/panic/panic_abort2.rs:LL:CC:
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 error: abnormal termination: the program aborted execution
-  --> RUSTLIB/panic_abort/src/lib.rs:LL:CC
+  --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |                 ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
-   = note: inside `panic_abort::__rust_start_panic::abort` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
+   = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC
+   = note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC
    = note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.rs b/src/tools/miri/tests/fail/panic/panic_abort3.rs
index d1435b55946..911dc4a44ab 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort3.rs
+++ b/src/tools/miri/tests/fail/panic/panic_abort3.rs
@@ -1,6 +1,6 @@
 //@error-in-other-file: the program aborted execution
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\); \}|core::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@compile-flags: -C panic=abort
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr
index f04a2b0f3f1..7f0564879e4 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr
@@ -4,13 +4,15 @@ panicking from libcore
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 error: abnormal termination: the program aborted execution
-  --> RUSTLIB/panic_abort/src/lib.rs:LL:CC
+  --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |                 ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
-   = note: inside `panic_abort::__rust_start_panic::abort` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
+   = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC
+   = note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC
    = note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.rs b/src/tools/miri/tests/fail/panic/panic_abort4.rs
index 54b9c9cbfdb..696fdff7422 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort4.rs
+++ b/src/tools/miri/tests/fail/panic/panic_abort4.rs
@@ -1,6 +1,6 @@
 //@error-in-other-file: the program aborted execution
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\); \}|core::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@compile-flags: -C panic=abort
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr
index e71c4879ea3..ce6910b9933 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr
@@ -4,13 +4,15 @@ thread 'main' panicked at tests/fail/panic/panic_abort4.rs:LL:CC:
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect
 error: abnormal termination: the program aborted execution
-  --> RUSTLIB/panic_abort/src/lib.rs:LL:CC
+  --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |                 ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
-   = note: inside `panic_abort::__rust_start_panic::abort` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
+   = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC
+   = note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC
    = note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC
    = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs
index 6f627c416b0..6119e8604b4 100644
--- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs
+++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs
@@ -1,6 +1,6 @@
 //! This is a regression test for <https://github.com/rust-lang/miri/issues/4188>: The precondition
 //! check in `ptr::swap_nonoverlapping` was incorrectly disabled in Miri.
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
 //@normalize-stderr-test: "\n +at [^\n]+" -> ""
diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
index 80dd2f39b42..f57487e3ffe 100644
--- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
+++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr
@@ -9,7 +9,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/tail_calls/cc-mismatch.rs b/src/tools/miri/tests/fail/tail_calls/cc-mismatch.rs
index 5f00dbf2573..952f9697fc7 100644
--- a/src/tools/miri/tests/fail/tail_calls/cc-mismatch.rs
+++ b/src/tools/miri/tests/fail/tail_calls/cc-mismatch.rs
@@ -1,4 +1,4 @@
-//@error-in-other-file: Undefined Behavior: calling a function with calling convention C using calling convention Rust
+//@error-in-other-file: Undefined Behavior: calling a function with calling convention "C" using calling convention "Rust"
 #![feature(explicit_tail_calls)]
 #![allow(incomplete_features)]
 
diff --git a/src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr b/src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
index 5061c9e8dc3..61ddea64472 100644
--- a/src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
+++ b/src/tools/miri/tests/fail/tail_calls/cc-mismatch.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: calling a function with calling convention C using calling convention Rust
+error: Undefined Behavior: calling a function with calling convention "C" using calling convention "Rust"
   --> RUSTLIB/core/src/ops/function.rs:LL:CC
    |
 LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with calling convention C using calling convention Rust
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with calling convention "C" using calling convention "Rust"
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs
index 465625c7572..31ae829a2de 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.rs
+++ b/src/tools/miri/tests/fail/terminate-terminator.rs
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
 //@normalize-stderr-test: "\n +at [^\n]+" -> ""
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
index f2548bf5cdb..d16119a30e6 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.stderr
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -13,7 +13,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.rs b/src/tools/miri/tests/fail/unwind-action-terminate.rs
index 465e07c8db4..f0fbcfd8867 100644
--- a/src/tools/miri/tests/fail/unwind-action-terminate.rs
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.rs
@@ -1,5 +1,5 @@
 //@error-in-other-file: aborted execution
-//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> ""
 //@normalize-stderr-test: "\n +at [^\n]+" -> ""
diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
index 7b9a4383fc4..222d4fb2866 100644
--- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
@@ -11,7 +11,7 @@ thread caused non-unwinding panic. aborting.
 error: abnormal termination: the program aborted execution
   --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC
    |
-LL |     ABORT();
+LL | ABORT()
    | ^ the program aborted execution
    |
    = note: BACKTRACE:
diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr
deleted file mode 100644
index a437ca34258..00000000000
--- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error: Undefined Behavior: Race condition detected between (1) 4-byte atomic store on thread `unnamed-ID` and (2) 2-byte atomic load on thread `unnamed-ID` at ALLOC. (2) just happened here
-  --> tests/fail/weak_memory/racing_mixed_size.rs:LL:CC
-   |
-LL |             std::intrinsics::atomic_load_relaxed(hi);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte atomic store on thread `unnamed-ID` and (2) 2-byte atomic load on thread `unnamed-ID` at ALLOC. (2) just happened here
-   |
-help: and (1) occurred earlier here
-  --> tests/fail/weak_memory/racing_mixed_size.rs:LL:CC
-   |
-LL |         x.store(1, Relaxed);
-   |         ^^^^^^^^^^^^^^^^^^^
-   = help: overlapping unsynchronized atomic accesses must use the same access size
-   = help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model
-   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
-   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE (of the first span) on thread `unnamed-ID`:
-   = note: inside closure at tests/fail/weak_memory/racing_mixed_size.rs:LL:CC
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs b/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs
index c2b6a7e68be..c76e7f2eebd 100644
--- a/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs
+++ b/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs
@@ -12,7 +12,6 @@ fn main() {
     mut_raw_mut();
     partially_invalidate_mut();
     drop_after_sharing();
-    // direct_mut_to_const_raw();
     two_raw();
     shr_and_raw();
     disjoint_mutable_subborrows();
diff --git a/src/tools/miri/tests/pass/coroutine.rs b/src/tools/miri/tests/pass/coroutine.rs
index 9ec9b1fc5bc..96b60b515cb 100644
--- a/src/tools/miri/tests/pass/coroutine.rs
+++ b/src/tools/miri/tests/pass/coroutine.rs
@@ -183,18 +183,18 @@ fn basic() {
 
 fn smoke_resume_arg() {
     fn drain<G: Coroutine<R, Yield = Y> + Unpin, R, Y>(
-        gen: &mut G,
+        gen_: &mut G,
         inout: Vec<(R, CoroutineState<Y, G::Return>)>,
     ) where
         Y: Debug + PartialEq,
         G::Return: Debug + PartialEq,
     {
-        let mut gen = Pin::new(gen);
+        let mut gen_ = Pin::new(gen_);
 
         for (input, out) in inout {
-            assert_eq!(gen.as_mut().resume(input), out);
+            assert_eq!(gen_.as_mut().resume(input), out);
             // Test if the coroutine is valid (according to type invariants).
-            let _ = unsafe { ManuallyDrop::new(ptr::read(gen.as_mut().get_unchecked_mut())) };
+            let _ = unsafe { ManuallyDrop::new(ptr::read(gen_.as_mut().get_unchecked_mut())) };
         }
     }
 
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index c37cf15d40a..46472b51f9c 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -44,8 +44,7 @@ pub fn flagsplit(flags: &str) -> Vec<String> {
 fn build_native_lib() -> PathBuf {
     let cc = env::var("CC").unwrap_or_else(|_| "cc".into());
     // Target directory that we can write to.
-    let so_target_dir =
-        Path::new(&env::var_os("CARGO_TARGET_DIR").unwrap()).join("miri-native-lib");
+    let so_target_dir = Path::new(env!("CARGO_TARGET_TMPDIR")).join("miri-native-lib");
     // Create the directory if it does not already exist.
     std::fs::create_dir_all(&so_target_dir)
         .expect("Failed to create directory for shared object file");
@@ -101,7 +100,7 @@ fn miri_config(
     let mut config = Config {
         target: Some(target.to_owned()),
         program,
-        out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("miri_ui"),
+        out_dir: PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join("miri_ui"),
         threads: std::env::var("MIRI_TEST_THREADS")
             .ok()
             .map(|threads| NonZero::new(threads.parse().unwrap()).unwrap()),
@@ -319,10 +318,10 @@ fn main() -> Result<()> {
     let mut args = std::env::args_os();
 
     // Skip the program name and check whether this is a `./miri run-dep` invocation
-    if let Some(first) = args.nth(1) {
-        if first == "--miri-run-dep-mode" {
-            return run_dep_mode(target, args);
-        }
+    if let Some(first) = args.nth(1)
+        && first == "--miri-run-dep-mode"
+    {
+        return run_dep_mode(target, args);
     }
 
     ui(Mode::Pass, "tests/pass", &target, WithoutDependencies, tmpdir.path())?;
diff --git a/tests/run-make/core-no-oom-handling/rmake.rs b/tests/run-make/core-no-oom-handling/rmake.rs
index a9e2b33e210..5194d773114 100644
--- a/tests/run-make/core-no-oom-handling/rmake.rs
+++ b/tests/run-make/core-no-oom-handling/rmake.rs
@@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root};
 
 fn main() {
     rustc()
-        .edition("2021")
+        .edition("2024")
         .arg("-Dwarnings")
         .crate_type("rlib")
         .input(source_root().join("library/core/src/lib.rs"))
diff --git a/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs b/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs
index 2727effe818..d28c8463016 100644
--- a/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs
+++ b/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs
@@ -11,6 +11,13 @@
 //@ needs-dynamic-linking
 //@ only-nightly (requires unstable rustc flag)
 
+// This test trips a check in the MSVC linker for an outdated processor:
+// "LNK1322: cannot avoid potential ARM hazard (Cortex-A53 MPCore processor bug #843419)"
+// Until MSVC removes this check:
+// https://developercommunity.microsoft.com/t/Remove-checking-for-and-fixing-Cortex-A/10905134
+// we'll need to disable this test on Arm64 Windows.
+//@ ignore-aarch64-pc-windows-msvc
+
 #![deny(warnings)]
 
 use run_make_support::{dynamic_lib_name, rfs, rust_lib_name, rustc};
diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.rs b/tests/ui/consts/miri_unleashed/abi-mismatch.rs
index 0a2b3f3abd6..6a46079b39b 100644
--- a/tests/ui/consts/miri_unleashed/abi-mismatch.rs
+++ b/tests/ui/consts/miri_unleashed/abi-mismatch.rs
@@ -10,7 +10,7 @@ const fn call_rust_fn(my_fn: extern "Rust" fn()) {
 
 static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
 //~^ ERROR could not evaluate static initializer
-//~| NOTE calling a function with calling convention C using calling convention Rust
+//~| NOTE calling a function with calling convention "C" using calling convention "Rust"
 
 fn main() {}
 
diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.stderr b/tests/ui/consts/miri_unleashed/abi-mismatch.stderr
index 88623b134b0..7d1fdcce526 100644
--- a/tests/ui/consts/miri_unleashed/abi-mismatch.stderr
+++ b/tests/ui/consts/miri_unleashed/abi-mismatch.stderr
@@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/abi-mismatch.rs:11:18
    |
 LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with calling convention C using calling convention Rust
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with calling convention "C" using calling convention "Rust"
    |
 note: inside `call_rust_fn`
   --> $DIR/abi-mismatch.rs:7:5
diff --git a/tests/ui/coroutine/delayed-obligations-emit.next.stderr b/tests/ui/coroutine/delayed-obligations-emit.next.stderr
new file mode 100644
index 00000000000..3a3663398c9
--- /dev/null
+++ b/tests/ui/coroutine/delayed-obligations-emit.next.stderr
@@ -0,0 +1,15 @@
+error[E0275]: overflow evaluating the requirement `{async block@$DIR/delayed-obligations-emit.rs:17:11: 17:16}: Send`
+  --> $DIR/delayed-obligations-emit.rs:17:5
+   |
+LL |     spawn(async { build_dependencies().await });
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `spawn`
+  --> $DIR/delayed-obligations-emit.rs:31:13
+   |
+LL | fn spawn<F: Send>(_: F) {}
+   |             ^^^^ required by this bound in `spawn`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/coroutine/delayed-obligations-emit.rs b/tests/ui/coroutine/delayed-obligations-emit.rs
new file mode 100644
index 00000000000..6334f29fcb2
--- /dev/null
+++ b/tests/ui/coroutine/delayed-obligations-emit.rs
@@ -0,0 +1,33 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ edition: 2024
+//@[current] check-pass
+
+// This previously caused an ICE with the new solver.
+// The delayed coroutine obligations were checked with the
+// opaque types inferred by borrowck.
+//
+// One of these delayed obligations failed with overflow in
+// borrowck, causing us to taint `type_of` for the opaque. This
+// then caused us to also not emit an error when checking the
+// coroutine obligations.
+
+fn build_multiple<'a>() -> impl Sized {
+    spawn(async { build_dependencies().await });
+    //[next]~^ ERROR overflow evaluating the requirement
+}
+
+// Adding an explicit `Send` bound fixes it.
+// Proving `build_dependencies(): Send` in `build_multiple` adds
+// addiitional defining uses/placeholders.
+fn build_dependencies() -> impl Future<Output = ()> /* + Send */ {
+    async {
+        Box::pin(build_dependencies()).await;
+        async { build_multiple() }.await;
+    }
+}
+
+fn spawn<F: Send>(_: F) {}
+
+fn main() {}
diff --git a/tests/ui/imports/issue-99695-b.fixed b/tests/ui/imports/issue-99695-b.fixed
index 0108f762400..ae63b0c4627 100644
--- a/tests/ui/imports/issue-99695-b.fixed
+++ b/tests/ui/imports/issue-99695-b.fixed
@@ -11,7 +11,7 @@ mod m {
         pub struct other_item;
     }
 
-    use ::nu;
+    use crate::nu;
 pub use self::p::{other_item as _};
     //~^ ERROR unresolved import `self::p::nu` [E0432]
     //~| HELP a macro with this name exists at the root of the crate
diff --git a/tests/ui/imports/issue-99695-b.stderr b/tests/ui/imports/issue-99695-b.stderr
index d58d2798746..ad752d5c45a 100644
--- a/tests/ui/imports/issue-99695-b.stderr
+++ b/tests/ui/imports/issue-99695-b.stderr
@@ -7,7 +7,7 @@ LL |     pub use self::p::{nu, other_item as _};
    = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
 help: a macro with this name exists at the root of the crate
    |
-LL ~     use ::nu;
+LL ~     use crate::nu;
 LL ~ pub use self::p::{other_item as _};
    |
 
diff --git a/tests/ui/imports/issue-99695.fixed b/tests/ui/imports/issue-99695.edition_2015.fixed
index 51ccd3f8c48..798acfd5874 100644
--- a/tests/ui/imports/issue-99695.fixed
+++ b/tests/ui/imports/issue-99695.edition_2015.fixed
@@ -1,4 +1,8 @@
 //@ run-rustfix
+//@ revisions: edition_2015 edition_2018
+//@ [edition_2015] edition: 2015
+//@ [edition_2018] edition: 2018
+
 #![allow(unused, nonstandard_style)]
 mod m {
     #[macro_export]
@@ -8,7 +12,7 @@ mod m {
 
     pub struct other_item;
 
-    use ::nu;
+    use crate::nu;
 pub use self::{other_item as _};
     //~^ ERROR unresolved import `self::nu` [E0432]
     //~| HELP a macro with this name exists at the root of the crate
diff --git a/tests/ui/imports/issue-99695.stderr b/tests/ui/imports/issue-99695.edition_2015.stderr
index 536f51dcb3b..4ef8e6426fb 100644
--- a/tests/ui/imports/issue-99695.stderr
+++ b/tests/ui/imports/issue-99695.edition_2015.stderr
@@ -1,5 +1,5 @@
 error[E0432]: unresolved import `self::nu`
-  --> $DIR/issue-99695.rs:11:20
+  --> $DIR/issue-99695.rs:15:20
    |
 LL |     pub use self::{nu, other_item as _};
    |                    ^^ no `nu` in `m`
@@ -7,7 +7,7 @@ LL |     pub use self::{nu, other_item as _};
    = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
 help: a macro with this name exists at the root of the crate
    |
-LL ~     use ::nu;
+LL ~     use crate::nu;
 LL ~ pub use self::{other_item as _};
    |
 
diff --git a/tests/ui/imports/issue-99695.edition_2018.fixed b/tests/ui/imports/issue-99695.edition_2018.fixed
new file mode 100644
index 00000000000..798acfd5874
--- /dev/null
+++ b/tests/ui/imports/issue-99695.edition_2018.fixed
@@ -0,0 +1,21 @@
+//@ run-rustfix
+//@ revisions: edition_2015 edition_2018
+//@ [edition_2015] edition: 2015
+//@ [edition_2018] edition: 2018
+
+#![allow(unused, nonstandard_style)]
+mod m {
+    #[macro_export]
+    macro_rules! nu {
+        {} => {};
+    }
+
+    pub struct other_item;
+
+    use crate::nu;
+pub use self::{other_item as _};
+    //~^ ERROR unresolved import `self::nu` [E0432]
+    //~| HELP a macro with this name exists at the root of the crate
+}
+
+fn main() {}
diff --git a/tests/ui/imports/issue-99695.edition_2018.stderr b/tests/ui/imports/issue-99695.edition_2018.stderr
new file mode 100644
index 00000000000..4ef8e6426fb
--- /dev/null
+++ b/tests/ui/imports/issue-99695.edition_2018.stderr
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `self::nu`
+  --> $DIR/issue-99695.rs:15:20
+   |
+LL |     pub use self::{nu, other_item as _};
+   |                    ^^ no `nu` in `m`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL ~     use crate::nu;
+LL ~ pub use self::{other_item as _};
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/imports/issue-99695.rs b/tests/ui/imports/issue-99695.rs
index a52370e0eb0..dc0a8f438e0 100644
--- a/tests/ui/imports/issue-99695.rs
+++ b/tests/ui/imports/issue-99695.rs
@@ -1,4 +1,8 @@
 //@ run-rustfix
+//@ revisions: edition_2015 edition_2018
+//@ [edition_2015] edition: 2015
+//@ [edition_2018] edition: 2018
+
 #![allow(unused, nonstandard_style)]
 mod m {
     #[macro_export]
diff --git a/tests/ui/traits/object/ambiguity-vtable-segfault.rs b/tests/ui/traits/object/ambiguity-vtable-segfault.rs
new file mode 100644
index 00000000000..dff7d26ae93
--- /dev/null
+++ b/tests/ui/traits/object/ambiguity-vtable-segfault.rs
@@ -0,0 +1,37 @@
+// In this example below, we have two overlapping candidates for `dyn Q: Q`.
+// Specifically, the user written impl for `<dyn Q as Mirror>::Assoc` and the
+// built-in impl for object types. Since they differ by their region responses,
+// the goal is ambiguous. This affects codegen since impossible obligations
+// for method dispatch will lead to a segfault, since we end up emitting dummy
+// call vtable offsets due to <https://github.com/rust-lang/rust/pull/136311>.
+
+// Test for <https://github.com/rust-lang/rust/issues/141119>.
+
+//@ run-pass
+
+trait Mirror {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Mirror for T {
+    type Assoc = T;
+}
+
+trait Q: 'static {
+    fn q(&self);
+}
+
+impl Q for i32 {
+    fn q(&self) { println!("i32"); }
+}
+
+impl Q for <dyn Q as Mirror>::Assoc where Self: 'static {
+    fn q(&self) { println!("dyn Q"); }
+}
+
+fn foo<T: Q + ?Sized>(t: &T) {
+    t.q();
+}
+
+fn main() {
+    foo(&1 as &dyn Q);
+}
diff --git a/triagebot.toml b/triagebot.toml
index f566a947e0e..3afa2d36410 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1424,3 +1424,6 @@ compiletest = [
 # Enable `@rustbot note` functionality
 # Documentation at: https://forge.rust-lang.org/triagebot/note.html
 [note]
+
+[behind-upstream]
+days-threshold = 14