[stdlib] Update partition tests with feedback

This commit is contained in:
Nate Cook
2016-07-15 00:39:25 -05:00
parent 13d1ac5b81
commit 29bbff221b
4 changed files with 44 additions and 84 deletions

View File

@@ -879,15 +879,12 @@ self.test("\(testNamePrefix).sort/${'Predicate' if predicate else 'WhereElementI
// partition() // partition()
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
% for predicate in [False, True]: func checkPartition(
func checkPartition_${'Predicate' if predicate else 'WhereElementIsComparable'}(
sequence: [Int], sequence: [Int],
equalImpl: ((Int, Int) -> Bool), pivotValue: Int,
lessImpl: ((Int, Int) -> Bool), lessImpl: ((Int, Int) -> Bool),
verifyOrder: Bool verifyOrder: Bool
) { ) {
% if predicate:
let extract = extractValue let extract = extractValue
let elements: [OpaqueValue<Int>] = let elements: [OpaqueValue<Int>] =
zip(sequence, 0..<sequence.count).map { zip(sequence, 0..<sequence.count).map {
@@ -895,33 +892,11 @@ func checkPartition_${'Predicate' if predicate else 'WhereElementIsComparable'}(
} }
var c = makeWrappedCollection(elements) var c = makeWrappedCollection(elements)
% else:
MinimalComparableValue.equalImpl.value = equalImpl
MinimalComparableValue.lessImpl.value = lessImpl
let extract = extractValueFromComparable
let elements: [MinimalComparableValue] =
zip(sequence, 0..<sequence.count).map {
MinimalComparableValue($0, identity: $1)
}
var c = makeWrappedCollectionWithComparableElement(elements)
% end
let pivotElt = c.first
var pivot = c.startIndex
% if predicate:
let closureLifetimeTracker = LifetimeTracked(0) let closureLifetimeTracker = LifetimeTracked(0)
if let first = pivotElt { let pivot = c.partition(by: { val in
pivot = c.partition(by: { _blackHole(closureLifetimeTracker)
val in return !lessImpl(extract(val).value, pivotValue)
_blackHole(closureLifetimeTracker) })
return !(extract(val).value < extract(first).value) })
}
% else:
if let first = c.first {
pivot = c.partition(by: { !($0 < first) })
}
% end
// Check that we didn't lose any elements. // Check that we didn't lose any elements.
let identities = c.map { extract($0).identity } let identities = c.map { extract($0).identity }
@@ -931,38 +906,49 @@ func checkPartition_${'Predicate' if predicate else 'WhereElementIsComparable'}(
// All the elements in the first partition are less than the pivot // All the elements in the first partition are less than the pivot
// value. // value.
for i in c[c.startIndex..<pivot].indices { for i in c[c.startIndex..<pivot].indices {
expectLT(extract(c[i]).value, extract(pivotElt!).value) expectLT(extract(c[i]).value, pivotValue)
} }
// All the elements in the second partition are greater or equal to // All the elements in the second partition are greater or equal to
// the pivot value. // the pivot value.
for i in c[pivot..<c.endIndex].indices { for i in c[pivot..<c.endIndex].indices {
expectLE(extract(pivotElt!).value, extract(c[i]).value) expectGE(extract(c[i]).value, pivotValue)
} }
} }
} }
self.test("\(testNamePrefix).partition/${'Predicate' if predicate else 'WhereElementIsComparable'}") { self.test("\(testNamePrefix).partition") {
for test in partitionExhaustiveTests { for test in partitionExhaustiveTests {
forAllPermutations(test.sequence) { (sequence) in forAllPermutations(test.sequence) { (sequence) in
checkPartition_${'Predicate' if predicate else 'WhereElementIsComparable'}( checkPartition(
sequence: sequence, sequence: sequence,
equalImpl: { $0 == $1 }, pivotValue: sequence.first ?? 0,
lessImpl: { $0 < $1 },
verifyOrder: true)
// Pivot value where all elements will pass the partitioning predicate
checkPartition(
sequence: sequence,
pivotValue: Int.min,
lessImpl: { $0 < $1 },
verifyOrder: true)
// Pivot value where no element will pass the partitioning predicate
checkPartition(
sequence: sequence,
pivotValue: Int.max,
lessImpl: { $0 < $1 }, lessImpl: { $0 < $1 },
verifyOrder: true) verifyOrder: true)
} }
} }
} }
self.test("\(testNamePrefix).partition/${'Predicate' if predicate else 'WhereElementIsComparable'}/InvalidOrderings") { self.test("\(testNamePrefix).partition/InvalidOrderings") {
withInvalidOrderings { (comparisonPredicate) in withInvalidOrderings { (comparisonPredicate) in
for i in 0..<7 { for i in 0..<7 {
forAllPermutations(i) { (sequence) in forAllPermutations(i) { (sequence) in
checkPartition_${'Predicate' if predicate else 'WhereElementIsComparable'}( checkPartition(
sequence: sequence, sequence: sequence,
equalImpl: { pivotValue: sequence.first ?? 0,
!comparisonPredicate($0, $1) &&
!comparisonPredicate($1, $0)
},
lessImpl: comparisonPredicate, lessImpl: comparisonPredicate,
verifyOrder: false) verifyOrder: false)
} }
@@ -970,41 +956,23 @@ self.test("\(testNamePrefix).partition/${'Predicate' if predicate else 'WhereEle
} }
} }
self.test("\(testNamePrefix).partition/DispatchesThrough_withUnsafeMutableBufferPointerIfSupported/${'Predicate' if predicate else 'WhereElementIsComparable'}") { self.test("\(testNamePrefix).partition/DispatchesThrough_withUnsafeMutableBufferPointerIfSupported") {
let sequence = [ 5, 4, 3, 2, 1 ] let sequence = [ 5, 4, 3, 2, 1 ]
% if predicate:
let extract = extractValue let extract = extractValue
let elements: [OpaqueValue<Int>] = let elements: [OpaqueValue<Int>] =
zip(sequence, 0..<sequence.count).map { zip(sequence, 0..<sequence.count).map {
OpaqueValue($0, identity: $1) OpaqueValue($0, identity: $1)
} }
let c = makeWrappedCollection(elements) let c = makeWrappedCollection(elements)
% else:
let extract = extractValueFromComparable
let elements: [MinimalComparableValue] =
zip(sequence, 0..<sequence.count).map {
MinimalComparableValue($0, identity: $1)
}
let c = makeWrappedCollectionWithComparableElement(elements)
% end
var lc = LoggingMutableRandomAccessCollection(wrapping: c) var lc = LoggingMutableRandomAccessCollection(wrapping: c)
% if predicate:
let closureLifetimeTracker = LifetimeTracked(0) let closureLifetimeTracker = LifetimeTracked(0)
var pivot = lc.startIndex let first = c.first
if let first = c.first { let pivot = lc.partition(by: { val in
pivot = lc.partition(by: { _blackHole(closureLifetimeTracker)
val in return !(extract(val).value < extract(first!).value)
_blackHole(closureLifetimeTracker) })
return !(extract(val).value < extract(first).value) })
}
% else:
var pivot = lc.startIndex
if let first = lc.first {
pivot = lc.partition(by: { !($0 < first) })
}
% end
expectEqual( expectEqual(
1, lc.log._withUnsafeMutableBufferPointerIfSupported[lc.dynamicType]) 1, lc.log._withUnsafeMutableBufferPointerIfSupported[lc.dynamicType])
@@ -1016,8 +984,6 @@ self.test("\(testNamePrefix).partition/DispatchesThrough_withUnsafeMutableBuffer
expectEqualSequence([ 1, 4, 3, 2, 5 ], lc.map { extract($0).value }) expectEqualSequence([ 1, 4, 3, 2, 5 ], lc.map { extract($0).value })
} }
% end
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
} // addMutableRandomAccessCollectionTests } // addMutableRandomAccessCollectionTests

View File

@@ -78,17 +78,14 @@ print("Test1 - Done")
let partition_verifier: ([Int]) -> Void = { let partition_verifier: ([Int]) -> Void = {
var y = $0 var y = $0
// Partition() returns the index to the pivot value. // partition(by:) returns the index to the pivot value.
var idx = y.startIndex let first = y.first
var pivot = -1 let idx = y.partition(by: { $0 >= first! })
if let first = y.first {
pivot = first
idx = y.partition(by: { $0 >= first })
}
// Check that all of the elements in the first partition are smaller than // Check that all of the elements in the first partition are smaller than
// the pivot value. // the pivot value.
for i in 0..<idx { for i in 0..<idx {
if y[i] >= pivot { if y[i] >= first! {
print("Error!\n", terminator: "") print("Error!\n", terminator: "")
return return
} }
@@ -96,7 +93,7 @@ let partition_verifier: ([Int]) -> Void = {
// Check that all of the elements in the second partition are greater or // Check that all of the elements in the second partition are greater or
// equal to the pivot value. // equal to the pivot value.
for i in idx..<y.count - 1 { for i in idx..<y.count - 1 {
if y[i] < pivot { if y[i] < first! {
print("Error!\n", terminator: "") print("Error!\n", terminator: "")
return return
} }

View File

@@ -76,10 +76,8 @@ extension MutableCollection
where Self: RandomAccessCollection, Self.Iterator.Element : Comparable { where Self: RandomAccessCollection, Self.Iterator.Element : Comparable {
public final mutating func myPartition() -> Index { public final mutating func myPartition() -> Index {
if let first = self.first { let first = self.first
return self.partition(by: { $0 >= first}) return self.partition(by: { $0 >= first! })
}
return self.startIndex
} }
} }

View File

@@ -150,9 +150,8 @@ Algorithm.test("invalidOrderings") {
var a: A<Int> var a: A<Int>
a = randomArray() a = randomArray()
let lt = $0 let lt = $0
if let first = a.first { let first = a.first
_ = a.partition(by: { !lt($0, first) }) _ = a.partition(by: { !lt($0, first!) })
}
} }
/* /*
// FIXME: Disabled due to <rdar://problem/17734737> Unimplemented: // FIXME: Disabled due to <rdar://problem/17734737> Unimplemented: