Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Algol68
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C with Coccinelle
C++ with Coccinelle
C++ (Circle)
CIRCT
Clean
Clojure
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
GLSL
Go
Haskell
HLSL
Helion
Hook
Hylo
IL
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Mojo
Nim
Numba
Nix
Objective-C
Objective-C++
OCaml
Odin
OpenCL C
Pascal
Pony
PTX
Python
Racket
Raku
Ruby
Rust
Sail
Snowball
Scala
Slang
Solidity
Spice
SPIR-V
Swift
LLVM TableGen
Toit
Triton
TypeScript Native
V
Vala
Visual Basic
Vyper
WASM
Yul (Solidity IR)
Zig
Javascript
GIMPLE
Ygen
sway
rust source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
mrustc (master)
rustc 1.0.0
rustc 1.1.0
rustc 1.10.0
rustc 1.11.0
rustc 1.12.0
rustc 1.13.0
rustc 1.14.0
rustc 1.15.1
rustc 1.16.0
rustc 1.17.0
rustc 1.18.0
rustc 1.19.0
rustc 1.2.0
rustc 1.20.0
rustc 1.21.0
rustc 1.22.0
rustc 1.23.0
rustc 1.24.0
rustc 1.25.0
rustc 1.26.0
rustc 1.27.0
rustc 1.27.1
rustc 1.28.0
rustc 1.29.0
rustc 1.3.0
rustc 1.30.0
rustc 1.31.0
rustc 1.32.0
rustc 1.33.0
rustc 1.34.0
rustc 1.35.0
rustc 1.36.0
rustc 1.37.0
rustc 1.38.0
rustc 1.39.0
rustc 1.4.0
rustc 1.40.0
rustc 1.41.0
rustc 1.42.0
rustc 1.43.0
rustc 1.44.0
rustc 1.45.0
rustc 1.45.2
rustc 1.46.0
rustc 1.47.0
rustc 1.48.0
rustc 1.49.0
rustc 1.5.0
rustc 1.50.0
rustc 1.51.0
rustc 1.52.0
rustc 1.53.0
rustc 1.54.0
rustc 1.55.0
rustc 1.56.0
rustc 1.57.0
rustc 1.58.0
rustc 1.59.0
rustc 1.6.0
rustc 1.60.0
rustc 1.61.0
rustc 1.62.0
rustc 1.63.0
rustc 1.64.0
rustc 1.65.0
rustc 1.66.0
rustc 1.67.0
rustc 1.68.0
rustc 1.69.0
rustc 1.7.0
rustc 1.70.0
rustc 1.71.0
rustc 1.72.0
rustc 1.73.0
rustc 1.74.0
rustc 1.75.0
rustc 1.76.0
rustc 1.77.0
rustc 1.78.0
rustc 1.79.0
rustc 1.8.0
rustc 1.80.0
rustc 1.81.0
rustc 1.82.0
rustc 1.83.0
rustc 1.84.0
rustc 1.85.0
rustc 1.86.0
rustc 1.87.0
rustc 1.88.0
rustc 1.89.0
rustc 1.9.0
rustc 1.90.0
rustc 1.91.0
rustc beta
rustc nightly
rustc-cg-gcc (master)
x86-64 GCCRS (GCC master)
x86-64 GCCRS (GCCRS master)
x86-64 GCCRS 14.1 (GCC assertions)
x86-64 GCCRS 14.1 (GCC)
x86-64 GCCRS 14.2 (GCC assertions)
x86-64 GCCRS 14.2 (GCC)
x86-64 GCCRS 14.3 (GCC assertions)
x86-64 GCCRS 14.3 (GCC)
x86-64 GCCRS 15.1 (GCC assertions)
x86-64 GCCRS 15.1 (GCC)
x86-64 GCCRS 15.2 (GCC assertions)
x86-64 GCCRS 15.2 (GCC)
Options
Source code
#![allow(unused_imports)] #![feature(ptr_sub_ptr, core_intrinsics, maybe_uninit_slice, strict_provenance)] use std::intrinsics; use std::mem::{self, ManuallyDrop, MaybeUninit}; use std::ptr; use std::cmp; struct FulcrumState<T> { r_ptr: *mut T, x_ptr: *mut T, elem_i: usize, } #[inline(always)] unsafe fn fulcrum_rotate<T, F>( arr_ptr: *mut T, state: &mut FulcrumState<T>, offset_val: isize, loop_len: usize, pivot: &T, is_less: &mut F, ) where F: FnMut(&T, &T) -> bool, { for _ in 0..loop_len { let is_l = is_less(&*state.x_ptr, pivot); let target_ptr = if is_l { arr_ptr.add(state.elem_i) } else { state.r_ptr.add(state.elem_i) }; ptr::copy(state.x_ptr, target_ptr, 1); state.elem_i += is_l as usize; state.x_ptr = state.x_ptr.wrapping_offset(offset_val); state.r_ptr = state.r_ptr.wrapping_sub(1); } } unsafe fn small_aux_partition<T, F>( v: &mut [T], swap_ptr: *mut T, pivot: &T, is_less: &mut F, ) -> usize where F: FnMut(&T, &T) -> bool, { let len = v.len(); let arr_ptr = v.as_mut_ptr(); // SAFETY: TODO unsafe { let mut swap_ptr_l = swap_ptr; let mut swap_ptr_r = swap_ptr.add(len - 1); // This could probably be sped-up by interleaving the two loops. for i in 0..len { let elem_ptr = arr_ptr.add(i); let is_l = is_less(&*elem_ptr, pivot); let target_ptr = if is_l { swap_ptr_l } else { swap_ptr_r }; ptr::copy_nonoverlapping(elem_ptr, target_ptr, 1); swap_ptr_l = swap_ptr_l.add(is_l as usize); swap_ptr_r = swap_ptr_r.sub(!is_l as usize); } // SAFETY: swap now contains all elements that belong on the left side of the pivot. All // comparisons have been done if is_less would have panicked v would have stayed untouched. // Now that swap has the correct order overwrite arr_ptr. ptr::copy_nonoverlapping(swap_ptr, arr_ptr, len); swap_ptr_l.sub_ptr(swap_ptr) } } // This function is *NOT* safe-to-use for non `Freeze` types. fn partition<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize { // Novel partition implementation by Igor van den Hoven as part of his work in quadsort and // crumsort. let len = v.len(); const ROTATION_ELEMS: usize = 32; let advance_left = |a_ptr: *const T, arr_ptr: *const T, elem_i: usize| -> bool { // SAFETY: TODO unsafe { (a_ptr.sub_ptr(arr_ptr) - elem_i) <= ROTATION_ELEMS } }; let mut swap = MaybeUninit::<[T; ROTATION_ELEMS * 2]>::uninit(); let swap_ptr = swap.as_mut_ptr() as *mut T; let arr_ptr = v.as_mut_ptr(); // SAFETY: TODO unsafe { if len <= (ROTATION_ELEMS * 2) { return small_aux_partition(v, swap_ptr, pivot, is_less); } } // SAFETY: TODO unsafe { ptr::copy_nonoverlapping(arr_ptr, swap_ptr, ROTATION_ELEMS); ptr::copy_nonoverlapping( arr_ptr.add(len - ROTATION_ELEMS), swap_ptr.add(ROTATION_ELEMS), ROTATION_ELEMS, ); let mut state = FulcrumState { r_ptr: arr_ptr.add(len - 1), x_ptr: ptr::null_mut(), elem_i: 0, }; let mut a_ptr = arr_ptr.add(ROTATION_ELEMS); let mut t_ptr = arr_ptr.add(len - (ROTATION_ELEMS + 1)); for _ in 0..((len / ROTATION_ELEMS) - 2) { let loop_len = ROTATION_ELEMS; if advance_left(a_ptr, arr_ptr, state.elem_i) { state.x_ptr = a_ptr; fulcrum_rotate(arr_ptr, &mut state, 1, loop_len, pivot, is_less); a_ptr = state.x_ptr; } else { state.x_ptr = t_ptr; fulcrum_rotate(arr_ptr, &mut state, -1, loop_len, pivot, is_less); t_ptr = state.x_ptr; } } let loop_len = len % ROTATION_ELEMS; if advance_left(a_ptr, arr_ptr, state.elem_i) { state.x_ptr = a_ptr; fulcrum_rotate(arr_ptr, &mut state, 1, loop_len, pivot, is_less); } else { state.x_ptr = t_ptr; fulcrum_rotate(arr_ptr, &mut state, -1, loop_len, pivot, is_less); } let loop_len = ROTATION_ELEMS * 2; state.x_ptr = swap_ptr; fulcrum_rotate(arr_ptr, &mut state, 1, loop_len, pivot, is_less); state.elem_i } } type TestT = u64; pub fn xx(v: &mut [TestT], pivot: &TestT) -> usize { partition(v, pivot, &mut |a, b| a.lt(b)) }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Compiler Explorer Shop
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
CE on Bluesky
Statistics
Changelog
Version tree