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}