Skip to content

Commit bd7171b

Browse files
[stdlib] De-gyb Sort (#17954)
* [stdlib] De-gyb Sort
1 parent adf79f9 commit bd7171b

File tree

7 files changed

+621
-696
lines changed

7 files changed

+621
-696
lines changed

stdlib/public/core/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ set(SWIFTLIB_ESSENTIAL
119119
Shims.swift
120120
Slice.swift
121121
SmallString.swift
122-
Sort.swift.gyb
122+
Sort.swift
123123
StaticString.swift
124124
Stride.swift.gyb
125125
StringHashable.swift # ORDER DEPENDENCY: Must precede String.swift

stdlib/public/core/CollectionAlgorithms.swift

Lines changed: 0 additions & 257 deletions
Original file line numberDiff line numberDiff line change
@@ -473,260 +473,3 @@ extension MutableCollection where Self : RandomAccessCollection {
473473
shuffle(using: &Random.default)
474474
}
475475
}
476-
477-
//===----------------------------------------------------------------------===//
478-
// sorted()/sort()
479-
//===----------------------------------------------------------------------===//
480-
481-
extension Sequence where Element : Comparable {
482-
/// Returns the elements of the sequence, sorted.
483-
///
484-
/// You can sort any sequence of elements that conform to the `Comparable`
485-
/// protocol by calling this method. Elements are sorted in ascending order.
486-
///
487-
/// The sorting algorithm is not stable. A nonstable sort may change the
488-
/// relative order of elements that compare equal.
489-
///
490-
/// Here's an example of sorting a list of students' names. Strings in Swift
491-
/// conform to the `Comparable` protocol, so the names are sorted in
492-
/// ascending order according to the less-than operator (`<`).
493-
///
494-
/// let students: Set = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
495-
/// let sortedStudents = students.sorted()
496-
/// print(sortedStudents)
497-
/// // Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
498-
///
499-
/// To sort the elements of your sequence in descending order, pass the
500-
/// greater-than operator (`>`) to the `sorted(by:)` method.
501-
///
502-
/// let descendingStudents = students.sorted(by: >)
503-
/// print(descendingStudents)
504-
/// // Prints "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
505-
///
506-
/// - Returns: A sorted array of the sequence's elements.
507-
@inlinable
508-
public func sorted() -> [Element] {
509-
var result = ContiguousArray(self)
510-
result.sort()
511-
return Array(result)
512-
}
513-
}
514-
515-
extension Sequence {
516-
/// Returns the elements of the sequence, sorted using the given predicate as
517-
/// the comparison between elements.
518-
///
519-
/// When you want to sort a sequence of elements that don't conform to the
520-
/// `Comparable` protocol, pass a predicate to this method that returns
521-
/// `true` when the first element passed should be ordered before the
522-
/// second. The elements of the resulting array are ordered according to the
523-
/// given predicate.
524-
///
525-
/// The predicate must be a *strict weak ordering* over the elements. That
526-
/// is, for any elements `a`, `b`, and `c`, the following conditions must
527-
/// hold:
528-
///
529-
/// - `areInIncreasingOrder(a, a)` is always `false`. (Irreflexivity)
530-
/// - If `areInIncreasingOrder(a, b)` and `areInIncreasingOrder(b, c)` are
531-
/// both `true`, then `areInIncreasingOrder(a, c)` is also `true`.
532-
/// (Transitive comparability)
533-
/// - Two elements are *incomparable* if neither is ordered before the other
534-
/// according to the predicate. If `a` and `b` are incomparable, and `b`
535-
/// and `c` are incomparable, then `a` and `c` are also incomparable.
536-
/// (Transitive incomparability)
537-
///
538-
/// The sorting algorithm is not stable. A nonstable sort may change the
539-
/// relative order of elements for which `areInIncreasingOrder` does not
540-
/// establish an order.
541-
///
542-
/// In the following example, the predicate provides an ordering for an array
543-
/// of a custom `HTTPResponse` type. The predicate orders errors before
544-
/// successes and sorts the error responses by their error code.
545-
///
546-
/// enum HTTPResponse {
547-
/// case ok
548-
/// case error(Int)
549-
/// }
550-
///
551-
/// let responses: [HTTPResponse] = [.error(500), .ok, .ok, .error(404), .error(403)]
552-
/// let sortedResponses = responses.sorted {
553-
/// switch ($0, $1) {
554-
/// // Order errors by code
555-
/// case let (.error(aCode), .error(bCode)):
556-
/// return aCode < bCode
557-
///
558-
/// // All successes are equivalent, so none is before any other
559-
/// case (.ok, .ok): return false
560-
///
561-
/// // Order errors before successes
562-
/// case (.error, .ok): return true
563-
/// case (.ok, .error): return false
564-
/// }
565-
/// }
566-
/// print(sortedResponses)
567-
/// // Prints "[.error(403), .error(404), .error(500), .ok, .ok]"
568-
///
569-
/// You also use this method to sort elements that conform to the
570-
/// `Comparable` protocol in descending order. To sort your sequence in
571-
/// descending order, pass the greater-than operator (`>`) as the
572-
/// `areInIncreasingOrder` parameter.
573-
///
574-
/// let students: Set = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
575-
/// let descendingStudents = students.sorted(by: >)
576-
/// print(descendingStudents)
577-
/// // Prints "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
578-
///
579-
/// Calling the related `sorted()` method is equivalent to calling this
580-
/// method and passing the less-than operator (`<`) as the predicate.
581-
///
582-
/// print(students.sorted())
583-
/// // Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
584-
/// print(students.sorted(by: <))
585-
/// // Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
586-
///
587-
/// - Parameter areInIncreasingOrder: A predicate that returns `true` if its
588-
/// first argument should be ordered before its second argument;
589-
/// otherwise, `false`.
590-
/// - Returns: A sorted array of the sequence's elements.
591-
@inlinable
592-
public func sorted(
593-
by areInIncreasingOrder:
594-
(Element, Element) throws -> Bool
595-
) rethrows -> [Element] {
596-
var result = ContiguousArray(self)
597-
try result.sort(by: areInIncreasingOrder)
598-
return Array(result)
599-
}
600-
}
601-
602-
extension MutableCollection
603-
where
604-
Self : RandomAccessCollection, Element : Comparable {
605-
606-
/// Sorts the collection in place.
607-
///
608-
/// You can sort any mutable collection of elements that conform to the
609-
/// `Comparable` protocol by calling this method. Elements are sorted in
610-
/// ascending order.
611-
///
612-
/// The sorting algorithm is not stable. A nonstable sort may change the
613-
/// relative order of elements that compare equal.
614-
///
615-
/// Here's an example of sorting a list of students' names. Strings in Swift
616-
/// conform to the `Comparable` protocol, so the names are sorted in
617-
/// ascending order according to the less-than operator (`<`).
618-
///
619-
/// var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
620-
/// students.sort()
621-
/// print(students)
622-
/// // Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"
623-
///
624-
/// To sort the elements of your collection in descending order, pass the
625-
/// greater-than operator (`>`) to the `sort(by:)` method.
626-
///
627-
/// students.sort(by: >)
628-
/// print(students)
629-
/// // Prints "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
630-
@inlinable
631-
public mutating func sort() {
632-
let didSortUnsafeBuffer: Void? =
633-
_withUnsafeMutableBufferPointerIfSupported {
634-
(bufferPointer) -> Void in
635-
bufferPointer.sort()
636-
return ()
637-
}
638-
if didSortUnsafeBuffer == nil {
639-
_introSort(&self, subRange: startIndex..<endIndex)
640-
}
641-
}
642-
}
643-
644-
extension MutableCollection where Self : RandomAccessCollection {
645-
/// Sorts the collection in place, using the given predicate as the
646-
/// comparison between elements.
647-
///
648-
/// When you want to sort a collection of elements that doesn't conform to
649-
/// the `Comparable` protocol, pass a closure to this method that returns
650-
/// `true` when the first element passed should be ordered before the
651-
/// second.
652-
///
653-
/// The predicate must be a *strict weak ordering* over the elements. That
654-
/// is, for any elements `a`, `b`, and `c`, the following conditions must
655-
/// hold:
656-
///
657-
/// - `areInIncreasingOrder(a, a)` is always `false`. (Irreflexivity)
658-
/// - If `areInIncreasingOrder(a, b)` and `areInIncreasingOrder(b, c)` are
659-
/// both `true`, then `areInIncreasingOrder(a, c)` is also `true`.
660-
/// (Transitive comparability)
661-
/// - Two elements are *incomparable* if neither is ordered before the other
662-
/// according to the predicate. If `a` and `b` are incomparable, and `b`
663-
/// and `c` are incomparable, then `a` and `c` are also incomparable.
664-
/// (Transitive incomparability)
665-
///
666-
/// The sorting algorithm is not stable. A nonstable sort may change the
667-
/// relative order of elements for which `areInIncreasingOrder` does not
668-
/// establish an order.
669-
///
670-
/// In the following example, the closure provides an ordering for an array
671-
/// of a custom enumeration that describes an HTTP response. The predicate
672-
/// orders errors before successes and sorts the error responses by their
673-
/// error code.
674-
///
675-
/// enum HTTPResponse {
676-
/// case ok
677-
/// case error(Int)
678-
/// }
679-
///
680-
/// var responses: [HTTPResponse] = [.error(500), .ok, .ok, .error(404), .error(403)]
681-
/// responses.sort {
682-
/// switch ($0, $1) {
683-
/// // Order errors by code
684-
/// case let (.error(aCode), .error(bCode)):
685-
/// return aCode < bCode
686-
///
687-
/// // All successes are equivalent, so none is before any other
688-
/// case (.ok, .ok): return false
689-
///
690-
/// // Order errors before successes
691-
/// case (.error, .ok): return true
692-
/// case (.ok, .error): return false
693-
/// }
694-
/// }
695-
/// print(responses)
696-
/// // Prints "[.error(403), .error(404), .error(500), .ok, .ok]"
697-
///
698-
/// Alternatively, use this method to sort a collection of elements that do
699-
/// conform to `Comparable` when you want the sort to be descending instead
700-
/// of ascending. Pass the greater-than operator (`>`) operator as the
701-
/// predicate.
702-
///
703-
/// var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
704-
/// students.sort(by: >)
705-
/// print(students)
706-
/// // Prints "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
707-
///
708-
/// - Parameter areInIncreasingOrder: A predicate that returns `true` if its
709-
/// first argument should be ordered before its second argument;
710-
/// otherwise, `false`. If `areInIncreasingOrder` throws an error during
711-
/// the sort, the elements may be in a different order, but none will be
712-
/// lost.
713-
@inlinable
714-
public mutating func sort(
715-
by areInIncreasingOrder:
716-
(Element, Element) throws -> Bool
717-
) rethrows {
718-
719-
let didSortUnsafeBuffer: Void? =
720-
try _withUnsafeMutableBufferPointerIfSupported {
721-
(bufferPointer) -> Void in
722-
try bufferPointer.sort(by: areInIncreasingOrder)
723-
return ()
724-
}
725-
if didSortUnsafeBuffer == nil {
726-
try _introSort(
727-
&self,
728-
subRange: startIndex..<endIndex,
729-
by: areInIncreasingOrder)
730-
}
731-
}
732-
}

stdlib/public/core/MutableCollection.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,32 @@ extension MutableCollection {
239239
}
240240
}
241241

242+
// the legacy swap free function
243+
//
244+
/// Exchanges the values of the two arguments.
245+
///
246+
/// The two arguments must not alias each other. To swap two elements of a
247+
/// mutable collection, use the `swapAt(_:_:)` method of that collection
248+
/// instead of this function.
249+
///
250+
/// - Parameters:
251+
/// - a: The first value to swap.
252+
/// - b: The second value to swap.
253+
@inlinable
254+
public func swap<T>(_ a: inout T, _ b: inout T) {
255+
// Semantically equivalent to (a, b) = (b, a).
256+
// Microoptimized to avoid retain/release traffic.
257+
let p1 = Builtin.addressof(&a)
258+
let p2 = Builtin.addressof(&b)
259+
_debugPrecondition(
260+
p1 != p2,
261+
"swapping a location with itself is not supported")
262+
263+
// Take from P1.
264+
let tmp: T = Builtin.take(p1)
265+
// Transfer P2 into P1.
266+
Builtin.initialize(Builtin.take(p2) as T, p1)
267+
// Initialize P2.
268+
Builtin.initialize(tmp, p2)
269+
}
242270

0 commit comments

Comments
 (0)