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