Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions stdlib/public/core/Sort.swift
Original file line number Diff line number Diff line change
Expand Up @@ -710,4 +710,45 @@ extension UnsafeMutableBufferPointer {
_internalInvariant(runs.count == 1, "Didn't complete final merge")
}
}

/// Sorts `self[range]` according to `areInIncreasingOrder`. Stable.
///
/// - Precondition: `sortedEnd != range.lowerBound`
/// - Precondition: `elements[..<sortedEnd]` are already in order.
@inlinable
internal mutating func _insertionSort(
within range: Range<Index>,
sortedEnd: Index,
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows {
_precondition(sortedEnd > range.lowerBound && sortedEnd <= range.upperBound)
var sortedEnd = sortedEnd

// Continue sorting until the sorted elements cover the whole range.
while sortedEnd != range.upperBound {
var i = sortedEnd
// Look backwards for `self[i]`'s position in the sorted sequence,
// moving each element forward to make room.
repeat {
let j = index(before: i)

let pi = (_position._unsafelyUnwrappedUnchecked + i)
let pj = (_position._unsafelyUnwrappedUnchecked + j)

// If `self[i]` doesn't belong before `self[j]`, we've found
// its position.
if try !areInIncreasingOrder(pi.pointee, pj.pointee) {
break
}

let tmp = pi.move()
pi.moveInitialize(from: pj, count: 1)
pj.initialize(to: consume tmp)

i = j
} while i != range.lowerBound

formIndex(after: &sortedEnd)
}
}
}
39 changes: 19 additions & 20 deletions stdlib/public/core/UnsafeBufferPointer.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -304,16 +304,15 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle

@inlinable // unsafe-performance
public func _failEarlyRangeCheck(_ index: Int, bounds: Range<Int>) {
// NOTE: In release mode, this method is a no-op for performance reasons.
_debugPrecondition(index >= bounds.lowerBound)
_debugPrecondition(index < bounds.upperBound)
_precondition(index >= bounds.lowerBound && index < bounds.upperBound)
}

@inlinable // unsafe-performance
public func _failEarlyRangeCheck(_ range: Range<Int>, bounds: Range<Int>) {
// NOTE: In release mode, this method is a no-op for performance reasons.
_debugPrecondition(range.lowerBound >= bounds.lowerBound)
_debugPrecondition(range.upperBound <= bounds.upperBound)
_precondition(
range.lowerBound >= bounds.lowerBound &&
range.upperBound <= bounds.upperBound
)
}

@inlinable // unsafe-performance
Expand Down Expand Up @@ -365,14 +364,14 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
@inlinable // unsafe-performance
public subscript(i: Int) -> Element {
get {
_debugPrecondition(i >= 0)
_debugPrecondition(i < endIndex)
_precondition(i >= 0)
_precondition(i < endIndex)
return _position._unsafelyUnwrappedUnchecked[i]
}
%if Mutable:
nonmutating _modify {
_debugPrecondition(i >= 0)
_debugPrecondition(i < endIndex)
_precondition(i >= 0)
_precondition(i < endIndex)
yield &_position._unsafelyUnwrappedUnchecked[i]
}
%end
Expand Down Expand Up @@ -438,16 +437,16 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
-> Slice<Unsafe${Mutable}BufferPointer<Element>>
{
get {
_debugPrecondition(bounds.lowerBound >= startIndex)
_debugPrecondition(bounds.upperBound <= endIndex)
_precondition(bounds.lowerBound >= startIndex)
_precondition(bounds.upperBound <= endIndex)
return Slice(
base: self, bounds: bounds)
}
% if Mutable:
nonmutating set {
_debugPrecondition(bounds.lowerBound >= startIndex)
_debugPrecondition(bounds.upperBound <= endIndex)
_debugPrecondition(bounds.count == newValue.count)
_precondition(bounds.lowerBound >= startIndex)
_precondition(bounds.upperBound <= endIndex)
_precondition(bounds.count == newValue.count)

// FIXME: swift-3-indexing-model: tests.
if !newValue.isEmpty {
Expand All @@ -472,8 +471,8 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
@inlinable // unsafe-performance
public func swapAt(_ i: Int, _ j: Int) {
guard i != j else { return }
_debugPrecondition(i >= 0 && j >= 0)
_debugPrecondition(i < endIndex && j < endIndex)
_precondition(i >= 0 && j >= 0)
_precondition(i < endIndex && j < endIndex)
let pi = (_position! + i)
let pj = (_position! + j)
let tmp = pi.move()
Expand Down Expand Up @@ -1029,7 +1028,7 @@ extension Unsafe${Mutable}BufferPointer {
@inlinable
@_alwaysEmitIntoClient
public func initializeElement(at index: Index, to value: Element) {
_debugPrecondition(startIndex <= index && index < endIndex)
_precondition(startIndex <= index && index < endIndex)
let p = baseAddress._unsafelyUnwrappedUnchecked.advanced(by: index)
p.initialize(to: value)
}
Expand All @@ -1047,7 +1046,7 @@ extension Unsafe${Mutable}BufferPointer {
@inlinable
@_alwaysEmitIntoClient
public func moveElement(from index: Index) -> Element {
_debugPrecondition(startIndex <= index && index < endIndex)
_precondition(startIndex <= index && index < endIndex)
return baseAddress._unsafelyUnwrappedUnchecked.advanced(by: index).move()
}

Expand All @@ -1062,7 +1061,7 @@ extension Unsafe${Mutable}BufferPointer {
@inlinable
@_alwaysEmitIntoClient
public func deinitializeElement(at index: Index) {
_debugPrecondition(startIndex <= index && index < endIndex)
_precondition(startIndex <= index && index < endIndex)
let p = baseAddress._unsafelyUnwrappedUnchecked.advanced(by: index)
p.deinitialize(count: 1)
}
Expand Down