//===----------------------------------------------------------*- swift -*-===// // // This source file is part of the Swift open source project // // Copyright (c) 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// // MARK: _rotate(in:shiftingToStart:) extension MutableCollection { /// Rotates the elements of the collection so that the element at `middle` /// ends up first. /// /// - Returns: The new index of the element that was first pre-rotation. /// /// - Complexity: O(*n*) @discardableResult internal mutating func _rotate(in subrange: Range, shiftingToStart middle: Index) -> Index { var m = middle, s = subrange.lowerBound let e = subrange.upperBound // Handle the trivial cases if s == m { return e } if m == e { return s } // We have two regions of possibly-unequal length that need to be // exchanged. The return value of this method is going to be the // position following that of the element that is currently last // (element j). // // [a b c d e f g|h i j] or [a b c|d e f g h i j] // ^ ^ ^ ^ ^ ^ // s m e s m e // var ret = e // start with a known incorrect result. while true { // Exchange the leading elements of each region (up to the // length of the shorter region). // // [a b c d e f g|h i j] or [a b c|d e f g h i j] // ^^^^^ ^^^^^ ^^^^^ ^^^^^ // [h i j d e f g|a b c] or [d e f|a b c g h i j] // ^ ^ ^ ^ ^ ^ ^ ^ // s s1 m m1/e s s1/m m1 e // let (s1, m1) = _swapNonemptySubrangePrefixes(s.., _ rhs: Range ) -> (Index, Index) { assert(!lhs.isEmpty) assert(!rhs.isEmpty) var p = lhs.lowerBound var q = rhs.lowerBound repeat { swapAt(p, q) formIndex(after: &p) formIndex(after: &q) } while p != lhs.upperBound && q != rhs.upperBound return (p, q) } } // MARK: - _stablePartition(count:range:by:) extension MutableCollection { /// Moves all elements satisfying `belongsInSecondPartition` into a suffix /// of the collection, preserving their relative order, and returns the /// start of the resulting suffix. /// /// - Complexity: O(*n* log *n*) where *n* is the number of elements. /// - Precondition: /// `n == distance(from: range.lowerBound, to: range.upperBound)` internal mutating func _stablePartition( count n: Int, range: Range, by belongsInSecondPartition: (Element) throws-> Bool ) rethrows -> Index { if n == 0 { return range.lowerBound } if n == 1 { return try belongsInSecondPartition(self[range.lowerBound]) ? range.lowerBound : range.upperBound } let h = n / 2, i = index(range.lowerBound, offsetBy: h) let j = try _stablePartition( count: h, range: range.lowerBound.., by belongsInSecondPartition: (Index) throws-> Bool ) rethrows -> Index { if n == 0 { return range.lowerBound } if n == 1 { return try belongsInSecondPartition(range.lowerBound) ? range.lowerBound : range.upperBound } let h = n / 2, i = index(range.lowerBound, offsetBy: h) let j = try _indexedStablePartition( count: h, range: range.lowerBound.. Bool ) rethrows -> Index { var n = count var l = startIndex while n > 0 { let half = n / 2 let mid = index(l, offsetBy: half) if try predicate(self[mid]) { n = half } else { l = index(after: mid) n -= half + 1 } } return l } }