10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
13
- %{
14
- def cmp(a, b, p):
15
- if p:
16
- return "(try areInIncreasingOrder(" + a + ", " + b + "))"
17
- else:
18
- return "(" + a + " < " + b + ")"
19
-
20
- }%
21
-
22
- // Generate two versions of sorting functions: one with an explicitly passed
23
- // predicate 'areInIncreasingOrder' and the other for Comparable types that don't
24
- // need such a predicate.
25
- % preds = [True, False]
26
- % for p in preds:
27
- %{
28
- if p:
29
- rethrows_ = "rethrows"
30
- try_ = "try"
31
- else:
32
- rethrows_ = ""
33
- try_ = ""
34
- }%
35
-
36
13
@_inlineable
37
14
@_versioned
38
15
func _insertionSort< C> (
39
16
_ elements: inout C ,
40
- subRange range: Range<C.Index>
41
- ${", by areInIncreasingOrder: (C.Iterator.Element, C.Iterator.Element) throws -> Bool" if p else ""}
42
- ) ${rethrows_}
43
- where
44
- C : MutableCollection & BidirectionalCollection
45
- ${"" if p else ", C.Iterator.Element : Comparable"} {
46
-
17
+ subRange range: Range < C . Index > ,
18
+ by areInIncreasingOrder: ( C . Iterator . Element , C . Iterator . Element ) throws -> Bool
19
+ ) rethrows where
20
+ C : MutableCollection & BidirectionalCollection
21
+ {
47
22
if !range. isEmpty {
48
23
let start = range. lowerBound
49
24
@@ -62,25 +37,20 @@ func _insertionSort<C>(
62
37
// moving elements forward to make room.
63
38
var i = sortedEnd
64
39
repeat {
65
- let predecessor: C.Iterator.Element = elements[elements.index(before: i)]
40
+ let predecessor : C . Iterator . Element =
41
+ elements [ elements. index ( before: i) ]
66
42
67
- % if p:
68
- // If clouser throws the error, We catch the error put the element at right
69
- // place and rethrow the error.
43
+ // If closure throws the error, We catch the error put the element at
44
+ // right place and rethrow the error.
70
45
do {
71
- // if x doesn't belong before y, we've found its position
72
- if !${cmp("x", " predecessor", p)} {
46
+ // if x doesn't belong before y, we've found its position
47
+ if try ! areInIncreasingOrder ( x , predecessor) {
73
48
break
74
49
}
75
50
} catch {
76
51
elements [ i] = x
77
52
throw error
78
53
}
79
- % else:
80
- if !${cmp("x", "predecessor", p)} {
81
- break
82
- }
83
- % end
84
54
85
55
// Move y forward
86
56
elements [ i] = predecessor
@@ -108,12 +78,11 @@ func _insertionSort<C>(
108
78
public // @testable
109
79
func _sort3< C> (
110
80
_ elements: inout C ,
111
- _ a: C.Index, _ b: C.Index, _ c: C.Index
112
- ${", by areInIncreasingOrder: (C.Iterator.Element, C.Iterator.Element) throws -> Bool" if p else ""}
113
- ) ${rethrows_}
81
+ _ a: C . Index , _ b: C . Index , _ c: C . Index ,
82
+ by areInIncreasingOrder: ( C . Iterator . Element , C . Iterator . Element ) throws -> Bool
83
+ ) rethrows
114
84
where
115
85
C : MutableCollection & RandomAccessCollection
116
- ${"" if p else ", C.Iterator.Element : Comparable"}
117
86
{
118
87
// There are thirteen possible permutations for the original ordering of
119
88
// the elements at indices `a`, `b`, and `c`. The comments in the code below
@@ -135,8 +104,8 @@ func _sort3<C>(
135
104
// 122, 212, or 221.
136
105
// - If all three elements are equivalent, they are already in order: 111.
137
106
138
- switch (${cmp(" elements[b]", " elements[a]", p)} ,
139
- ${cmp(" elements[c]", " elements[b]", p)} ) {
107
+ switch ( try areInIncreasingOrder ( elements [ b] , elements [ a] ) ,
108
+ try areInIncreasingOrder ( elements [ c] , elements [ b] ) ) {
140
109
case ( false , false ) :
141
110
// 0 swaps: 123, 112, 122, 111
142
111
break
@@ -151,7 +120,7 @@ func _sort3<C>(
151
120
// swap(a, b): 213->123, 212->122, 312->132, 211->121
152
121
elements. swapAt ( a, b)
153
122
154
- if ${cmp(" elements[c]", " elements[b]", p)} {
123
+ if try areInIncreasingOrder ( elements [ c] , elements [ b] ) {
155
124
// 132 (started as 312), 121 (started as 211)
156
125
// swap(b, c): 132->123, 121->112
157
126
elements. swapAt ( b, c)
@@ -162,7 +131,7 @@ func _sort3<C>(
162
131
// swap(b, c): 132->123, 121->112, 231->213, 221->212
163
132
elements. swapAt ( b, c)
164
133
165
- if ${cmp(" elements[b]", " elements[a]", p)} {
134
+ if try areInIncreasingOrder ( elements [ b] , elements [ a] ) {
166
135
// 213 (started as 231), 212 (started as 221)
167
136
// swap(a, b): 213->123, 212->122
168
137
elements. swapAt ( a, b)
@@ -180,12 +149,11 @@ func _sort3<C>(
180
149
@_versioned
181
150
func _partition< C> (
182
151
_ elements: inout C ,
183
- subRange range: Range<C.Index>
184
- ${", by areInIncreasingOrder: (C.Iterator.Element, C.Iterator.Element) throws -> Bool" if p else ""}
185
- ) ${rethrows_} -> C.Index
152
+ subRange range: Range < C . Index > ,
153
+ by areInIncreasingOrder: ( C . Iterator . Element , C . Iterator . Element ) throws -> Bool
154
+ ) rethrows -> C . Index
186
155
where
187
156
C : MutableCollection & RandomAccessCollection
188
- ${"" if p else ", C.Iterator.Element : Comparable"}
189
157
{
190
158
var lo = range. lowerBound
191
159
var hi = elements. index ( before: range. upperBound)
@@ -194,8 +162,7 @@ func _partition<C>(
194
162
// as the pivot for the partition.
195
163
let half = numericCast ( elements. distance ( from: lo, to: hi) ) as UInt / 2
196
164
let mid = elements. index ( lo, offsetBy: numericCast ( half) )
197
- ${try_} _sort3(&elements, lo, mid, hi
198
- ${", by: areInIncreasingOrder" if p else ""})
165
+ try _sort3 ( & elements, lo, mid, hi, by: areInIncreasingOrder)
199
166
let pivot = elements [ mid]
200
167
201
168
// Loop invariants:
@@ -206,7 +173,7 @@ func _partition<C>(
206
173
FindLo: do {
207
174
elements. formIndex ( after: & lo)
208
175
while lo != hi {
209
- if !${cmp(" elements[lo]", " pivot", p)} { break FindLo }
176
+ if try ! areInIncreasingOrder ( elements [ lo] , pivot) { break FindLo }
210
177
elements. formIndex ( after: & lo)
211
178
}
212
179
break Loop
@@ -215,7 +182,7 @@ func _partition<C>(
215
182
FindHi: do {
216
183
elements. formIndex ( before: & hi)
217
184
while hi != lo {
218
- if ${cmp(" elements[hi]", " pivot", p)} { break FindHi }
185
+ if try areInIncreasingOrder ( elements [ hi] , pivot) { break FindHi }
219
186
elements. formIndex ( before: & hi)
220
187
}
221
188
break Loop
@@ -231,87 +198,66 @@ func _partition<C>(
231
198
public // @testable
232
199
func _introSort< C> (
233
200
_ elements: inout C ,
234
- subRange range: Range<C.Index>
235
- ${", by areInIncreasingOrder: (C.Iterator.Element, C.Iterator.Element) throws -> Bool" if p else ""}
236
- ) ${rethrows_}
201
+ subRange range: Range < C . Index > ,
202
+ by areInIncreasingOrder: ( C . Iterator . Element , C . Iterator . Element ) throws -> Bool
203
+ ) rethrows
237
204
where
238
205
C : MutableCollection & RandomAccessCollection
239
- ${"" if p else ", C.Iterator.Element : Comparable"} {
240
-
241
- let count =
242
- elements.distance(from: range.lowerBound, to: range.upperBound)
206
+ {
207
+ let count = elements. distance ( from: range. lowerBound, to: range. upperBound)
243
208
if count < 2 {
244
209
return
245
210
}
246
211
// Set max recursion depth to 2*floor(log(N)), as suggested in the introsort
247
212
// paper: http://www.cs.rpi.edu/~musser/gp/introsort.ps
248
213
let depthLimit = 2 * _floorLog2( Int64 ( count) )
249
- ${try_} _introSortImpl(
250
- &elements,
251
- subRange: range,
252
- ${"by: areInIncreasingOrder," if p else ""}
214
+ try _introSortImpl ( & elements, subRange: range, by: areInIncreasingOrder,
253
215
depthLimit: depthLimit)
254
216
}
255
217
256
218
@_inlineable
257
219
@_versioned
258
220
func _introSortImpl< C> (
259
221
_ elements: inout C ,
260
- subRange range: Range<C.Index>
261
- ${", by areInIncreasingOrder: (C.Iterator.Element, C.Iterator.Element) throws -> Bool" if p else ""} ,
222
+ subRange range: Range < C . Index > ,
223
+ by areInIncreasingOrder: ( C . Iterator . Element , C . Iterator . Element ) throws -> Bool ,
262
224
depthLimit: Int
263
- ) ${rethrows_}
225
+ ) rethrows
264
226
where
265
227
C : MutableCollection & RandomAccessCollection
266
- ${"" if p else ", C.Iterator.Element : Comparable"} {
267
-
228
+ {
268
229
// Insertion sort is better at handling smaller regions.
269
230
if elements. distance ( from: range. lowerBound, to: range. upperBound) < 20 {
270
- ${try_} _insertionSort(
271
- &elements,
272
- subRange: range
273
- ${", by: areInIncreasingOrder" if p else ""})
231
+ try _insertionSort ( & elements, subRange: range, by: areInIncreasingOrder)
274
232
return
275
233
}
276
234
if depthLimit == 0 {
277
- ${try_} _heapSort(
278
- &elements,
279
- subRange: range
280
- ${", by: areInIncreasingOrder" if p else ""})
235
+ try _heapSort ( & elements, subRange: range, by: areInIncreasingOrder)
281
236
return
282
237
}
283
238
284
239
// Partition and sort.
285
240
// We don't check the depthLimit variable for underflow because this variable
286
241
// is always greater than zero (see check above).
287
- let partIdx: C.Index = ${try_} _partition(
288
- &elements,
289
- subRange: range
290
- ${", by: areInIncreasingOrder" if p else ""})
291
- ${try_} _introSortImpl(
292
- &elements,
293
- subRange: range.lowerBound..<partIdx,
294
- ${"by: areInIncreasingOrder, " if p else ""}
295
- depthLimit: depthLimit &- 1)
296
- ${try_} _introSortImpl(
297
- &elements,
298
- subRange: partIdx..<range.upperBound,
299
- ${"by: areInIncreasingOrder, " if p else ""}
300
- depthLimit: depthLimit &- 1)
242
+ let partIdx : C . Index = try _partition ( & elements, subRange: range,
243
+ by: areInIncreasingOrder)
244
+ try _introSortImpl ( & elements, subRange: range. lowerBound..< partIdx,
245
+ by: areInIncreasingOrder, depthLimit: depthLimit &- 1 )
246
+ try _introSortImpl ( & elements, subRange: partIdx..< range. upperBound,
247
+ by: areInIncreasingOrder, depthLimit: depthLimit &- 1 )
301
248
}
302
249
303
250
@_inlineable
304
251
@_versioned
305
252
func _siftDown< C> (
306
253
_ elements: inout C ,
307
254
index: C . Index ,
308
- subRange range: Range<C.Index>
309
- ${", by areInIncreasingOrder: (C.Iterator.Element, C.Iterator.Element) throws -> Bool" if p else ""}
310
- ) ${rethrows_}
255
+ subRange range: Range < C . Index > ,
256
+ by areInIncreasingOrder: ( C . Iterator . Element , C . Iterator . Element ) throws -> Bool
257
+ ) rethrows
311
258
where
312
259
C : MutableCollection & RandomAccessCollection
313
- ${"" if p else ", C.Iterator.Element : Comparable"} {
314
-
260
+ {
315
261
let countToIndex = elements. distance ( from: range. lowerBound, to: index)
316
262
let countFromIndex = elements. distance ( from: index, to: range. upperBound)
317
263
// Check if left child is within bounds. If not, return, because there are
@@ -321,38 +267,35 @@ func _siftDown<C>(
321
267
}
322
268
let left = elements. index ( index, offsetBy: countToIndex + 1 )
323
269
var largest = index
324
- if ${cmp(" elements[largest]", " elements[left]", p)} {
270
+ if try areInIncreasingOrder ( elements [ largest] , elements [ left] ) {
325
271
largest = left
326
272
}
327
273
// Check if right child is also within bounds before trying to examine it.
328
274
if countToIndex + 2 < countFromIndex {
329
275
let right = elements. index ( after: left)
330
- if ${cmp(" elements[largest]", " elements[right]", p)} {
276
+ if try areInIncreasingOrder ( elements [ largest] , elements [ right] ) {
331
277
largest = right
332
278
}
333
279
}
334
280
// If a child is bigger than the current node, swap them and continue sifting
335
281
// down.
336
282
if largest != index {
337
283
elements. swapAt ( index, largest)
338
- ${try_} _siftDown(
339
- &elements,
340
- index: largest,
341
- subRange: range
342
- ${", by: areInIncreasingOrder" if p else ""})
284
+ try _siftDown ( & elements, index: largest, subRange: range,
285
+ by: areInIncreasingOrder)
343
286
}
344
287
}
345
288
346
289
@_inlineable
347
290
@_versioned
348
291
func _heapify< C> (
349
292
_ elements: inout C ,
350
- subRange range: Range<C.Index>
351
- ${", by areInIncreasingOrder: (C.Iterator.Element, C.Iterator.Element) throws -> Bool" if p else ""}
352
- ) ${rethrows_}
293
+ subRange range: Range < C . Index > ,
294
+ by areInIncreasingOrder: ( C . Iterator . Element , C . Iterator . Element ) throws -> Bool
295
+ ) rethrows
353
296
where
354
297
C : MutableCollection & RandomAccessCollection
355
- ${"" if p else ", C.Iterator.Element : Comparable"} {
298
+ {
356
299
// Here we build a heap starting from the lowest nodes and moving to the root.
357
300
// On every step we sift down the current node to obey the max-heap property:
358
301
// parent >= max(leftChild, rightChild)
@@ -367,45 +310,32 @@ func _heapify<C>(
367
310
368
311
while node != root {
369
312
elements. formIndex ( before: & node)
370
- ${try_} _siftDown(
371
- &elements,
372
- index: node,
373
- subRange: range
374
- ${", by: areInIncreasingOrder" if p else ""})
313
+ try _siftDown ( & elements, index: node, subRange: range,
314
+ by: areInIncreasingOrder)
375
315
}
376
316
}
377
317
378
318
@_inlineable
379
319
@_versioned
380
320
func _heapSort< C> (
381
321
_ elements: inout C ,
382
- subRange range: Range<C.Index>
383
- ${", by areInIncreasingOrder: (C.Iterator.Element, C.Iterator.Element) throws -> Bool" if p else ""}
384
- ) ${rethrows_}
322
+ subRange range: Range < C . Index > ,
323
+ by areInIncreasingOrder: ( C . Iterator . Element , C . Iterator . Element ) throws -> Bool
324
+ ) rethrows
385
325
where
386
326
C : MutableCollection & RandomAccessCollection
387
- ${"" if p else ", C.Iterator.Element : Comparable"} {
327
+ {
388
328
var hi = range. upperBound
389
329
let lo = range. lowerBound
390
- ${try_} _heapify(
391
- &elements,
392
- subRange: range
393
- ${", by: areInIncreasingOrder" if p else ""})
330
+ try _heapify ( & elements, subRange: range, by: areInIncreasingOrder)
394
331
elements. formIndex ( before: & hi)
395
332
while hi != lo {
396
333
elements. swapAt ( lo, hi)
397
- ${try_} _siftDown(
398
- &elements,
399
- index: lo,
400
- subRange: lo..<hi
401
- ${", by: areInIncreasingOrder" if p else ""})
334
+ try _siftDown ( & elements, index: lo, subRange: lo..< hi, by: areInIncreasingOrder)
402
335
elements. formIndex ( before: & hi)
403
336
}
404
337
}
405
338
406
- % end
407
- // for p in preds
408
-
409
339
/// Exchange the values of `a` and `b`.
410
340
///
411
341
/// - Precondition: `a` and `b` do not alias each other.
0 commit comments