Skip to content

Instantly share code, notes, and snippets.

@wircho
Last active August 3, 2016 18:31
Show Gist options
  • Save wircho/a78e4137cdac1e79e7aa6d4da65f6ab9 to your computer and use it in GitHub Desktop.
Save wircho/a78e4137cdac1e79e7aa6d4da65f6ab9 to your computer and use it in GitHub Desktop.
A type-safe wrapper for existing matrix types.
/*
* SafeMatrix.swift
*/
// MARK: Convenience types and functions
public typealias MatrixDimensions = (rows:UInt,columns:UInt)
public typealias MatrixIndex = (i:UInt,j:UInt)
public func ==(lhs:MatrixDimensions,rhs:MatrixDimensions) -> Bool {
return lhs.rows == rhs.rows && lhs.columns == rhs.columns
}
private func enforceDimensions(got:MatrixDimensions,expected:MatrixDimensions) throws {
guard got == expected else {
throw SafeMatrixError.BadDimensions(got:got, expected: expected)
}
}
private func enforceIndex(index:MatrixIndex,dimensions:MatrixDimensions) throws {
guard index.i >= 0 && index.i < dimensions.rows && index.j >= 0 && index.j < dimensions.columns else {
throw SafeMatrixError.OutOfBounds(index: index, dimensions: dimensions)
}
}
// MARK: Error types
public enum SafeMatrixError: ErrorType {
case BadDimensions(got:MatrixDimensions,expected:MatrixDimensions)
case OutOfBounds(index:MatrixIndex,dimensions:MatrixDimensions)
}
// MARK: UnsafeMatrixProtocol
public protocol UnsafeMatrixProtocol {
associatedtype Scalar
subscript(_:UInt,_:UInt) -> Scalar { get set }
var dimensions:MatrixDimensions { get }
}
// MARK: NumeralProtocol
public protocol NumeralProtocol {
static var value:UInt { get }
}
// MARK: SafeMatrixProtocol
public protocol SafeMatrixProtocol {
associatedtype MatrixType:UnsafeMatrixProtocol
associatedtype Rows:NumeralProtocol
associatedtype Columns:NumeralProtocol
var matrix:MatrixType { get set }
init(matrix:MatrixType) throws
}
// Dimensions
extension SafeMatrixProtocol {
static var staticDimensions:MatrixDimensions {
return (Rows.value,Columns.value)
}
var dimensions:MatrixDimensions {
return Self.staticDimensions
}
}
// Access
extension SafeMatrixProtocol {
func get(i i:UInt,j:UInt) throws -> MatrixType.Scalar {
try enforceIndex((i,j), dimensions: dimensions)
return matrix[i,j]
}
mutating func set(i i:UInt,j:UInt,value:MatrixType.Scalar) throws {
try enforceIndex((i,j), dimensions: dimensions)
matrix[i,j] = value
}
}
// MARK: SafeMatrix
public struct SafeMatrix<MatrixType:UnsafeMatrixProtocol,RowsType:NumeralProtocol,ColumnsType:NumeralProtocol>
: SafeMatrixProtocol {
public typealias Rows = RowsType
public typealias Columns = ColumnsType
public var matrix:MatrixType {
willSet {
try! enforceDimensions(matrix.dimensions, expected: dimensions)
}
}
public init(matrix:MatrixType) throws {
try enforceDimensions(matrix.dimensions, expected: SafeMatrix.staticDimensions)
self.matrix = matrix
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment