Skip to main content

a/sort/
shell.rs

1use core::hint::select_unpredictable;
2use core::mem::{self, ManuallyDrop, MaybeUninit};
3use core::ops::Range;
4use core::ptr;
5
6/// Sorts a slice in place using Shell sort.
7///
8/// Shell sort, published by Donald Shell in 1959, is insertion sort with a gap. A pass with
9/// gap `h` insertion sorts every chain of elements `h` apart, `v[c], v[c + h], v[c + 2h], ...`,
10/// so an element far from its place travels there in steps of `h` instead of one slot at a
11/// time. The passes use a decreasing sequence of gaps ending with 1, a plain insertion sort,
12/// which the earlier passes leave with little to do. How fast the sort is depends almost
13/// entirely on the gap sequence: with the ones used here it makes about `1.6–2·n·log₂ n`
14/// comparisons on random input of up to a million elements, though no gap sequence is known
15/// to make Shell sort `O(n log n)`.
16///
17/// Five refinements keep the algorithm as cheap as Shell sort can be:
18///
19/// * **Sorted and reverse-sorted input is recognised.** The slice is first scanned for one
20///   ascending or strictly descending run; if it covers the whole slice, the slice is left
21///   alone or reversed. This costs `n − 1` comparisons on such input and usually two or three
22///   on any other.
23/// * **Hole shifting.** An element is read out once, the greater elements before it on its
24///   chain shift one place along the chain each, and it is written once into the slot left
25///   free: one move per step instead of the three of a swap.
26/// * **The gaps that are fastest, not the fewest comparisons.** Ciura's sequence (`1, 4, 10,
27///   23, 57, 132, 301, 701`, then times 2.25) makes the fewest comparisons of the sequences
28///   tried, 1.1–1.27 times fewer than Sedgewick's 1982 one (`1, 8, 23, 77, 281, 1073, ...`).
29///   But every pass ends nearly every insertion with a mispredicted branch, and Sedgewick's
30///   gaps grow by a factor of about 4 instead of 2.25, so they take fewer passes: for elements
31///   larger than 8 bytes they are 1.05–1.35 times faster, strings included (except random
32///   strings from a million elements on, 1.1 times slower, where each comparison is a cache
33///   miss). Elements of at most 8 bytes use Ciura's gaps, which suit the window below.
34/// * **A branchless window for small elements.** In a pass over a slice that is still far from
35///   sorted, how far an element moves along its chain is about as hard to predict as a coin
36///   toss: with Ciura's gaps, 0 steps 44% of the time, 1 step 26%, 2 steps 14%, 3 steps 8%
37///   and 4 or more 8%. For elements of at most 8 bytes, each element is compared with the 4
38///   elements before it on its chain at once, how many of them it passes is computed as a
39///   number, and the 4 slots it can move into are rewritten from copies held in registers,
40///   each chosen by two selects on that number: no branch, at the cost of comparisons that
41///   turn out unnecessary. Only the 8% of elements that pass all 4 go on with a branch per
42///   step. On random input this is 1.65–1.9 times faster for integers.
43/// * **The window only where it pays, judged by the insertions themselves.** Where the slice
44///   is nearly sorted or its order follows a pattern, insertion's branches are predictable and
45///   the window's extra comparisons and writes are wasted: a pass can be up to 5 times slower
46///   with it. How many elements move does not tell the two apart (sawtooth input moves as
47///   many as random input), but how regularly they move does. So a pass is made in blocks of
48///   512 elements, and each block counts, at no measurable cost, how predictable its insertions
49///   were and chooses the window for the next block only if they were not. Inserted plainly,
50///   it counts the runs of consecutive elements that moved and the steps they took beyond the
51///   first, and takes `2·runs + 0.35·steps > 0.42` per element as unpredictable; through the
52///   window, it counts how often the number of elements passed differs from the one before,
53///   and takes more than `0.42` per element as unpredictable. As branch predictors also learn
54///   short patterns, the last 32 elements of each block note their steps too, and a block whose
55///   steps repeat with a period of at most 16 is followed by plain insertion. The first pass
56///   assumes the window pays, and the final pass, with gap 1, never takes it, since each
57///   element there depends on the one just placed. Against taking the window whenever the
58///   pass before moved more than a quarter of the elements, this is 1.2–1.85 times faster on
59///   sawtooth input of 1000 to a million integers with periods from 4 to `n/8` (but a period
60///   of `√n` from 100,000 elements on, as fast to 1.1 times slower), 2.1–2.45 times on
61///   organ-pipe input, 1.05–1.15 times on nearly sorted input, 1.05–1.25 times with 4 distinct
62///   keys, and as fast on random input (within 3%; sorted runs of about `√n` random elements,
63///   which only the old count read right, are 1.03–1.25 times slower below 10,000 elements).
64///
65/// # Properties
66///
67/// * **Unstable**: equal elements may be reordered (an insertion along a chain can carry an
68///   element past an equal one that lies between the two in the slice).
69/// * **In place**: `O(1)` auxiliary memory, no allocation.
70/// * **Adaptive**: the passes do less on nearly sorted input, and sorted or reverse-sorted
71///   input costs one scan.
72///
73/// | Case                              | Comparisons                    | Moves                  |
74/// |-----------------------------------|--------------------------------|------------------------|
75/// | Best (sorted, reverse, all equal) | `n − 1`                        | `0` (`n` reversed)     |
76/// | Average, Sedgewick's gaps         | `≈ (1.6–2)·n·log₂ n`           | `O(comparisons)`       |
77/// | Average, Ciura's gaps and window  | `≈ (2.1–2.8)·n·log₂ n`         | `O(comparisons)`       |
78/// | Worst                             | `O(n^(4/3))`, Sedgewick's gaps | the same               |
79///
80/// No bound is known for Ciura's gaps, which were found by experiment.
81///
82/// For `n = 1000`: 999 comparisons on sorted or reverse-sorted input and about 15,900 on random
83/// input, or 21,300 with the window, whose unnecessary comparisons are cheap for small
84/// elements; heap sort makes about 10,500.
85///
86/// Against classic Shell sort with Ciura's gaps, plain insertion and the same scan for a run,
87/// this is 1.65–1.9 times faster on random integers from 1000 elements on, up to 1.75 times on
88/// nearly sorted ones, 1.3–1.4 times with few distinct keys and 1.1–1.2 times on organ-pipe
89/// input; on sawtooth input of 1000–100,000 integers with periods from 4 to `n/8` it ranges
90/// from 1.15 times slower (a period of 16 at 1000 elements, which the branch predictor learns
91/// from history the window cannot see) to 1.35 times faster, mostly within 1.1 times either
92/// way; 1.05–1.4 times faster on strings except random ones from a million elements on, and
93/// 1.03–1.3 times on 64-byte elements. Against this crate's [`comb`](crate::sort::comb) sort,
94/// whose fixed compare-exchanges the compiler vectorizes for integers: 3.55–4 times slower on
95/// random integers from 1000 elements on and 1.8–2.65 times on nearly sorted ones or with few
96/// distinct keys (1.15 times faster on 100 nearly sorted ones), but 1.1–2.5 times faster on
97/// strings that have few distinct keys or follow a pattern, and 1.6 times on 1000 nearly
98/// sorted strings (as fast on longer ones).
99/// Against [`heap`](crate::sort::heap) sort: 1.45–1.8 times slower on random integers from
100/// 1000 elements on, 1.1–1.6 times on nearly sorted ones and 1.1–1.25 times with few distinct
101/// keys, about as fast on random strings, and faster on strings that are nearly sorted or
102/// patterned.
103///
104/// Shell sort is mainly of educational value; prefer [`slice::sort_unstable`] for real
105/// workloads.
106///
107/// # Panics
108///
109/// Does not panic by itself. If the [`Ord`] implementation of `T` panics, the panic is
110/// propagated and `arr` is left in an unspecified order, but it still holds every original
111/// element exactly once: nothing is dropped twice or leaked. An [`Ord`] that is not a total
112/// order leaves `arr` in an unspecified order with every element exactly once as well.
113///
114/// # Examples
115///
116/// ```
117/// use a::sort::shell;
118///
119/// let mut v = [5, 1, 4, 2, 8, 0, 3, 9, 7, 6];
120/// shell(&mut v);
121/// assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
122///
123/// // Small elements far from their place travel in long steps.
124/// let mut v: Vec<u32> = (0..1000).rev().chain(1000..2000).collect();
125/// v.swap(0, 1999);
126/// shell(&mut v);
127/// assert!(v.windows(2).all(|w| w[0] <= w[1]));
128///
129/// let mut words = vec!["pear", "apple", "fig"];
130/// shell(&mut words);
131/// assert_eq!(words, ["apple", "fig", "pear"]);
132/// ```
133pub fn shell<T: Ord>(arr: &mut [T]) {
134    let len = arr.len();
135    if len < 2 {
136        return;
137    }
138    // An ascending run stops at the first descent; a strictly descending one at the first
139    // element that is not smaller, so reversing it is all it takes.
140    let descending = arr[1] < arr[0];
141    let run = 2 + if descending {
142        arr[1..].windows(2).take_while(|w| w[1] < w[0]).count()
143    } else {
144        arr[1..].windows(2).take_while(|w| w[1] >= w[0]).count()
145    };
146    if run == len {
147        if descending {
148            arr.reverse();
149        }
150        return;
151    }
152
153    let mut gaps = [0; MAX_GAPS];
154    if mem::size_of::<T>() <= WINDOW_MAX_SIZE {
155        let count = ciura_gaps(len, &mut gaps);
156        // Whether the elements inserted last were hard to predict, so that the next ones had
157        // better go through the window; the first pass assumes they were.
158        let mut window = true;
159        for &gap in gaps[..count].iter().rev() {
160            if gap > 1 {
161                window = pass_choosing(arr, gap, window);
162            } else {
163                insert(arr, 1, 1..len, &mut ());
164            }
165        }
166    } else {
167        let count = sedgewick_gaps(len, &mut gaps);
168        for &gap in gaps[..count].iter().rev() {
169            insert(arr, gap, gap..len, &mut ());
170        }
171    }
172}
173
174/// Room for the gaps of any slice: both sequences grow by a factor of at least 2.25.
175const MAX_GAPS: usize = 64;
176
177/// The largest element size, in bytes, for which passes may insert through a window
178/// ([`insert_window`]) and the gaps are Ciura's; larger elements use Sedgewick's gaps and
179/// plain insertion only.
180///
181/// Measured on random input: integers sort 1.65–1.9 times faster with the window, and `u128`
182/// 1.15–1.4 times; but `&str` and `String`, as small as a `u128` and slower to compare, sort
183/// 1.1–1.45 times slower with it on input with few distinct keys or in a sawtooth pattern;
184/// 32-byte elements gain on random input but lose up to 1.75 times elsewhere, and 64-byte
185/// ones lose on all input.
186const WINDOW_MAX_SIZE: usize = 8;
187
188/// How many steps [`insert_window`] takes without branching.
189///
190/// Measured against 3 and 6: 1.05–1.1 times faster than 3 on random input from 100,000
191/// elements on, and up to 1.1 times slower around 1000 elements; 6 is slower on all input.
192const WINDOW: usize = 4;
193
194/// How many elements [`pass_choosing`] inserts the same way before it chooses again.
195///
196/// Measured against 256 and 1024: within 2% of either on random input; 256 is up to 1.1
197/// times slower on sawtooth input, whose blocks then differ more from one to the next.
198const BLOCK: usize = 512;
199
200/// How many elements of the head of a pass, where the window cannot reach, it takes to
201/// choose from them: fewer, and the choice made at the end of the pass before stands.
202const SAMPLE: usize = 128;
203
204/// How many elements at the end of each block note their steps for [`History::periodic`].
205const HISTORY: usize = 32;
206
207/// Writes the gaps below `n` of Ciura's sequence, `1, 4, 10, 23, 57, 132, 301, 701`, extended
208/// by multiplying by 2.25 and rounding down, into `gaps` in increasing order, and returns how
209/// many there are. Found by experiment to make about the fewest comparisons of any sequence.
210fn ciura_gaps(n: usize, gaps: &mut [usize; MAX_GAPS]) -> usize {
211    const CIURA: [usize; 8] = [1, 4, 10, 23, 57, 132, 301, 701];
212    let mut count = 0;
213    let mut gap = 1;
214    while gap < n {
215        gaps[count] = gap;
216        count += 1;
217        gap = match CIURA.get(count) {
218            Some(&next) => next,
219            // `⌊2.25·gap⌋`; past `usize::MAX`, the gap is too large for any slice.
220            None => gap.checked_mul(9).map_or(usize::MAX, |g| g / 4),
221        };
222    }
223    count
224}
225
226/// Writes the gaps below `n` of Sedgewick's 1982 sequence, `1` and `4^k + 3·2^(k−1) + 1`
227/// (`8, 23, 77, 281, 1073, ...`), into `gaps` in increasing order, and returns how many there
228/// are. Its gaps grow by a factor of about 4, so it takes fewer passes than Ciura's.
229fn sedgewick_gaps(n: usize, gaps: &mut [usize; MAX_GAPS]) -> usize {
230    let mut count = 0;
231    let mut gap = 1;
232    let mut k = 0u32;
233    while gap < n {
234        gaps[count] = gap;
235        count += 1;
236        k += 1;
237        // Past `usize::MAX`, the gap is too large for any slice.
238        gap = 4usize
239            .checked_pow(k)
240            .and_then(|p| p.checked_add(3 << (k - 1)))
241            .map_or(usize::MAX, |g| g.saturating_add(1));
242    }
243    count
244}
245
246/// Makes the pass with gap `gap > 1` over a slice of small elements in blocks of [`BLOCK`]
247/// elements, each inserted plainly or through the window, whichever the block before it found
248/// to pay; `window` is the choice the pass before ended with. Returns the choice this pass
249/// ends with.
250///
251/// Plain insertion is fast when its branches are predictable, and the window when they are
252/// not, so a block chooses the window for the next one if its own insertions were hard to
253/// predict. Inserted plainly, a block counts the runs of consecutive elements that moved and
254/// the steps they took beyond the first: a branch predictor guesses well inside runs, and
255/// each extra step is another branch that ends the insertion somewhere. Through the window it
256/// counts how often the number of places an element passes differs from the one before it.
257/// Each count is free: the first two are kept on the path of elements that move only, the
258/// third replaces a count the window kept before. And as a branch predictor also learns short
259/// patterns, the last [`HISTORY`] elements of the block note how far each moved, and a block
260/// whose steps repeat with a short period ([`History::periodic`]) chooses plain insertion.
261fn pass_choosing<T: Ord>(v: &mut [T], gap: usize, mut window: bool) -> bool {
262    let len = v.len();
263    // The window reaches back `WINDOW` places along the chain, so the elements before `head`
264    // are inserted plainly.
265    let head = WINDOW.saturating_mul(gap).min(len);
266    let mut start = gap;
267    while start < head {
268        let end = start + (head - start).min(BLOCK);
269        let mut runs = Runs::new(start);
270        insert(v, gap, start..end, &mut runs);
271        if end - start >= SAMPLE {
272            window = runs.unpredictable(gap, end - start);
273        }
274        start = end;
275    }
276    while start < len {
277        let end = start + (len - start).min(BLOCK);
278        // The last `HISTORY` elements note their steps, unless the block is short.
279        let split = if end - start >= 2 * HISTORY {
280            end - HISTORY
281        } else {
282            end
283        };
284        let unpredictable = if window {
285            let mut changes = Changes::default();
286            insert_window(v, gap, start..split, &mut changes);
287            changes.unpredictable(split - start)
288        } else {
289            let mut runs = Runs::new(start);
290            insert(v, gap, start..split, &mut runs);
291            runs.unpredictable(gap, split - start)
292        };
293        if split < end {
294            let mut history = History::default();
295            if window {
296                insert_window(v, gap, split..end, &mut history);
297            } else {
298                insert(v, gap, split..end, &mut history);
299            }
300            window = unpredictable && !history.periodic();
301        } else {
302            window = unpredictable;
303        }
304        start = end;
305    }
306    window
307}
308
309/// What an insertion pass notes about the elements it inserts.
310trait Tally {
311    /// Plain insertion left the element where it was.
312    #[inline(always)]
313    fn stayed(&mut self) {}
314
315    /// Plain insertion carried element `i` back along its chain to `j < i`.
316    #[inline(always)]
317    fn moved(&mut self, i: usize, j: usize, gap: usize) {
318        let _ = (i, j, gap);
319    }
320
321    /// The window found that element passed `k` of the [`WINDOW`] elements before it on its
322    /// chain (all of them if `k == WINDOW`, after which it went on).
323    #[inline(always)]
324    fn passed(&mut self, k: usize) {
325        let _ = k;
326    }
327}
328
329/// Notes nothing.
330impl Tally for () {}
331
332/// The runs of consecutive elements that plain insertion moved, and the steps they took
333/// beyond the first.
334struct Runs {
335    runs: usize,
336    /// The extra steps times the gap: `i - gap - j` summed, wrapping rather than overflowing
337    /// for slices of zero-sized elements longer than memory could hold.
338    extra: u64,
339    /// The last element that moved, or one at least two before the first of the block.
340    last: usize,
341}
342
343impl Runs {
344    fn new(start: usize) -> Self {
345        Runs {
346            runs: 0,
347            extra: 0,
348            last: start.wrapping_sub(2),
349        }
350    }
351
352    /// Whether `2·runs + 0.35·extra steps > 0.42·n` for the `n` elements counted: the next
353    /// elements had better go through the window.
354    ///
355    /// Fitted to the time of each pass in either way, for integers of 100 to a million
356    /// elements in 13 patterns: 1.03 times the time of the faster way of each pass on
357    /// average, against 1.25 times for choosing the window when a quarter of the elements of
358    /// the pass before moved.
359    fn unpredictable(&self, gap: usize, n: usize) -> bool {
360        let extra = self.extra / gap as u64;
361        let score = (200 * self.runs as u64).saturating_add(extra.saturating_mul(35));
362        score > 42 * n as u64
363    }
364}
365
366impl Tally for Runs {
367    #[inline(always)]
368    fn moved(&mut self, i: usize, j: usize, gap: usize) {
369        self.runs += usize::from(self.last.wrapping_add(1) != i);
370        self.last = i;
371        self.extra = self.extra.wrapping_add((i - gap - j) as u64);
372    }
373}
374
375/// How often the number of elements the window found an element passed differs from the
376/// one before it.
377#[derive(Default)]
378struct Changes {
379    changes: usize,
380    last: usize,
381}
382
383impl Changes {
384    /// Whether the number changed for more than `0.42` of the `n` elements counted: the next
385    /// elements had better go through the window too.
386    fn unpredictable(&self, n: usize) -> bool {
387        100 * self.changes > 42 * n
388    }
389}
390
391impl Tally for Changes {
392    #[inline(always)]
393    fn passed(&mut self, k: usize) {
394        self.changes += usize::from(k != self.last);
395        self.last = k;
396    }
397}
398
399/// The steps of the last 32 elements inserted, 0 to 3 (or more) in 2 bits each, the latest
400/// in the lowest bits.
401#[derive(Default)]
402struct History(u64);
403
404impl History {
405    /// Whether the steps repeat with a period of at most 16 elements, but for one in 16
406    /// mismatches: a pattern a branch predictor learns, so the next elements had better be
407    /// inserted plainly however often the steps change. Sawtooth input with a period of 4
408    /// sorts up to 1.25 times faster with this, and random input as fast.
409    fn periodic(&self) -> bool {
410        const LOW: u64 = 0x5555_5555_5555_5555;
411        let steps = self.0;
412        (1..=16u32).any(|lag| {
413            let differ = steps ^ (steps >> (2 * lag));
414            // One bit per pair of steps `lag` apart that differ, for the `32 - lag` pairs.
415            let mismatches = (differ | (differ >> 1)) & LOW & (u64::MAX >> (2 * lag));
416            mismatches.count_ones() * 16 <= 32 - lag
417        })
418    }
419}
420
421impl Tally for History {
422    #[inline(always)]
423    fn stayed(&mut self) {
424        self.0 <<= 2;
425    }
426
427    #[inline(always)]
428    fn moved(&mut self, i: usize, j: usize, gap: usize) {
429        let distance = i - j;
430        let steps = 1 + u64::from(distance > gap) + u64::from(distance > 2 * gap);
431        self.0 = (self.0 << 2) | steps;
432    }
433
434    #[inline(always)]
435    fn passed(&mut self, k: usize) {
436        self.0 = (self.0 << 2) | k.min(3) as u64;
437    }
438}
439
440/// Inserts each element of `range` into the chain `v[i - gap], v[i - 2·gap], ...` before
441/// it: the element is carried back past the greater elements before it, which shift one
442/// place down the chain, and `tally` notes where it went.
443///
444/// # Panics
445///
446/// If `range` does not lie within `gap..v.len()`.
447#[inline(always)]
448fn insert<T: Ord, N: Tally>(v: &mut [T], gap: usize, range: Range<usize>, tally: &mut N) {
449    assert!(gap <= range.start && range.end <= v.len());
450    let base = v.as_mut_ptr();
451    for i in range {
452        // SAFETY: `gap <= i < len`, so both elements are inside `v`.
453        if unsafe { *base.add(i) >= *base.add(i - gap) } {
454            tally.stayed();
455            continue;
456        }
457        // SAFETY: every offset is `i - m·gap >= 0` for some `m`, inside `v`. The element is
458        // read out, and `hole.dst` is always the one vacant slot: each step shifts the chain
459        // element before it into it. If a comparison panics, dropping `hole` writes the
460        // element into the vacant slot, so `v` holds every element exactly once.
461        let j = unsafe {
462            let x = ManuallyDrop::new(ptr::read(base.add(i)));
463            ptr::copy_nonoverlapping(base.add(i - gap), base.add(i), 1);
464            let mut hole = Hole {
465                src: &*x,
466                dst: base.add(i - gap),
467            };
468            let mut j = i - gap;
469            while j >= gap && *x < *base.add(j - gap) {
470                ptr::copy_nonoverlapping(base.add(j - gap), base.add(j), 1);
471                j -= gap;
472                hole.dst = base.add(j);
473            }
474            // Dropping `hole` writes the element into the vacant slot.
475            j
476        };
477        tally.moved(i, j, gap);
478    }
479}
480
481/// Like [`insert`], but takes the first [`WINDOW`] steps of each insertion without
482/// branching, and `tally` notes how many of them each element took.
483///
484/// Each element is compared with the `WINDOW` elements before it on its chain, and `k`, the
485/// number of those (counted from the nearest, up to the first that is not greater) it moves
486/// past, is computed as a number. Then each of those `WINDOW` slots is rewritten from a copy
487/// chosen by two selects on `k`: the slot `m` places back takes the element `m + 1` places
488/// back if `m < k`, the element itself if `m == k`, and its own element otherwise. Only
489/// an element that moves past all `WINDOW` goes on along its chain with a branch per step.
490///
491/// The comparisons beyond the first that fails are made for nothing, but in a pass of a
492/// partly sorted slice how far an element moves is about as hard to predict as a coin toss,
493/// and each misprediction costs more than several comparisons of small elements.
494///
495/// # Panics
496///
497/// If `range` does not lie within `WINDOW·gap..v.len()`.
498#[inline(always)]
499fn insert_window<T: Ord, N: Tally>(v: &mut [T], gap: usize, range: Range<usize>, tally: &mut N) {
500    assert!(WINDOW.saturating_mul(gap) <= range.start && range.end <= v.len());
501    let base = v.as_mut_ptr();
502    for i in range {
503        // SAFETY: `i >= WINDOW·gap`, so every `i - m·gap` with `m <= WINDOW` is inside `v`.
504        // The elements of the window are copied out bit for bit into `window` before any is
505        // compared or written: `window[0]` is the element being inserted, `window[m]` the one
506        // `m` places back. A panicking comparison therefore leaves `v` untouched. The writes
507        // that follow cannot panic, and whatever `Ord` answered, `k <= WINDOW` and they place
508        // `window[0..=k]` into the slots `0..=k` places back in a rotated order and leave the
509        // others as they were: a permutation of the window, except when `k == WINDOW`, where
510        // the slot `WINDOW` places back is left vacant for the rest of the insertion, which
511        // is `insert`'s loop with its hole.
512        unsafe {
513            let slot = |m: usize| base.add(i - m * gap);
514            let mut window: [MaybeUninit<T>; WINDOW + 1] =
515                [const { MaybeUninit::uninit() }; WINDOW + 1];
516            for (m, copy) in window.iter_mut().enumerate() {
517                ptr::copy_nonoverlapping(slot(m), copy.as_mut_ptr(), 1);
518            }
519            let x = window[0].as_ptr();
520            let mut k = 0;
521            let mut before = 1;
522            for copy in &window[1..] {
523                before &= usize::from(*x < *copy.as_ptr());
524                k += before;
525            }
526            tally.passed(k);
527            for m in 0..WINDOW {
528                // The slot `m` places back takes the element `m + 1` places back if `m < k`,
529                // the element itself if `m == k`, and keeps its own otherwise: two selects of
530                // copies held in registers. Loading the copy from `window` at an index
531                // computed from `k`, which keeps the compiler from branching just as well,
532                // goes through memory and was 1.05–1.18 times slower.
533                let own =
534                    select_unpredictable(m == k, ptr::read(&window[0]), ptr::read(&window[m]));
535                let value = select_unpredictable(m < k, ptr::read(&window[m + 1]), own);
536                slot(m).cast::<MaybeUninit<T>>().write(value);
537            }
538            if k == WINDOW {
539                let mut hole = Hole {
540                    src: x,
541                    dst: slot(WINDOW),
542                };
543                let mut j = i - WINDOW * gap;
544                while j >= gap && *x < *base.add(j - gap) {
545                    ptr::copy_nonoverlapping(base.add(j - gap), base.add(j), 1);
546                    j -= gap;
547                    hole.dst = base.add(j);
548                }
549                // Dropping `hole` writes the element into the vacant slot.
550            }
551        }
552    }
553}
554
555/// An element held outside a slice and the vacant slot it belongs in: dropping it, when the
556/// insertion is done or a comparison panics, writes the element there.
557struct Hole<T> {
558    src: *const T,
559    dst: *mut T,
560}
561
562impl<T> Drop for Hole<T> {
563    fn drop(&mut self) {
564        // SAFETY: `dst` is the vacant slot of the slice, and `src` the element read out of it.
565        unsafe { ptr::copy_nonoverlapping(self.src, self.dst, 1) }
566    }
567}