1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
use ;
use ptr;
/// Sorts a slice in place using Shell sort.
///
/// Shell sort, published by Donald Shell in 1959, is insertion sort with a gap. A pass with
/// gap `h` insertion sorts every chain of elements `h` apart, `v[c], v[c + h], v[c + 2h], ...`,
/// so an element far from its place travels there in steps of `h` instead of one slot at a
/// time. The passes use a decreasing sequence of gaps ending with 1, a plain insertion sort,
/// which the earlier passes leave with little to do. How fast the sort is depends almost
/// entirely on the gap sequence: with the ones used here it makes about `1.6–2·n·log₂ n`
/// comparisons on random input of up to a million elements, though no gap sequence is known
/// to make Shell sort `O(n log n)`.
///
/// Five refinements keep the algorithm as cheap as Shell sort can be:
///
/// * **Sorted and reverse-sorted input is recognised.** The slice is first scanned for one
/// ascending or strictly descending run; if it covers the whole slice, the slice is left
/// alone or reversed. This costs `n − 1` comparisons on such input and usually two or three
/// on any other.
/// * **Hole shifting.** An element is read out once, the greater elements before it on its
/// chain shift one place along the chain each, and it is written once into the slot left
/// free: one move per step instead of the three of a swap.
/// * **The gaps that are fastest, not the fewest comparisons.** Ciura's sequence (`1, 4, 10,
/// 23, 57, 132, 301, 701`, then times 2.25) makes the fewest comparisons of the sequences
/// tried, 1.1–1.27 times fewer than Sedgewick's 1982 one (`1, 8, 23, 77, 281, 1073, ...`).
/// But every pass ends nearly every insertion with a mispredicted branch, and Sedgewick's
/// gaps grow by a factor of about 4 instead of 2.25, so they take fewer passes: for elements
/// larger than 8 bytes they are 1.05–1.35 times faster, strings included (except random
/// strings from a million elements on, 1.1 times slower, where each comparison is a cache
/// miss). Elements of at most 8 bytes use Ciura's gaps, which suit the window below.
/// * **A branchless window for small elements.** In a pass over a slice that is still far from
/// sorted, how far an element moves along its chain is about as hard to predict as a coin
/// toss: with Ciura's gaps, 0 steps 44% of the time, 1 step 26%, 2 steps 14%, 3 steps 8%
/// and 4 or more 8%. For elements of at most 8 bytes, each element is compared with the 4
/// elements before it on its chain at once, how many of them it passes is computed as a
/// number, and the 5 slots are rewritten from copies chosen by an index computed from that
/// number: no branch, at the cost of comparisons that turn out unnecessary. Only the 8% of
/// elements that pass all 4 go on with a branch per step. On random input this is 1.4–1.8
/// times faster for integers.
/// * **The window only while it pays.** On a slice that is nearly sorted, insertion's branches
/// are predictable and the window's extra comparisons and writes are wasted: up to 2.6 times
/// slower. So a pass takes the window only if the pass before it moved more than a quarter
/// of the elements; the first pass assumes it did, and the final pass, with gap 1, never
/// does, since each element there depends on the one just placed.
///
/// # Properties
///
/// * **Unstable**: equal elements may be reordered (an insertion along a chain can carry an
/// element past an equal one that lies between the two in the slice).
/// * **In place**: `O(1)` auxiliary memory, no allocation.
/// * **Adaptive**: the passes do less on nearly sorted input, and sorted or reverse-sorted
/// input costs one scan.
///
/// | Case | Comparisons | Moves |
/// |-----------------------------------|--------------------------------|------------------------|
/// | Best (sorted, reverse, all equal) | `n − 1` | `0` (`n` reversed) |
/// | Average, Sedgewick's gaps | `≈ (1.6–2)·n·log₂ n` | `O(comparisons)` |
/// | Average, Ciura's gaps and window | `≈ (2.1–2.8)·n·log₂ n` | `O(comparisons)` |
/// | Worst | `O(n^(4/3))`, Sedgewick's gaps | the same |
///
/// No bound is known for Ciura's gaps, which were found by experiment.
///
/// For `n = 1000`: 999 comparisons on sorted or reverse-sorted input and about 15,900 on random
/// input, or 21,300 with the window, whose unnecessary comparisons are cheap for small
/// elements; heap sort makes about 10,500.
///
/// Against classic Shell sort with Ciura's gaps, plain insertion and the same scan for a run,
/// this is 1.2–1.75 times faster on random integers, 1.1–1.65 times on nearly sorted ones and
/// 1.15–1.3 times with few distinct keys; 1.05–1.4 times faster on strings except random ones
/// from a million elements on, and 1.03–1.3 times on 64-byte elements. Against this crate's
/// [`comb`](crate::sort::comb) sort, whose fixed compare-exchanges the compiler vectorizes for
/// integers: 2.4–3.3 times slower on random integers from 1000 elements on, but faster on
/// nearly sorted input and with few distinct keys up to 1000 elements, and 1.3–2.5 times
/// faster on strings that are nearly sorted, have few distinct keys or follow a pattern.
/// Against [`heap`](crate::sort::heap) sort: 1.3–1.7 times slower on random integers from
/// 1000 elements on, about as fast on random strings, and faster on everything nearly
/// sorted or patterned.
///
/// Shell sort is mainly of educational value; prefer [`slice::sort_unstable`] for real
/// workloads.
///
/// # Panics
///
/// Does not panic by itself. If the [`Ord`] implementation of `T` panics, the panic is
/// propagated and `arr` is left in an unspecified order, but it still holds every original
/// element exactly once: nothing is dropped twice or leaked. An [`Ord`] that is not a total
/// order leaves `arr` in an unspecified order with every element exactly once as well.
///
/// # Examples
///
/// ```
/// use a::sort::shell;
///
/// let mut v = [5, 1, 4, 2, 8, 0, 3, 9, 7, 6];
/// shell(&mut v);
/// assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
///
/// // Small elements far from their place travel in long steps.
/// let mut v: Vec<u32> = (0..1000).rev().chain(1000..2000).collect();
/// v.swap(0, 1999);
/// shell(&mut v);
/// assert!(v.windows(2).all(|w| w[0] <= w[1]));
///
/// let mut words = vec!["pear", "apple", "fig"];
/// shell(&mut words);
/// assert_eq!(words, ["apple", "fig", "pear"]);
/// ```
/// Room for the gaps of any slice: both sequences grow by a factor of at least 2.25.
const MAX_GAPS: usize = 64;
/// The largest element size, in bytes, for which passes may insert through a window
/// ([`pass_window`]) and the gaps are Ciura's; larger elements use Sedgewick's gaps and plain
/// insertion only.
///
/// Measured on random input: integers sort 1.4–1.8 times faster with the window, and `u128`
/// 1.15–1.4 times; but `&str` and `String`, as small as a `u128` and slower to compare, sort
/// 1.1–1.45 times slower with it on input with few distinct keys or in a sawtooth pattern;
/// 32-byte elements gain on random input but lose up to 1.75 times elsewhere, and 64-byte
/// ones lose on all input.
const WINDOW_MAX_SIZE: usize = 8;
/// How many steps [`pass_window`] takes without branching.
///
/// Measured against 3 and 6: 1.05–1.1 times faster than 3 on random input from 100,000
/// elements on, and up to 1.1 times slower around 1000 elements; 6 is slower on all input.
const WINDOW: usize = 4;
/// The next pass inserts through a window if this pass moved more than `1 / BUSY` of the
/// elements, and plainly otherwise.
///
/// Measured against 2 and 8: within 3% of 8, and 1.05–1.2 times faster than 2.
const BUSY: usize = 4;
/// Writes the gaps below `n` of Ciura's sequence, `1, 4, 10, 23, 57, 132, 301, 701`, extended
/// by multiplying by 2.25 and rounding down, into `gaps` in increasing order, and returns how
/// many there are. Found by experiment to make about the fewest comparisons of any sequence.
/// Writes the gaps below `n` of Sedgewick's 1982 sequence, `1` and `4^k + 3·2^(k−1) + 1`
/// (`8, 23, 77, 281, 1073, ...`), into `gaps` in increasing order, and returns how many there
/// are. Its gaps grow by a factor of about 4, so it takes fewer passes than Ciura's.
/// Sorts each chain `v[c], v[c + gap], v[c + 2·gap], ...` by insertion: each element is
/// carried back along its chain past the greater elements before it, which shift one place
/// down the chain. Returns how many elements moved.
/// Like [`pass`], but takes the first [`WINDOW`] steps of each insertion without branching.
/// Returns how many elements moved.
///
/// Each element is compared with the `WINDOW` elements before it on its chain, and `k`, the
/// number of those (counted from the nearest, up to the first that is not greater) it moves
/// past, is computed as a number. Then each of those `WINDOW` slots is rewritten from a copy
/// chosen by an index computed from `k`: the slot `m` places back takes the element `m + 1`
/// places back if `m < k`, the element itself if `m == k`, and its own element otherwise. Only
/// an element that moves past all `WINDOW` goes on along its chain with a branch per step.
///
/// The comparisons beyond the first that fails are made for nothing, but in a pass of a
/// partly sorted slice how far an element moves is about as hard to predict as a coin toss,
/// and each misprediction costs more than several comparisons of small elements.
/// An element held outside a slice and the vacant slot it belongs in: dropping it, when the
/// insertion is done or a comparison panics, writes the element there.