forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSort.swift.gyb
149 lines (127 loc) · 4.62 KB
/
Sort.swift.gyb
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
// RUN: rm -f %t.swift %t.out
// RUN: %S/../../utils/gyb %s -o %t.swift
// RUN: %S/../../utils/line-directive %t.swift -- %target-build-swift %t.swift -o %t.out
// RUN: %S/../../utils/line-directive %t.swift -- %target-run %t.out
// REQUIRES: executable_test
import StdlibUnittest
import SwiftPrivate
// FIXME(prext): fold this test into Algorithm.swift.gyb.
var Algorithm = TestSuite("Algorithm")
// Check if one array is a correctly sorted version of another array.
// We can't simply sort both arrays and compare them, because it is needed to
// check correctness of sorting itself.
func expectSortedCollection(sortedAry: [Int], _ originalAry: [Int]) {
expectEqual(sortedAry.count, originalAry.count)
var sortedVals = [Int:Int]()
var originalVals = [Int:Int]()
// Keep track of what values we have in sortedAry.
for e in sortedAry {
if let v = sortedVals[e] {
sortedVals[e] = v + 1
} else {
sortedVals[e] = 0
}
}
// And do the same for originalAry.
for e in originalAry {
if let v = originalVals[e] {
originalVals[e] = v + 1
} else {
originalVals[e] = 0
}
}
// Now check if sets of elements are the same in both arrays.
for (key, value) in sortedVals {
expectNotEmpty(originalVals[key])
expectEqual(originalVals[key]!, value)
}
// Check if values in sortedAry are actually sorted.
for i in 1..<sortedAry.count {
expectTrue(sortedAry[i - 1] <= sortedAry[i])
}
}
func expectSortedCollection(
sortedAry: [Int],
_ originalAry: ContiguousArray<Int>
) {
expectSortedCollection(sortedAry, Array(originalAry))
}
func expectSortedCollection(sortedAry: ArraySlice<Int>, _ originalAry: ArraySlice<Int>) {
expectSortedCollection([Int](sortedAry), [Int](originalAry))
}
class OffsetCollection : MutableCollectionType {
let offset: Int
var data: [Int] = []
let forward: Bool
var startIndex: Int { return forward ? offset : offset - data.count }
var endIndex: Int { return forward ? offset + data.count : offset }
subscript (i: Int) -> Int {
get { return data[i - startIndex] }
set { data[i - startIndex] = newValue }
}
func generate() -> IndexingGenerator<[Int]> {
return IndexingGenerator<[Int]>(data)
}
func toArray() -> [Int] {
return data
}
var count: Int { return data.count }
init(_ ary: [Int], offset: Int, forward: Bool) {
data = ary
self.offset = offset
self.forward = forward
}
}
// Generate two versions of tests: one for sort with explicitly passed
// predicate and the other using default comparison operator.
% withArrayTypeNames = ["Array", "ContiguousArray"]
% withPredicateValues = [True, False]
% for t in withArrayTypeNames:
// workaround for <rdar://problem/18900352> gyb miscompiles nested loops
% for p in withPredicateValues:
// workaround for <rdar://problem/18900352> gyb miscompiles nested loops
% comparePredicate = "<" if p else ""
% commaComparePredicate = ", <" if p else ""
% name = "lessPredicate" if p else "noPredicate"
Algorithm.test("${t}/sorted/${name}") {
let count = 1000
var ary = ${t}(randArray(count))
var sortedAry1 = [Int]()
var sortedAry2 = ${t}<Int>()
// Similar test for sorting with predicate
sortedAry1 = ary.sort(${comparePredicate})
expectSortedCollection(sortedAry1, ary)
// Check that sorting works well on intervals
let i1 = 400
let i2 = 700
sortedAry2 = ary
_introSort(&sortedAry2, i1..<i2${commaComparePredicate})
expectEqual(ary[0..<i1], sortedAry2[0..<i1])
expectSortedCollection(sortedAry2[i1..<i2], ary[i1..<i2])
expectEqual(ary[i2..<count], sortedAry2[i2..<count])
}
% end
% end
Algorithm.test("sort/CollectionsWithUnusualIndices") {
let count = 1000
var ary = randArray(count)
// Check if sorting routines work well on collections with startIndex != 0.
var offsetAry = OffsetCollection(ary, offset: 500, forward: false)
offsetAry.sortInPlace(${comparePredicate})
expectSortedCollection(offsetAry.toArray(), ary)
// Check if sorting routines work well on collections with endIndex = Int.max.
// That could expose overflow errors in index computations.
offsetAry = OffsetCollection(ary, offset: Int.max, forward: false)
offsetAry.sortInPlace(${comparePredicate})
expectSortedCollection(offsetAry.toArray(), ary)
// Check if sorting routines work well on collections with
// startIndex = Int.min.
offsetAry = OffsetCollection(ary, offset: Int.min, forward: true)
offsetAry.sortInPlace(${comparePredicate})
expectSortedCollection(offsetAry.toArray(), ary)
}
Algorithm.test("partition/CrashOnSingleElement") {
var a = DefaultedRandomAccessMutableCollection([10])
expectEqual(a.startIndex, a.partition(a.indices))
}
runAllTests()