1
1
mirror of https://github.com/github/semantic.git synced 2024-12-29 01:42:43 +03:00
semantic/prototype/Doubt/Matrix.swift

56 lines
1.7 KiB
Swift
Raw Normal View History

2015-10-06 19:19:59 +03:00
/// A two-dimensional matrix of memoized values.
///
/// These values are populated by a function from the coordinates of a given cell to the matrixs element type.
///
/// Values are retrieved by subscripting with row/column indices. Out-of-bound indices produce `nil` values, rather than asserting.
2015-11-05 23:51:15 +03:00
public struct Matrix<A, I: ForwardIndexType> {
public init(across: Range<I>, down: Range<I>, compute: (I, I) -> A) {
self.init(across: across, down: down, values: constructRowMajor(across, down: down, forEach: { i, j in Memo { compute(i, j) } }))
}
2015-11-05 23:51:15 +03:00
public let across: Range<I>
public let down: Range<I>
2015-10-06 00:11:56 +03:00
2015-11-12 23:26:50 +03:00
private let width: I.Distance
2015-10-06 20:00:01 +03:00
private let values: [Memo<A>]
2015-10-06 00:11:56 +03:00
2015-11-05 23:51:15 +03:00
public subscript (i: I, j: I) -> Memo<A>? {
guard i != across.endIndex && j != down.endIndex else { return nil }
2015-11-05 23:51:15 +03:00
let i = across.startIndex.distanceTo(i)
let j = down.startIndex.distanceTo(j)
2015-11-12 23:26:50 +03:00
return values[Int((i + j * width).toIntMax())]
2015-10-06 00:11:56 +03:00
}
2015-10-06 00:18:40 +03:00
// MARK: Functor
2015-11-05 23:51:15 +03:00
public func map<Other>(transform: A -> Other) -> Matrix<Other, I> {
return Matrix<Other, I>(across: across, down: down, values: values.map { $0.map(transform) })
2015-10-06 00:18:40 +03:00
}
// MARK: Implementation details
2015-11-05 23:51:15 +03:00
private init(across: Range<I>, down: Range<I>, values: [Memo<A>]) {
self.across = across
self.down = down
self.values = values
2015-11-12 23:26:50 +03:00
self.width = across.count
}
2015-10-06 00:11:56 +03:00
}
2015-10-06 21:17:14 +03:00
/// Constructs a row-major ordering of values produced with `forEach`.
private func constructRowMajor<A, I: ForwardIndexType>(across: Range<I>, down: Range<I>, @noescape forEach: (I, I) -> A) -> [A] {
var values: [A] = []
values.reserveCapacity(Int(across.count.toIntMax()) * Int(down.count.toIntMax()))
for j in down {
for i in across {
values.append(forEach(i, j))
}
}
return values
}
2015-10-13 07:51:43 +03:00
import Memo