9
9
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10
10
//
11
11
//===----------------------------------------------------------------------===//
12
- // RUN: %target-run-stdlib-swift
12
+ // RUN: %empty-directory(%t)
13
+ // RUN: %target-build-swift -g -Onone -DUSE_STDLIBUNITTEST %s -o %t/a.out
14
+ // RUN: %target-run %t/a.out
13
15
// REQUIRES: executable_test
14
16
17
+ #if USE_STDLIBUNITTEST
15
18
import Swift
16
19
import StdlibUnittest
20
+ #endif
17
21
18
22
//===--- Rotate -----------------------------------------------------------===//
19
23
//===----------------------------------------------------------------------===//
20
24
21
- public protocol CollectionAlgorithms : Collection
22
- where SubSequence : CollectionAlgorithms
23
- {
24
- func lastIndex( where predicate: ( Element ) throws -> Bool ) rethrows -> Index ?
25
- func _indexAfterLastIndex(
26
- where predicate: ( Element ) throws -> Bool
27
- ) rethrows -> Index ?
28
- }
29
-
30
- extension Collection {
31
- public func lastIndex(
32
- where predicate: ( Element ) throws -> Bool
33
- ) rethrows -> Index ? {
34
- return try indices. reduce ( nil ) {
35
- r, i in try predicate ( self [ i] ) ? i as Optional : r
36
- }
37
- }
38
-
39
- public func _indexAfterLastIndex(
40
- where predicate: ( Element ) throws -> Bool
41
- ) rethrows -> Index ? {
42
- return try lastIndex ( where: predicate) . map { index ( after: $0) }
43
- }
44
- }
45
-
46
- extension BidirectionalCollection {
47
- public func lastIndex(
48
- where predicate: ( Element ) throws -> Bool
49
- ) rethrows -> Index ? {
50
- return try indices. reversed ( ) . first { try predicate ( self [ $0] ) }
51
- }
52
-
53
- public func _indexAfterLastIndex(
54
- where predicate: ( Element ) throws -> Bool
55
- ) rethrows -> Index ? {
56
- return try self . reversed ( ) . firstIndex ( where: predicate) ? . base
57
- }
58
- }
59
-
60
- // In the stdlib, this would simply be MutableCollection
61
- public protocol MutableCollectionAlgorithms
62
- : MutableCollection , CollectionAlgorithms
25
+ /// Provides customization points for `MutableCollection` algorithms.
26
+ ///
27
+ /// If incorporated into the standard library, these requirements would just be
28
+ /// part of `MutableCollection`. In the meantime, you can declare conformance
29
+ /// of a collection to `MutableCollectionAlgorithms` to get these customization
30
+ /// points to be used from other algorithms defined on
31
+ /// `MutableCollectionAlgorithms`.
32
+ public protocol MutableCollectionAlgorithms : MutableCollection
63
33
where SubSequence : MutableCollectionAlgorithms
64
34
{
65
35
/// Rotates the elements of the collection so that the element
@@ -72,15 +42,14 @@ public protocol MutableCollectionAlgorithms
72
42
mutating func rotate( shiftingToStart middle: Index ) -> Index
73
43
}
74
44
75
- // In the stdlib, these conformances wouldn't be needed
45
+ // Conformances of common collection types to MutableCollectionAlgorithms.
46
+ // If rotate was a requirement of MutableCollection, these would not be needed.
76
47
extension Array : MutableCollectionAlgorithms { }
77
48
extension ArraySlice : MutableCollectionAlgorithms { }
78
-
79
- extension Slice : MutableCollectionAlgorithms , CollectionAlgorithms
49
+ extension Slice : MutableCollectionAlgorithms
80
50
where Base: MutableCollection { }
81
51
82
- /// In the stdlib, this would simply be MutableCollection
83
- extension MutableCollectionAlgorithms {
52
+ extension MutableCollection {
84
53
/// Swaps the elements of the two given subranges, up to the upper bound of
85
54
/// the smaller subrange. The returned indices are the ends of the two ranges
86
55
/// that were actually swapped.
@@ -557,55 +526,58 @@ extension Collection {
557
526
//===--- Stable Partition -------------------------------------------------===//
558
527
//===----------------------------------------------------------------------===//
559
528
560
- extension Collection
561
- where Self : MutableCollectionAlgorithms {
562
-
529
+ extension MutableCollectionAlgorithms {
530
+ /// Moves all elements satisfying `isSuffixElement` into a suffix of the
531
+ /// collection, preserving their relative order, and returns the start of the
532
+ /// resulting suffix.
533
+ ///
534
+ /// - Complexity: O(n) where n is the number of elements.
563
535
@discardableResult
564
536
mutating func stablePartition(
565
537
isSuffixElement: ( Element ) throws -> Bool
566
538
) rethrows -> Index {
567
- return try stablePartition (
568
- count: count, isSuffixElement: isSuffixElement)
569
- }
570
-
571
- /// Moves all elements satisfying `isSuffixElement` into a suffix of the collection,
572
- /// preserving their relative order, returning the start of the resulting suffix.
573
- ///
574
- /// - Complexity: O(n) where n is the number of elements.
575
- /// - Precondition: `n == self.count`
576
- fileprivate mutating func stablePartition(
577
- count n: Int , isSuffixElement: ( Element ) throws -> Bool
578
- ) rethrows -> Index {
579
- if n == 0 { return startIndex }
580
- if n == 1 {
581
- return try isSuffixElement ( self [ startIndex] ) ? startIndex : endIndex
582
- }
583
- let h = n / 2 , i = index ( startIndex, offsetBy: h)
584
- let j = try self [ ..< i] . stablePartition (
585
- count: h, isSuffixElement: isSuffixElement)
586
- let k = try self [ i... ] . stablePartition (
587
- count: n - h, isSuffixElement: isSuffixElement)
588
- return self [ j..< k] . rotate ( shiftingToStart: i)
539
+ return try stablePartition ( count: count, isSuffixElement: isSuffixElement)
540
+ }
541
+
542
+ /// Moves all elements satisfying `isSuffixElement` into a suffix of the
543
+ /// collection, preserving their relative order, and returns the start of the
544
+ /// resulting suffix.
545
+ ///
546
+ /// - Complexity: O(n) where n is the number of elements.
547
+ /// - Precondition: `n == self.count`
548
+ fileprivate mutating func stablePartition(
549
+ count n: Int , isSuffixElement: ( Element ) throws -> Bool
550
+ ) rethrows -> Index {
551
+ if n == 0 { return startIndex }
552
+ if n == 1 {
553
+ return try isSuffixElement ( self [ startIndex] ) ? startIndex : endIndex
589
554
}
555
+ let h = n / 2 , i = index ( startIndex, offsetBy: h)
556
+ let j = try self [ ..< i] . stablePartition (
557
+ count: h, isSuffixElement: isSuffixElement)
558
+ let k = try self [ i... ] . stablePartition (
559
+ count: n - h, isSuffixElement: isSuffixElement)
560
+ return self [ j..< k] . rotate ( shiftingToStart: i)
561
+ }
590
562
}
591
563
592
564
extension Collection {
593
- func stablyPartitioned(
594
- isSuffixElement p: ( Element ) -> Bool
595
- ) -> [ Element ] {
596
- var a = Array ( self )
597
- a. stablePartition ( isSuffixElement: p)
598
- return a
599
- }
565
+ func stablyPartitioned(
566
+ isSuffixElement p: ( Element ) -> Bool
567
+ ) -> [ Element ] {
568
+ var a = Array ( self )
569
+ a. stablePartition ( isSuffixElement: p)
570
+ return a
571
+ }
600
572
}
601
573
602
574
extension LazyCollectionProtocol
603
575
where Element == Elements . Element {
604
- func stablyPartitioned(
605
- isSuffixElement p: ( Element ) -> Bool
606
- ) -> LazyCollection < [ Element ] > {
607
- return elements. stablyPartitioned ( isSuffixElement: p) . lazy
608
- }
576
+ func stablyPartitioned(
577
+ isSuffixElement p: ( Element ) -> Bool
578
+ ) -> LazyCollection < [ Element ] > {
579
+ return elements. stablyPartitioned ( isSuffixElement: p) . lazy
580
+ }
609
581
}
610
582
611
583
extension Collection {
@@ -635,9 +607,60 @@ extension Collection {
635
607
}
636
608
}
637
609
610
+ //===--- Minimal subset of StdlibUnittest for standalone testing ----------===//
611
+ //===----------------------------------------------------------------------===//
612
+ #if !USE_STDLIBUNITTEST
613
+ class TestSuite {
614
+ let name : String
615
+ var tests : [ ( name: String , body: ( ) -> ( ) ) ] = [ ]
616
+ static var all : [ TestSuite ] = [ ]
617
+ init ( _ name: String ) {
618
+ self . name = name
619
+ TestSuite . all. append ( self )
620
+ }
621
+
622
+ func test( _ name: String , body: @escaping ( ) -> ( ) ) {
623
+ tests. append ( ( name, body) )
624
+ }
625
+ }
626
+
627
+ func runAllTests( ) {
628
+ for s in TestSuite . all {
629
+ for (testName, f) in s. tests {
630
+ print ( " \( s. name) / \( testName) ... " )
631
+ f ( )
632
+ print ( " done. " )
633
+ }
634
+ }
635
+ }
636
+
637
+ func expectEqual< T : Equatable > (
638
+ _ expected: T , _ x: T , file: StaticString = #file, line: UInt = #line
639
+ ) {
640
+ precondition (
641
+ x == expected, " Expected \( x) == \( expected) " , file: file, line: line)
642
+ }
643
+
644
+ func expectGE< T: Comparable > (
645
+ _ a: T , _ b: T , _ message: @autoclosure ( ) -> String = " " ,
646
+ file: StaticString = #file, line: UInt = #line
647
+ ) {
648
+ precondition ( a >= b, message ( ) , file: file, line: line)
649
+ }
650
+
651
+ func expectLE< T: Comparable > (
652
+ _ a: T , _ b: T , _ message: @autoclosure ( ) -> String = " " ,
653
+ file: StaticString = #file, line: UInt = #line
654
+ ) {
655
+ precondition ( a <= b, message ( ) , file: file, line: line)
656
+ }
657
+ #endif
658
+
659
+
638
660
//===--- Tests ------------------------------------------------------------===//
639
661
//===----------------------------------------------------------------------===//
640
662
663
+
641
664
func address< T> ( _ p: UnsafePointer < T > ) -> UInt { return UInt ( bitPattern: p ) }
642
665
643
666
var suite = TestSuite ( " Algorithms " )
@@ -799,8 +822,8 @@ suite.test("partitionPoint") {
799
822
for j in i..< 11 {
800
823
for k in i... j {
801
824
let p = ( i..< j) . partitionPoint { $0 >= k }
802
- expectGE ( p, i)
803
- expectLE ( p, j)
825
+ expectGE ( p, i, " \( p ) >= \( i ) " )
826
+ expectLE ( p, j, " \( p ) <= \( j ) " )
804
827
expectEqual ( p, k)
805
828
}
806
829
}
0 commit comments