/// A two-dimensional matrix of memoized values.
///
/// These values are populated by a function from the coordinates of a given cell to the matrix’s element type.
///
/// Values are retrieved by subscripting with row/column indices. Out-of-bound indices produce `nil` values, rather than asserting.
public struct Matrix {
public init(width: Int, height: Int, compute: (Int, Int) -> A) {
self.init(width: width, height: height, values: constructRowMajor(width, height: height, forEach: { i, j in Memo { compute(i, j) } }))
}
public let width: Int
public let height: Int
private let values: [Memo]
public subscript (i: Int, j: Int) -> Memo? {
guard i < width && j < height else { return nil }
return values[i + j * width]
}
// MARK: Functor
public func map(transform: A -> Other) -> Matrix {
return Matrix(width: width, height: height, values: values.map { $0.map(transform) })
}
// MARK: Implementation details
private init(width: Int, height: Int, values: [Memo]) {
self.width = width
self.height = height
self.values = values
}
}
/// Constructs a row-major ordering of values produced with `forEach`.
private func constructRowMajor(width: Int, height: Int, @noescape forEach: (Int, Int) -> A) -> [A] {
var values: [A] = []
values.reserveCapacity(width * height)
for j in 0..