[stdlib] Update complexity docs for seq/collection algorithms (#17254)

* [stdlib] Update complexity docs for seq/collection algorithms

This corrects and standardizes the complexity documentation for Sequence
and Collection methods. The use of constants is more consistent, with `n`
equal to the length of the target collection, `m` equal to the length of
a collection passed in as a parameter, and `k` equal to any other passed
or calculated constant.

* Apply notes from @brentdax about complexity nomenclature

* Change `n` to `distance` in `index(_:offsetBy:)`

* Use equivalency language more places; sync across array types

* Use k instead of n for parameter names

* Slight changes to index(_:offsetBy:) discussion.

* Update tests with new parameter names
This commit is contained in:
Nate Cook
2018-07-24 01:01:34 -05:00
committed by GitHub
parent 0abb019ddf
commit 3d7dfc232b
16 changed files with 551 additions and 392 deletions

View File

@@ -85,6 +85,8 @@ where SubSequence: RandomAccessCollection, Indices: RandomAccessCollection
///
/// - Parameter bounds: A range of the collection's indices. The bounds of
/// the range must be valid indices of the collection.
///
/// - Complexity: O(1)
subscript(bounds: Range<Index>) -> SubSequence { get }
// FIXME(ABI): Associated type inference requires this.
@@ -97,9 +99,6 @@ where SubSequence: RandomAccessCollection, Indices: RandomAccessCollection
var endIndex: Index { get }
}
// TODO: swift-3-indexing-model - Make sure RandomAccessCollection has
// documented complexity guarantees, e.g. for index(_:offsetBy:).
// TODO: swift-3-indexing-model - (By creating an ambiguity?), try to
// make sure RandomAccessCollection models implement
// index(_:offsetBy:) and distance(from:to:), or they will get the
@@ -130,31 +129,32 @@ extension RandomAccessCollection {
/// print(j)
/// // Prints "nil"
///
/// The value passed as `n` must not offset `i` beyond the bounds of the
/// collection, unless the index passed as `limit` prevents offsetting
/// The value passed as `distance` must not offset `i` beyond the bounds of
/// the collection, unless the index passed as `limit` prevents offsetting
/// beyond those bounds.
///
/// - Parameters:
/// - i: A valid index of the array.
/// - n: The distance to offset `i`.
/// - limit: A valid index of the collection to use as a limit. If `n > 0`,
/// `limit` should be greater than `i` to have any effect. Likewise, if
/// `n < 0`, `limit` should be less than `i` to have any effect.
/// - Returns: An index offset by `n` from the index `i`, unless that index
/// would be beyond `limit` in the direction of movement. In that case,
/// the method returns `nil`.
/// - distance: The distance to offset `i`.
/// - limit: A valid index of the collection to use as a limit. If
/// `distance > 0`, `limit` should be greater than `i` to have any
/// effect. Likewise, if `distance < 0`, `limit` should be less than `i`
/// to have any effect.
/// - Returns: An index offset by `distance` from the index `i`, unless that
/// index would be beyond `limit` in the direction of movement. In that
/// case, the method returns `nil`.
///
/// - Complexity: O(1)
@inlinable
public func index(
_ i: Index, offsetBy n: Int, limitedBy limit: Index
_ i: Index, offsetBy distance: Int, limitedBy limit: Index
) -> Index? {
// FIXME: swift-3-indexing-model: tests.
let l = distance(from: i, to: limit)
if n > 0 ? l >= 0 && l < n : l <= 0 && n < l {
let l = self.distance(from: i, to: limit)
if distance > 0 ? l >= 0 && l < distance : l <= 0 && distance < l {
return nil
}
return index(i, offsetBy: n)
return index(i, offsetBy: distance)
}
}
@@ -214,21 +214,22 @@ where Index : Strideable,
/// print(numbers[i])
/// // Prints "50"
///
/// The value passed as `n` must not offset `i` beyond the bounds of the
/// collection.
/// The value passed as `distance` must not offset `i` beyond the bounds of
/// the collection.
///
/// - Parameters:
/// - i: A valid index of the collection.
/// - n: The distance to offset `i`.
/// - Returns: An index offset by `n` from the index `i`. If `n` is positive,
/// this is the same value as the result of `n` calls to `index(after:)`.
/// If `n` is negative, this is the same value as the result of `-n` calls
/// to `index(before:)`.
/// - distance: The distance to offset `i`.
/// - Returns: An index offset by `distance` from the index `i`. If
/// `distance` is positive, this is the same value as the result of
/// `distance` calls to `index(after:)`. If `distance` is negative, this
/// is the same value as the result of `abs(distance)` calls to
/// `index(before:)`.
///
/// - Complexity: O(1)
@inlinable
public func index(_ i: Index, offsetBy n: Index.Stride) -> Index {
let result = i.advanced(by: n)
public func index(_ i: Index, offsetBy distance: Index.Stride) -> Index {
let result = i.advanced(by: distance)
// This range check is not precise, tighter bounds exist based on `n`.
// Unfortunately, we would need to perform index manipulation to
// compute those bounds, which is probably too slow in the general