From d986c566a11d528e88ea6ada7a1b6d10717224f8 Mon Sep 17 00:00:00 2001 From: Karl <5254025+karwa@users.noreply.github.com> Date: Tue, 16 Mar 2021 12:26:20 +0100 Subject: [PATCH 1/2] Make suffix functions inlinable --- Sources/Algorithms/Suffix.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Algorithms/Suffix.swift b/Sources/Algorithms/Suffix.swift index 0ebd0356..56966c77 100644 --- a/Sources/Algorithms/Suffix.swift +++ b/Sources/Algorithms/Suffix.swift @@ -45,7 +45,7 @@ extension Collection { /// be called again. /// /// - Complexity: O(*n*), where *n* is the length of the collection. - @usableFromInline + @inlinable internal func endOfPrefix( while predicate: (Element) throws -> Bool ) rethrows -> Index { @@ -71,7 +71,7 @@ extension BidirectionalCollection { /// be called again. /// /// - Complexity: O(*n*), where *n* is the length of the collection. - @usableFromInline + @inlinable internal func startOfSuffix( while predicate: (Element) throws -> Bool ) rethrows -> Index { From ba57786b8db4a50f92bfec127ce82c67be22fd17 Mon Sep 17 00:00:00 2001 From: Karl <5254025+karwa@users.noreply.github.com> Date: Tue, 16 Mar 2021 12:49:24 +0100 Subject: [PATCH 2/2] Inline all the things! --- Sources/Algorithms/Chain.swift | 14 +++++++------- Sources/Algorithms/Chunked.swift | 25 +++++++++++++------------ Sources/Algorithms/Combinations.swift | 9 +++++---- Sources/Algorithms/Cycle.swift | 4 ++-- Sources/Algorithms/Indexed.swift | 2 +- Sources/Algorithms/Intersperse.swift | 13 +++++++++---- Sources/Algorithms/LazySplit.swift | 10 +++++----- Sources/Algorithms/Partition.swift | 2 +- Sources/Algorithms/Permutations.swift | 10 +++++----- Sources/Algorithms/Product.swift | 18 ++++++++++-------- Sources/Algorithms/Rotate.swift | 4 ++-- Sources/Algorithms/Stride.swift | 10 +++++----- Sources/Algorithms/Windows.swift | 12 ++++++------ 13 files changed, 71 insertions(+), 62 deletions(-) diff --git a/Sources/Algorithms/Chain.swift b/Sources/Algorithms/Chain.swift index 311e341a..fc9f3ef0 100644 --- a/Sources/Algorithms/Chain.swift +++ b/Sources/Algorithms/Chain.swift @@ -19,7 +19,7 @@ public struct Chain2 /// The second sequence in this chain. public let base2: Base2 - @usableFromInline + @inlinable internal init(base1: Base1, base2: Base2) { self.base1 = base1 self.base2 = base2 @@ -35,7 +35,7 @@ extension Chain2: Sequence { @usableFromInline internal var iterator2: Base2.Iterator - @usableFromInline + @inlinable internal init(_ concatenation: Chain2) { iterator1 = concatenation.base1.makeIterator() iterator2 = concatenation.base2.makeIterator() @@ -71,13 +71,13 @@ extension Chain2: Collection where Base1: Collection, Base2: Collection { internal let position: Representation /// Creates a new index into the first underlying collection. - @usableFromInline + @inlinable internal init(first i: Base1.Index) { position = .first(i) } /// Creates a new index into the second underlying collection. - @usableFromInline + @inlinable internal init(second i: Base2.Index) { position = .second(i) } @@ -99,7 +99,7 @@ extension Chain2: Collection where Base1: Collection, Base2: Collection { /// Converts an index of `Base1` to the corresponding `Index` by mapping /// `base1.endIndex` to `base2.startIndex`. - @usableFromInline + @inlinable internal func convertIndex(_ i: Base1.Index) -> Index { i == base1.endIndex ? Index(second: base2.startIndex) : Index(first: i) } @@ -157,7 +157,7 @@ extension Chain2: Collection where Base1: Collection, Base2: Collection { : offsetBackward(i, by: -n, limitedBy: limit) } - @usableFromInline + @inlinable internal func offsetForward( _ i: Index, by n: Int, limitedBy limit: Index ) -> Index? { @@ -197,7 +197,7 @@ extension Chain2: Collection where Base1: Collection, Base2: Collection { } } - @usableFromInline + @inlinable internal func offsetBackward( _ i: Index, by n: Int, limitedBy limit: Index ) -> Index? { diff --git a/Sources/Algorithms/Chunked.swift b/Sources/Algorithms/Chunked.swift index 388ee4e3..f57b1fc7 100644 --- a/Sources/Algorithms/Chunked.swift +++ b/Sources/Algorithms/Chunked.swift @@ -27,7 +27,7 @@ public struct LazyChunked { @usableFromInline internal var firstUpperBound: Base.Index - @usableFromInline + @inlinable internal init( base: Base, projection: @escaping (Base.Element) -> Subject, @@ -51,7 +51,7 @@ extension LazyChunked: LazyCollectionProtocol { @usableFromInline internal var baseRange: Range - @usableFromInline + @inlinable internal init(_ baseRange: Range) { self.baseRange = baseRange } @@ -72,7 +72,7 @@ extension LazyChunked: LazyCollectionProtocol { /// Returns the index in the base collection of the end of the chunk starting /// at the given index. - @usableFromInline + @inlinable internal func endOfChunk(startingAt start: Base.Index) -> Base.Index { let subject = projection(base[start]) return base[base.index(after: start)...] @@ -112,7 +112,7 @@ extension LazyChunked: BidirectionalCollection { /// Returns the index in the base collection of the start of the chunk ending /// at the given index. - @usableFromInline + @inlinable internal func startOfChunk(endingAt end: Base.Index) -> Base.Index { let indexBeforeEnd = base.index(before: end) @@ -174,7 +174,7 @@ extension Collection { /// predicate. /// /// - Complexity: O(*n*), where *n* is the length of this collection. - @usableFromInline + @inlinable internal func chunked( on projection: (Element) throws -> Subject, by belongInSameGroup: (Subject, Subject) throws -> Bool @@ -273,7 +273,7 @@ extension ChunkedByCount: Collection { @usableFromInline internal let baseRange: Range - @usableFromInline + @inlinable internal init(_baseRange: Range) { self.baseRange = _baseRange } @@ -290,6 +290,7 @@ extension ChunkedByCount: Collection { } /// - Complexity: O(1) + @inlinable public subscript(i: Index) -> Element { precondition(i < endIndex, "Index out of range") return base[i.baseRange] @@ -392,7 +393,7 @@ extension ChunkedByCount { return index } - @usableFromInline + @inlinable internal func offsetForward( _ i: Index, offsetBy distance: Int, limit: Index? = nil ) -> Index? { @@ -406,8 +407,8 @@ extension ChunkedByCount { } // Convenience to compute offset backward base distance. - @inline(__always) - private func computeOffsetBackwardBaseDistance( + @inlinable + internal func computeOffsetBackwardBaseDistance( _ i: Index, _ distance: Int ) -> Int { if i == endIndex { @@ -423,7 +424,7 @@ extension ChunkedByCount { return distance * chunkCount } - @usableFromInline + @inlinable internal func offsetBackward( _ i: Index, offsetBy distance: Int, limit: Index? = nil ) -> Index? { @@ -438,8 +439,8 @@ extension ChunkedByCount { } // Helper to compute index(offsetBy:) index. - @inline(__always) - private func makeOffsetIndex( + @inlinable + internal func makeOffsetIndex( from i: Index, baseBound: Base.Index, distance: Int, baseDistance: Int, limit: Index?, by limitFn: (Base.Index, Base.Index) -> Bool ) -> Index? { diff --git a/Sources/Algorithms/Combinations.swift b/Sources/Algorithms/Combinations.swift index 07c19913..c1e8c1c6 100644 --- a/Sources/Algorithms/Combinations.swift +++ b/Sources/Algorithms/Combinations.swift @@ -27,7 +27,7 @@ public struct Combinations { /// - Parameters: /// - base: The collection to iterate over for combinations. /// - k: The expected size of each combination. - @usableFromInline + @inlinable internal init(_ base: Base, k: Int) { self.init(base, kRange: k...k) } @@ -37,7 +37,7 @@ public struct Combinations { /// - Parameters: /// - base: The collection to iterate over for combinations. /// - kRange: The range of accepted sizes of combinations. - @usableFromInline + @inlinable internal init( _ base: Base, kRange: R ) where R.Bound == Int { @@ -89,7 +89,7 @@ extension Combinations: Sequence { internal var kRange: Range /// Whether or not iteration is finished (`kRange` is empty) - @usableFromInline + @inlinable internal var isFinished: Bool { return kRange.isEmpty } @@ -97,6 +97,7 @@ extension Combinations: Sequence { @usableFromInline internal var indexes: [Base.Index] + @inlinable internal init(_ combinations: Combinations) { self.base = combinations.base self.kRange = combinations.kRange ?? 0..<0 @@ -121,7 +122,7 @@ extension Combinations: Sequence { /// [2, 3, 4] * /// // Can't advance without needing to go past `base.endIndex`, /// // so the iteration is finished. - @usableFromInline + @inlinable internal mutating func advance() { /// Advances `kRange` by incrementing its `lowerBound` until the range is /// empty, when iteration is finished. diff --git a/Sources/Algorithms/Cycle.swift b/Sources/Algorithms/Cycle.swift index fe3c9661..41d298bd 100644 --- a/Sources/Algorithms/Cycle.swift +++ b/Sources/Algorithms/Cycle.swift @@ -14,7 +14,7 @@ public struct Cycle { /// The collection to repeat. public let base: Base - @usableFromInline + @inlinable internal init(base: Base) { self.base = base } @@ -29,7 +29,7 @@ extension Cycle: Sequence { @usableFromInline var current: Base.Index - @usableFromInline + @inlinable internal init(base: Base) { self.base = base self.current = base.startIndex diff --git a/Sources/Algorithms/Indexed.swift b/Sources/Algorithms/Indexed.swift index 09b3627e..d81c9a77 100644 --- a/Sources/Algorithms/Indexed.swift +++ b/Sources/Algorithms/Indexed.swift @@ -18,7 +18,7 @@ public struct Indexed { /// The base collection. public let base: Base - @usableFromInline + @inlinable internal init(base: Base) { self.base = base } diff --git a/Sources/Algorithms/Intersperse.swift b/Sources/Algorithms/Intersperse.swift index aa9a32a7..165881bf 100644 --- a/Sources/Algorithms/Intersperse.swift +++ b/Sources/Algorithms/Intersperse.swift @@ -18,7 +18,7 @@ public struct Intersperse { @usableFromInline internal let separator: Base.Element - @usableFromInline + @inlinable internal init(base: Base, separator: Base.Element) { self.base = base self.separator = separator @@ -37,7 +37,7 @@ extension Intersperse: Sequence { @usableFromInline internal var state = State.start - @usableFromInline + @inlinable internal init(iterator: Base.Iterator, separator: Base.Element) { self.iterator = iterator self.separator = separator @@ -89,6 +89,11 @@ extension Intersperse: Collection where Base: Collection { @usableFromInline internal let representation: Representation + @inlinable + init(representation: Representation) { + self.representation = representation + } + @inlinable public static func < (lhs: Index, rhs: Index) -> Bool { switch (lhs.representation, rhs.representation) { @@ -101,12 +106,12 @@ extension Intersperse: Collection where Base: Collection { } } - @usableFromInline + @inlinable static func element(_ index: Base.Index) -> Self { Self(representation: .element(index)) } - @usableFromInline + @inlinable static func separator(next: Base.Index) -> Self { Self(representation: .separator(next: next)) } diff --git a/Sources/Algorithms/LazySplit.swift b/Sources/Algorithms/LazySplit.swift index 5f6dae6e..9241e636 100644 --- a/Sources/Algorithms/LazySplit.swift +++ b/Sources/Algorithms/LazySplit.swift @@ -34,7 +34,7 @@ public struct LazySplitSequence { @usableFromInline internal let omittingEmptySubsequences: Bool - @usableFromInline + @inlinable internal init( base: Base, isSeparator: @escaping (Base.Element) -> Bool, @@ -72,7 +72,7 @@ extension LazySplitSequence { @usableFromInline internal var sequenceLength = 0 - @usableFromInline + @inlinable internal init( base: Base.Iterator, whereSeparator: @escaping (Base.Element) -> Bool, @@ -360,7 +360,7 @@ public struct LazySplitCollection { @usableFromInline internal var _startIndex: Index - @usableFromInline + @inlinable internal init( base: Base, isSeparator: @escaping (Base.Element) -> Bool, @@ -415,7 +415,7 @@ extension LazySplitCollection: LazyCollectionProtocol { @usableFromInline internal let splitCount: Int - @usableFromInline + @inlinable internal init( baseRange: Range, sequenceLength: Int, @@ -441,7 +441,7 @@ extension LazySplitCollection: LazyCollectionProtocol { /// Returns the index of the subsequence starting at or after the given base /// collection index. - @usableFromInline + @inlinable internal func indexForSubsequence( atOrAfter lowerBound: Base.Index, sequenceLength: Int, diff --git a/Sources/Algorithms/Partition.swift b/Sources/Algorithms/Partition.swift index af81eae4..66a0b011 100644 --- a/Sources/Algorithms/Partition.swift +++ b/Sources/Algorithms/Partition.swift @@ -21,7 +21,7 @@ extension MutableCollection { /// - Complexity: O(*n* log *n*), where *n* is the number of elements. /// - Precondition: /// `n == distance(from: range.lowerBound, to: range.upperBound)` - @usableFromInline + @inlinable internal mutating func stablePartition( count n: Int, subrange: Range, diff --git a/Sources/Algorithms/Permutations.swift b/Sources/Algorithms/Permutations.swift index 81f8f0d8..e34ecfaf 100644 --- a/Sources/Algorithms/Permutations.swift +++ b/Sources/Algorithms/Permutations.swift @@ -28,7 +28,7 @@ public struct Permutations { /// - base: The collection to iterate over for permutations /// - k: The expected size of each permutation, or `nil` (default) to /// iterate over all permutations of the same size as the base collection. - @usableFromInline + @inlinable internal init(_ base: Base, k: Int? = nil) { let kRange: ClosedRange? if let countToChoose = k { @@ -45,7 +45,7 @@ public struct Permutations { /// - base: The collection to iterate over for permutations. /// - kRange: The range of accepted sizes of permutations, or `nil` to /// iterate over all permutations of the same size as the base collection. - @usableFromInline + @inlinable internal init( _ base: Base, kRange: R? ) where R.Bound == Int { @@ -84,7 +84,7 @@ extension Permutations: Sequence { internal var kRange: Range /// Whether or not iteration is finished (`kRange` is empty) - @usableFromInline + @inlinable internal var isFinished: Bool { return kRange.isEmpty } @@ -92,7 +92,7 @@ extension Permutations: Sequence { @usableFromInline internal var indexes: [Base.Index] - @usableFromInline + @inlinable internal init(_ permutations: Permutations) { self.base = permutations.base self.baseCount = permutations.baseCount @@ -111,7 +111,7 @@ extension Permutations: Sequence { /// is in ascending order. /// /// - Complexity: O(*n*), where *n* is the length of the collection. - @usableFromInline + @inlinable internal mutating func nextState() -> Bool { let countToChoose = self.kRange.lowerBound let edge = countToChoose - 1 diff --git a/Sources/Algorithms/Product.swift b/Sources/Algorithms/Product.swift index 8b353ba8..870ee1b7 100644 --- a/Sources/Algorithms/Product.swift +++ b/Sources/Algorithms/Product.swift @@ -16,7 +16,7 @@ public struct Product2 { /// The inner sequence in the product. public let base2: Base2 - @usableFromInline + @inlinable internal init(_ base1: Base1, _ base2: Base2) { self.base1 = base1 self.base2 = base2 @@ -35,7 +35,7 @@ extension Product2: Sequence { @usableFromInline internal let base2: Base2 - @usableFromInline + @inlinable internal init(_ c: Product2) { self.base2 = c.base2 self.i1 = c.base1.makeIterator() @@ -90,7 +90,7 @@ extension Product2: Collection where Base1: Collection { @usableFromInline internal var i2: Base2.Index - @usableFromInline + @inlinable internal init(i1: Base1.Index, i2: Base2.Index) { self.i1 = i1 self.i2 = i2 @@ -128,7 +128,7 @@ extension Product2: Collection where Base1: Collection { /// Forms an index from a pair of base indices, normalizing /// `(i, base2.endIndex)` to `(base1.index(after: i), base2.startIndex)` if /// necessary. - @usableFromInline + @inlinable internal func normalizeIndex(_ i1: Base1.Index, _ i2: Base2.Index) -> Index { i2 == base2.endIndex ? Index(i1: base1.index(after: i1), i2: base2.startIndex) @@ -195,6 +195,7 @@ extension Product2: Collection where Base1: Collection { } } + @inlinable public func index(_ i: Index, offsetBy distance: Int) -> Index { guard distance != 0 else { return i } @@ -203,6 +204,7 @@ extension Product2: Collection where Base1: Collection { : offsetBackward(i, by: -distance) } + @inlinable public func index( _ i: Index, offsetBy distance: Int, @@ -219,21 +221,21 @@ extension Product2: Collection where Base1: Collection { } } - @usableFromInline + @inlinable internal func offsetForward(_ i: Index, by distance: Int) -> Index { guard let index = offsetForward(i, by: distance, limitedBy: endIndex) else { fatalError("Index is out of bounds") } return index } - @usableFromInline + @inlinable internal func offsetBackward(_ i: Index, by distance: Int) -> Index { guard let index = offsetBackward(i, by: distance, limitedBy: startIndex) else { fatalError("Index is out of bounds") } return index } - @usableFromInline + @inlinable internal func offsetForward( _ i: Index, by distance: Int, limitedBy limit: Index ) -> Index? { @@ -311,7 +313,7 @@ extension Product2: Collection where Base1: Collection { .map { i2 in Index(i1: i1, i2: i2) } } - @usableFromInline + @inlinable internal func offsetBackward( _ i: Index, by distance: Int, limitedBy limit: Index ) -> Index? { diff --git a/Sources/Algorithms/Rotate.swift b/Sources/Algorithms/Rotate.swift index 08799ed6..094b1d9d 100644 --- a/Sources/Algorithms/Rotate.swift +++ b/Sources/Algorithms/Rotate.swift @@ -29,7 +29,7 @@ extension MutableCollection where Self: BidirectionalCollection { /// /// - Postcondition: For returned indices `(lower, upper)`: /// `lower == limit || upper == limit` - @usableFromInline + @inlinable @discardableResult internal mutating func _reverse( subrange: Range, until limit: Index @@ -94,7 +94,7 @@ extension MutableCollection { /// - distance(from: lhs.lowerBound, to: p) == distance(from: /// rhs.lowerBound, to: q) /// - p == lhs.upperBound || q == rhs.upperBound - @usableFromInline + @inlinable internal mutating func _swapNonemptySubrangePrefixes( _ lhs: Range, _ rhs: Range ) -> (Index, Index) { diff --git a/Sources/Algorithms/Stride.swift b/Sources/Algorithms/Stride.swift index a4ce4a15..347825b8 100644 --- a/Sources/Algorithms/Stride.swift +++ b/Sources/Algorithms/Stride.swift @@ -61,7 +61,7 @@ public struct StrideSequence: Sequence { @usableFromInline internal let stride: Int - @usableFromInline + @inlinable internal init(base: Base, stride: Int) { precondition(stride > 0, "striding must be greater than zero") self.base = base @@ -82,7 +82,7 @@ extension StrideSequence { @usableFromInline internal var striding: Bool = false - @usableFromInline + @inlinable internal init(iterator: Base.Iterator, stride: Int) { self.iterator = iterator self.stride = stride @@ -122,7 +122,7 @@ public struct StrideCollection { @usableFromInline internal let stride: Int - @usableFromInline + @inlinable internal init(base: Base, stride: Int) { precondition(stride > 0, "striding must be greater than zero") self.base = base @@ -190,7 +190,7 @@ extension StrideCollection: Collection { : offsetBackward(i, offsetBy: -n, limitedBy: limit) } - @usableFromInline + @inlinable internal func offsetForward( _ i: Index, offsetBy n: Int, @@ -220,7 +220,7 @@ extension StrideCollection: Collection { } } - @usableFromInline + @inlinable internal func offsetBackward( _ i: Index, offsetBy n: Int, diff --git a/Sources/Algorithms/Windows.swift b/Sources/Algorithms/Windows.swift index 8a2ac191..03f9fad6 100644 --- a/Sources/Algorithms/Windows.swift +++ b/Sources/Algorithms/Windows.swift @@ -53,7 +53,7 @@ public struct Windows { @usableFromInline internal var firstUpperBound: Base.Index? - @usableFromInline + @inlinable internal init(base: Base, size: Int) { precondition(size > 0, "Windows size must be greater than zero") self.base = base @@ -72,7 +72,7 @@ extension Windows: Collection { @usableFromInline internal var upperBound: Base.Index - @usableFromInline + @inlinable internal init(lowerBound: Base.Index, upperBound: Base.Index) { self.lowerBound = lowerBound self.upperBound = upperBound @@ -150,21 +150,21 @@ extension Windows: Collection { } } - @usableFromInline + @inlinable internal func offsetForward(_ i: Index, by distance: Int) -> Index { guard let index = offsetForward(i, by: distance, limitedBy: endIndex) else { fatalError("Index is out of bounds") } return index } - @usableFromInline + @inlinable internal func offsetBackward(_ i: Index, by distance: Int) -> Index { guard let index = offsetBackward(i, by: distance, limitedBy: startIndex) else { fatalError("Index is out of bounds") } return index } - @usableFromInline + @inlinable internal func offsetForward( _ i: Index, by distance: Int, limitedBy limit: Index ) -> Index? { @@ -235,7 +235,7 @@ extension Windows: Collection { } } - @usableFromInline + @inlinable internal func offsetBackward( _ i: Index, by distance: Int, limitedBy limit: Index ) -> Index? {